-
New Feature Request
-
Resolution: Unresolved
-
Trivial
-
None
-
None
-
None
Hello
I am trying to create a MR but I don't know how to do it…
I would like to propose a new timer discovery rule in the systemd timer (from version 7.0.21) :
```
diff --git a/templates/app/systemd/template_app_systemd.yaml b/templates/app/systemd/template_app_systemd.yaml
index d4bb2df26c0..22e08e33b9c 100644
— a/templates/app/systemd/template_app_systemd.yaml
+++ b/templates/app/systemd/template_app_systemd.yaml
@@ -21,6 +21,180 @@ zabbix_export:
groups:
- name: Templates/Applications
discovery_rules:
+ - uuid: 7c72b62ff55d49a4a69a0b9d199ff522
+ name: Timer units discovery
+ key: systemd.timer.discovery
+ delay: 30m
+ filter:
+ evaltype: AND
+ conditions:
+ - macro: '{#TIMER.ACTIVESTATE}'
+ value: '{$SYSTEMD.ACTIVESTATE.TIMER.MATCHES}'
+ formulaid: A
+ - macro: '{#TIMER.ACTIVESTATE}'
+ value: '{$SYSTEMD.ACTIVESTATE.TIMER.NOT_MATCHES}'
+ operator: NOT_MATCHES_REGEX
+ formulaid: B
+ - macro: '{#TIMER.ID}'
+ value: '{$SYSTEMD.NAME.TIMER.MATCHES}'
+ formulaid: C
+ - macro: '{#TIMER.ID}'
+ value: '{$SYSTEMD.NAME.TIMER.NOT_MATCHES}'
+ operator: NOT_MATCHES_REGEX
+ formulaid: D
+ - macro: '{#TIMER.UNITFILESTATE}'
+ value: '{$SYSTEMD.UNITFILESTATE.TIMER.MATCHES}'
+ formulaid: E
+ - macro: '{#TIMER.UNITFILESTATE}'
+ value: '{$SYSTEMD.UNITFILESTATE.TIMER.NOT_MATCHES}'
+ operator: NOT_MATCHES_REGEX
+ formulaid: F
+ description: Discover systemd timer units and their details.
+ item_prototypes:
+ - uuid: 2fb2a5db32a84214ab4012926c790711
+ name: '{#TIMER.ID}: service active state'
+ type: DEPENDENT
+ key: systemd.service.active_state"{#TIMER.UNIT}"
+ delay: '0'
+ valuemap:
+ name: Unit Active State
+ preprocessing:
+ - type: JSONPATH
+ parameters:
+ - $.ActiveState.state
+ - type: DISCARD_UNCHANGED_HEARTBEAT
+ parameters:
+ - 30m
+ master_item:
+ key: systemd.unit.get"{#TIMER.UNIT}"
+ tags:
+ - tag: application
+ value: systemd
+ - tag: component
+ value: service
+ - tag: component
+ value: timer
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ trigger_prototypes:
+ - uuid: 46c1c02b69af4e4d93b5bda30461d7ff
+ expression: last(/Systemd by Zabbix agent 2/systemd.service.active_state"{#TIMER.UNIT}")=4 or last(/Systemd by Zabbix agent 2/systemd.service.active_state"{#TIMER.UNIT}")=0
+ name: 'Systemd: {#TIMER.ID}: last service run has failed'
+ priority: WARNING
+ manual_close: YES
+ tags:
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ - tag: scope
+ value: health
+ - uuid: 45aa4ff8a75e4f3dac2f698be53ec181
+ name: '{#TIMER.ID}: service last run duration'
+ type: DEPENDENT
+ key: systemd.service.last_run_duration"{#TIMER.UNIT}"
+ delay: '0'
+ units: s
+ preprocessing:
+ - type: JAVASCRIPT
+ parameters:
+ - |
+ data = JSON.parse(value);
+ if (data.InactiveExitTimestamp == 0 && data.InactiveEnterTimestampMonotonic == 0)
+ else if (data.InactiveExitTimestamp > data.InactiveEnterTimestamp)
{ + // the service is running + return Math.floor(Date.now() / 1000 - data.InactiveExitTimestamp / 1000000); + }+ // else if (data.InactiveExitTimestamp <= data.InactiveEnterTimestamp)
+ // the service is not running and had run
+ return Math.floor((data.InactiveEnterTimestamp - data.InactiveExitTimestamp) / 1000000);
+ master_item:
+ key: systemd.unit.get"{#TIMER.UNIT}"
+ tags:
+ - tag: application
+ value: systemd
+ - tag: component
+ value: timer
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ trigger_prototypes:
+ - uuid: f8e978a86c9645639ec9786f3daedb9c
+ expression: last(/Systemd by Zabbix agent 2/systemd.service.last_run_duration"{#TIMER.UNIT}")>{$SYSTEMD.TIMER.DURATION_THRESHOLD:"
+ name: 'Systemd: {#TIMER.ID}: current/last service execution take/took too long'
+ priority: WARNING
+ manual_close: YES
+ tags:
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ - tag: scope
+ value: health
+ - uuid: 49091846ce384572925f94d7e3a4ef6b
+ name: '{#TIMER.ID}: time since last service start'
+ type: DEPENDENT
+ key: systemd.service.time_since_last_start"{#TIMER.UNIT}"
+ delay: '0'
+ units: s
+ preprocessing:
+ - type: JAVASCRIPT
+ parameters:
+ - |
+ data = JSON.parse(value);
+ if (data.InactiveExitTimestamp == 0 && data.InactiveEnterTimestampMonotonic == 0) { + // the service was never started + return Math.floor(Date.now() / 1000); + }
+ return Math.floor(Date.now() / 1000 - data.InactiveExitTimestamp / 1000000);
+ master_item:
+ key: systemd.unit.get"{#TIMER.UNIT}"
+ tags:
+ - tag: application
+ value: systemd
+ - tag: component
+ value: timer
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ trigger_prototypes:
+ - uuid: 608372ef501341e880ce7db2b351bcb9
+ expression: last(/Systemd by Zabbix agent 2/systemd.service.time_since_last_start"{#TIMER.UNIT}")>{$SYSTEMD.TIMER.LAST_START_THRESHOLD:"{#TIMER.ID}
"}
+ name: 'Systemd: {#TIMER.ID}: current/last service execution is too old'
+ priority: WARNING
+ manual_close: YES
+ tags:
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
+ - tag: scope
+ value: health
+ - uuid: 9599a8578b9f4db796a41e235d77c566
+ name: '{#TIMER.ID}: Get associated service unit info'
+ key: systemd.unit.get"{#TIMER.UNIT}"
+ history: '0'
+ value_type: TEXT
+ trends: '0'
+ description: Returns all properties of a systemd timer associated service unit.
+ tags:
+ - tag: application
+ value: systemd
+ - tag: component
+ value: raw
+ - tag: component
+ value: timer
+ - tag: component
+ value: '{#TIMER.ID}'
+ - tag: component
+ value: '{#TIMER.UNIT}'
- uuid: 0dfbc5994c1e44a6a1a2aa8ecc2f0347
name: 'Service units discovery'
key: 'systemd.unit.discovery[service]'
@@ -264,6 +438,12 @@ zabbix_export:
- macro: '{$SYSTEMD.ACTIVESTATE.SOCKET.NOT_MATCHES}'
value: ^inactive$
description: 'Filter of systemd socket units by active state.'
+ - macro: '{$SYSTEMD.ACTIVESTATE.TIMER.MATCHES}'
+ value: active
+ description: 'Filter of systemd timer units by active state'
+ - macro: '{$SYSTEMD.ACTIVESTATE.TIMER.NOT_MATCHES}'
+ value: CHANGE_IF_NEEDED
+ description: 'Filter of systemd timer units by active state'
- macro: '{$SYSTEMD.NAME.SERVICE.MATCHES}'
value: .+
description: 'Filter of systemd service units by name.'
@@ -276,6 +456,18 @@ zabbix_export:
- macro: '{$SYSTEMD.NAME.SOCKET.NOT_MATCHES}'
value: CHANGE_IF_NEEDED
description: 'Filter of systemd socket units by name.'
+ - macro: '{$SYSTEMD.NAME.TIMER.MATCHES}'
+ value: CHANGE_IF_NEEDED
+ description: Filter of systemd timer units by name
+ - macro: '{$SYSTEMD.NAME.TIMER.NOT_MATCHES}'
+ value: CHANGE_IF_NEEDED
+ description: Filter of systemd timer units by name
+ - macro: '{$SYSTEMD.TIMER.DURATION_THRESHOLD}'
+ value: '1800'
+ description: systemd timer maximum duration
+ - macro: '{$SYSTEMD.TIMER.LAST_START_THRESHOLD}'
+ value: '90000'
+ description: systemd timer maximum time since last start
- macro: '{$SYSTEMD.UNITFILESTATE.SERVICE.MATCHES}'
value: ^enabled$
description: 'Filter of systemd service units by unit file state.'
@@ -288,6 +480,12 @@ zabbix_export:
- macro: '{$SYSTEMD.UNITFILESTATE.SOCKET.NOT_MATCHES}'
value: CHANGE_IF_NEEDED
description: 'Filter of systemd socket units by unit file state.'
+ - macro: '{$SYSTEMD.UNITFILESTATE.TIMER.MATCHES}'
+ value: enabled|static
+ description: Filter of systemd timer units by unit file state
+ - macro: '{$SYSTEMD.UNITFILESTATE.TIMER.NOT_MATCHES}'
+ value: CHANGE_IF_NEEDED
+ description: Filter of systemd timer units by unit file state
dashboards:
- uuid: 35c40e164dc64c3997206b042a49f5c4
name: 'Systemd: Overview'
```
This discovery rule need a new key which is currently created via a UserParameter :
```
UserParameter=systemd.timer.discovery,/etc/zabbix/scripts/systemd/timer_discovery.py
```
`/etc/zabbix/scripts/systemd/timer_discovery.py` :
```
#!/usr/bin/python3
import json
import subprocess
cmd = ["/usr/bin/systemctl",
"show",
"-p",
"Id,Unit,ActiveState,UnitFileState",
"*.timer"]
cmd = subprocess.run(cmd, check=True, encoding="utf-8", stdout=subprocess.PIPE)
macro_names =
',
'Unit': '{#TIMER.UNIT}',
'ActiveState': '{#TIMER.ACTIVESTATE}',
'UnitFileState': '{#TIMER.UNITFILESTATE}'
}
timer_service_mapping = []
timer_service_current = {}
for line in cmd.stdout.splitlines():
if (not line) and timer_service_current:
timer_service_mapping.append(timer_service_current)
timer_service_current = {}
continue
line_partition = line.partition("=")
assert line_partition[1] == "="
timer_service_current[macro_names[line_partition[0]]] = line_partition[2]
if timer_service_current:
timer_service_mapping.append(timer_service_current)
print(json.dumps(timer_service_mapping))
```
What do you think of it ?
Regards