Use low-level discovery as much as possible. This helps to avoid unsupported items as well as to improve templates flexibility.
Good | Bad |
---|---|
Discovering temperature sensors using LLD Discovering network interface using LLD Discovering CPU cores using LLD |
CPU core #1 utilization, Sensor 1 temperature value, network interface Fa0/0 directly by statically creating items without using LLD |
Choose a simple, descriptive name for each discovery rule. Make sure it always ends with the “discovery” word.
Good | Bad |
---|---|
Network interface discovery CPU core discovery |
Network Discovery of CPU cores |
Items, triggers, graphs names generated from LLD should be prefixed with the discovery entity name they belong to. The only exception is the singleton discovery pattern.
Low-level discovery is considered a heavy operation in Zabbix, so its frequency should be low. Consider always starting at 1 per hour.
If discovery uses another frequent item as a source (Item type = dependent item) - apply “Discard unchanged with heartbeat” preprocessing for such discovery. You can also use such preprocessing for other discoveries too.
In such case, you can also use discovery preprocessing to filter out toggling parts of the low-level discovery data, for example, for data coming from master item:
[
{
“volume_name”: “my disk1”,
“volume_size”: 1000000000000,
“volume_used”: 800000000000,
“volume_updated_at”: “2019-07-01 00:00:00”
},
{
“volume_name”: “my disk2”,
“volume_size”: 1000000000000,
“volume_used”: 800000000000,
“volume_updated_at”: “2019-07-01 00:00:00”
}
]
For such output consider transforming this array using JS or JSONPath preprocessing to:
Before applying throttling discard rule.
Keep it to default: 30d.
Use user macros in filters
Consider using user macros in filters, two for each useful LLD macro.
Good | Bad |
---|---|
{#IFNAME} MATCHES {$NET.IF.IFNAME.MATCHES} {#IFNAME} NOT_MATCHES {$NET.IF.IFNAME.NOT_MATCHES} .. {#IFTYPE} MATCHES {$NET.IF. IFTYPE.MATCHES} {#IFTYPE} NOT_MATCHES {$NET.IF.IFTYPE.NOT_MATCHES} Where: {$NET.IF.IFNAME.MATCHES} = ^.*$ {$NET.IF.IFNAME.NOT_MATCHES} = (^Software Loopback Interface|^NULL[0-9.]*$| ^[Ll]o[0-9.]*$| ^[Ss]ystem$|^Nu[0-9.]*$) And {$NET.IF. IFTYPE.MATCHES} = ^.*$ {$NET.IF. IFTYPE.NOT_MATCHES} = CHANGE_IF_NEEDED |
{#IFNAME} MATCHES "@Network interfaces for discovery" |
That way, filters can be redefined on a linked template or host level without changing the template itself.
SNMP
When discovering SNMP OIDs, make sure to use regexes that match both MIB translated values and raw values. This would make discovery filters even if proper MIBs are not loaded into Zabbix server or proxy.
For example, filter for discovering disks when you need to discover only disks of resource type = hrStorageFixedDisk (1.3.6.1.2.1.25.2.1.4)
Good | Bad |
---|---|
MATCHES .*(\.4|hrStorageFixedDisk)$ | MATCHES .*(hrStorageFixedDisk)$ |
LLD items and triggers should contain the same tags as regular items and triggers, but LLD items may have additional custom tags with LLD macros.
For example, the low-level discovery item Interface {#IFNAME}({#IFALIAS}): Operational status might contain the following tags:
Where applicable, configure LLD host discovery rule to assign the host tag service to discovered hosts to specify resource references.
For example, discovered hosts "load_balancer", "web01", "web02", "webforum" should all contains the following tag:
When pushing items via Zabbix trapper protocol – consider pushing low-level discovery data as well since discovery items support it.
With JavaScript preprocessing and other powerful features, you can create low-level discovery data on the fly. Prefer this method over external discovery scripts:
Example 1
Get Nginx Plus zones stats using Zabbix HTTP agent from URL such as this: http://demo.nginx.com/api/3/http/server_zones
{
"hg.nginx.org": {
"processing": 0,
"requests": 175276,
"responses": {
"1xx": 0,
"2xx": 162948,
"3xx": 10117,
"4xx": 2125,
"5xx": 8,
"total": 175198
},
"discarded": 78,
"received": 50484208,
"sent": 7356417338
},
"trac.nginx.org": {
"processing": 7,
"requests": 448613,
"responses": {
"1xx": 0,
"2xx": 305562,
"3xx": 87065,
"4xx": 23136,
"5xx": 5127,
"total": 420890
},
"discarded": 27716,
"received": 137307886,
"sent": 3989556941
}
}
Feed this output to discovery rule via dependent item and apply Javascript preprocessing as this:
//parsing NGINX plus output:
output = Object.keys(JSON.parse(value)).map(function(zone){
return {"{#NGINX_ZONE}": zone}
})
return JSON.stringify({"data": output})
Making original JSON object a fully LLD compatible JSON Array that can be used for NGINX zones discovery.
Example 2
Get disks stats using Zabbix agent vfs.file.contents[/proc/diskstats] item:
7 0 loop0 2 0 10 0 0 0 0 0 0 0 0
7 1 loop1 0 0 0 0 0 0 0 0 0 0 0
7 2 loop2 0 0 0 0 0 0 0 0 0 0 0
7 3 loop3 0 0 0 0 0 0 0 0 0 0 0
7 4 loop4 0 0 0 0 0 0 0 0 0 0 0
7 5 loop5 0 0 0 0 0 0 0 0 0 0 0
7 6 loop6 0 0 0 0 0 0 0 0 0 0 0
7 7 loop7 0 0 0 0 0 0 0 0 0 0 0
8 0 sda 192218 21315 11221888 13020540 28630719 8482221 801446972 388811708 0 265066852 401774948
8 1 sda1 252 59 11294 5424 6 0 12 464 0 4160 5888
8 2 sda2 4 0 8 72 0 0 0 0 0 72 72
8 5 sda5 191918 21256 11208378 13014352 22872982 8482221 801446960 215739516 0 99497600 228699704
252 0 dm-0 186763 0 10985130 22979168 31930494 0 799946248 396490524 0 265080476 419505356
252 1 dm-1 26897 0 220608 688352 187589 0 1500712 23501956 0 212608 24190464
Feed this output to a regular item and then apply preprocessing as this:
JAVASCRIPT
var parsed = value.split("\n").reduce(function(acc, x, i) {
acc["values"][x.split(/ +/)[3]] = x.split(/ +/).slice(1)
acc["lld"].push({"{#DEVNAME}":x.split(/ +/)[3]});
return acc;
}, {"values":{}, "lld": []});
return JSON.stringify(parsed);
Create new discovery rule with the item above as the master item. Apply additional preprocessing to this discovery rule:
JSONPATH
While the low-level discovery was designed to automate the creation of items, triggers, and graphs for multiple similar entities such as network interfaces or disks, it can also be used as a simple filter for exclusive entities that either don’t exist or exist in the single instance.
This approach allows keeping a template clean, without users facing unsupported items when a template is applied to hosts with different configurations or versions of the monitored object.
To use singleton pattern, you need to do the following:
These two steps can be combined in a single line of JavaScript that would generate an LLD array.
Use this macro {#SINGLETON} inside square brackets of all item prototypes keys.
Append this macro to any graph prototype name.
Empty macro is required, so Zabbix can differentiate item or graph from the prototype. When macro is expanded after discovery - only clean item name or graph name can be seen absolutely identical to the one that you would statically define.
See MPM event discovery in Zabbix 4.4 “Template App Apache by HTTP” template as an example. We will also describe it in more detail in our blog.
Good | Bad |
---|---|
MPM event singleton discovery in Template App Apache by HTTP (Zabbix 4.4) | Templates that monitor Apache HTTP server without such Singleton approach, thus leaving MPM event metrics as not supported when MPM event module is disabled |
There is a constraint that LLD macro must be inside square brackets in item key.