A Nagios/Icinga plugin for checking connectivity to an MQTT broker. Or with --readonly monitor an mqtt application. Or for checking the status of MQTT clients maintaining the status on an MQTT broker.
This plugin connects to the specified broker and subscribes to a topic. Upon successful subscription, a message is published to said topic, and the plugin expects to receive that payload within max_wait
seconds.
This module can use jsonpath-rw. To install, use $ pip install jsonpath-rw
Configuration can be done via the following command line arguments:
usage: check-mqtt.py [-h] [-d|--debug] [-H <hostname>] [-P <port>] [-u <username>]
[-p <password>] [-m <seconds>] [-e <seconds>]
[--sleep <seconds>] [-a <cafile>] [-C <certfile>]
[-k <keyfile>] [-n] [-t <topic>] [-s <subscription>] [-r]
[-l <payload>] [-j <jsonpath>] [-v <value>]
[-o <operator>] [-w <expr>] [-c <expr>] [-S] [-V]
Nagios/Icinga plugin for checking connectivity or status of MQTT clients on an
MQTT broker.
optional arguments:
-h, --help show this help message and exit
-d, --debug enable MQTT logging
-H <hostname>, --host <hostname>
mqtt host to connect to (default: 'localhost')
-P <port>, --port <port>
network port to connect to (default: 1883)
-u <username>, --username <username>
MQTT username (default: None)
-p <password>, --password <password>
MQTT password (default: None)
-m <seconds>, --max-wait <seconds>
maximum time to wait for the check (default: 4
seconds)
-e <seconds>, --keepalive <seconds>
maximum period in seconds allowed between
communications with the broker (default: 60 seconds)
--sleep <seconds> main loop sleep period in seconds (default: 0.1
seconds)
-a <cafile>, --cafile <cafile>
cafile (default: None)
-C <certfile>, --certfile <certfile>
certfile (default: None)
-k <keyfile>, --keyfile <keyfile>
keyfile (default: None)
-n, --insecure suppress TLS verification of server hostname
-t <topic>, --topic <topic>
topic to use for the active check (default:
'nagios/test')
-s <subscription>, --subscription <subscription>
topic to use for the passive check (default: 'None')
-r, --readonly just read the value of the topic
-l <payload>, --payload <payload>
payload which will be PUBLISHed (default: PiNG). If it
starts with an exclamation mark (!) the output of the
command will be used
-j <jsonpath>, --jsonpath <jsonpath>
if given, payload is interpreted as JSON string and
value is extracted using <jsonpath> (default: 'None')
-v <value>, --value <value>
value to compare against received payload (default:
'PiNG'). If it starts with an exclamation mark (!) the
output of the command will be used
-o <operator>, --operator <operator>
operator to compare received value with value. Choose
from ['eq', 'equal', 'lt', 'lessthan', 'gt',
'greaterthan', 'ct', 'contains'] (default: 'equal').
'eq' compares Strings, the other convert the arguments
to float before compare
-w <expr>, --warning <expr>
Exit with WARNING status if <expr> is true (default:
'None'). <expr> can be any Python expression, use
<payload> within expression for current payload value.
-c <expr>, --critical <expr>
Exit with CRITICAL status if <expr> is true (default:
'None'). <expr> can be any Python expression, use
<payload> within expression for current payload value.
-S, --short use a shorter string on output
-V, --version show program's version number and exit
There are no required arguments, defaults are displayed using --help
. If --warning
and/or --critical
is used then possible given --operator
and --value
arguments are ignored.
- hostname, port, username, password used to connect to a MQTT broker
- cafile certfile keyfile insecure optional used for an encrypted TLS connection, for details see mosquitto.conf - Certificate based SSL/TLS Support.
- max_wait
- is the time (integer) we're willing to wait for a SUB to the topic we PUBlish on. If we don't receive the MQTT PUB within this many seconds we exit with _CRITICAL_
- keepalive
- maximum period in seconds (integer) allowed between communications with the broker. If no other messages are being exchanged, this controls the rate at which the client will send ping messages to the broker
- sleep
- period in seconds (float) to sleep in main loop - may reduce cpu load if a lot of processes (>100) are running.
- topic
- topic where the
payload
will be published when we have received the subscribed message. - payload
payload
to publish ontopic
.- subscription
- topic to use for the passive check - read only. If
subscription
is not given it will be set totopic
- readonly
- just read on
subscription
, do not publish anypayload
ontopic
- jsonpath
- a JSONPath expression refering to a JSON structure (for JSONPath syntax see JSONPath expressions)
- value, operator
value
to compare against received payload. The comparison is done using one of the listed (see help above) operators. The returned status is OK if the comparison is true, otherwise it will return CRITICAL. If -w (--warning) or -c (--critical) argument is used,value
andoperator
will be ignored.- warning, critical
- a warning and/or critical expression. Use the word
payload
within your formular to refer to the read payload value.
If both are given (warning and critical) the critical expression overrule the warning.<exp>
can be any valid pyhton expression inclusive build-in and standard library functions e. g. conversion likestr()
,float()
...
Using one of them a possible--value
and/or--operator
argument will be ignored. - short
- if set it will use a short string layout for returned message
./check-mqtt.py -H localhost -P 1883 -u user -p password -t nagios/test -m 10
OK - message from nagios/test at localhost in 0.00 | response_time=0.10 value=PiNG
./check-mqtt.py -H localhost -t devices/mydevice/lastevent -v '!expr `date +%s` - 216000' -r -o greaterthan
OK - message from devices/mydevice/lastevent at localhost in 0.05s | response_time=0.05 value=1472626997
./check-mqtt.py -H localhost -t nagios/ListenForPing -s nagios/PublishPongTo -l ping -v pong
OK - message from nagios/PublishPongTo at localhost in 0.05s | response_time=0.05 value=pong
./check-mqtt.py -H localhost -t devices/mydevice/sensor -v '950' -j '$.BME280.Pressure' -r -o greaterthan
OK - message from devices/mydevice/sensor at localhost in 0.06s | response_time=0.06 value=1005.0
Jsonpath check using range (warning if lower than 4° or higher than 28°, critical if minus or higher than 35°)
./check-mqtt.py -H localhost -t devices/mydevice/sensor -v '950' -j '$.BME280.Temperature' -r --warning 'payload < 4 or payload >28' --critical 'payload < 0 or payload >35'
OK - message from devices/mydevice/sensor at localhost in 0.06s | response_time=0.06 value=20.1
define command{
command_name check_mqtt
command_line $USER1$/check_mqtt
}
define command{
command_name check_myapplication
command_line $USER1$/check_mqtt -i pong -t mytopic/test/myapplication
}
object CheckCommand "check-mqtt" {
import "plugin-check-command"
command = [ PluginDir + "/check-mqtt.py" ] //constants.conf -> const PluginDir
arguments = {
"-H" = "$mqtt_host$"
"-u" = "$mqtt_user$"
"-p" = "$mqtt_password$"
"-P" = "$mqtt_port$"
"-a" = "$mqtt_cafile$"
"-c" = "$mqtt_certfile$"
"-k" = "$mqtt_keyfile$"
"-t" = "$mqtt_topic$"
"-m" = {
set_if = "$mqtt_max$"
value = "$mqtt_max$"
}
"-l" = "$mqtt_payload$"
"-v" = "$mqtt_value$"
"-o" = "$mqtt_operator$"
"-r" = {
set_if = "$mqtt_readonly$"
description = "Don't write."
}
"-n" = {
set_if = "$mqtt_insecure$"
description = "suppress TLS hostname check"
}
}
}
define service{
use local-service
host_name localhost
service_description mqtt broker
check_command check_mqtt
notifications_enabled 0
}
define service{
use local-service
host_name localhost
service_description check if myapplication is running
check_command check_myapplication
notifications_enabled 0
}
object Host "wemos1" {
import "generic-host"
check_command = "check-mqtt"
vars.homie = true
vars.lastevent = true
vars.mqtt_host = "localhost"
# vars.mqtt_port = 1883
# vars.mqtt_user = "user"
# vars.mqtt_password = "password"
# vars.mqtt_cafile = "cafile"
# vars.mqtt_certfile = "certfile"
# vars.mqtt_keyfile = "keyfile"
vars.mqtt_prefix = "devices/mydevice"
vars.mqtt_topic = vars.mqtt_prefix + "/$$online"
vars.mqtt_payload = "true"
vars.mqtt_value = "true"
vars.mqtt_operator = "equal"
vars.mqtt_readonly = true
vars.os = "Homie"
vars.sla = "24x7"
}
apply Service "mqtt-health" {
import "generic-service"
check_command = "check-mqtt"
assign where host.vars.mqtt == true
ignore where host.vars.no_health_check == true
}
apply Service "homie-health" {
import "generic-service"
check_command = "check-mqtt"
vars.mqtt_topic = host.vars.mqtt_prefix + "/$$online"
vars.mqtt_payload = "true"
vars.mqtt_value = "true"
vars.mqtt_operator = "equal"
vars.mqtt_readonly = true
assign where host.vars.homie == true
ignore where host.vars.no_health_check == true
}
apply Service "lastevent-health" {
import "generic-service"
check_command = "check-mqtt"
vars.mqtt_topic = host.vars.mqtt_prefix + "/lastevent"
vars.mqtt_payload = "true"
vars.mqtt_value = "!expr `date +%s` - 21600"
vars.mqtt_operator = "greaterthan"
vars.mqtt_readonly = true
assign where host.vars.lastevent == true
ignore where host.vars.no_health_check == true
}