Skip to content

Latest commit

 

History

History
322 lines (250 loc) · 11.7 KB

README.md

File metadata and controls

322 lines (250 loc) · 11.7 KB

check-mqtt

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.

Prerequisite

This module can use jsonpath-rw. To install, use $ pip install jsonpath-rw

Configuration

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 on topic.
subscription
topic to use for the passive check - read only. If subscription is not given it will be set to topic
readonly
just read on subscription, do not publish any payload on topic
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 and operator 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 like str(), 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

Examples

simple

./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

Status check

./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

Ping Pong check

./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

Jsonpath check

./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

Nagios Configuration

command definition

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
        }

icinga2 command definition


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"
    }
  }
}


service definition

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
        }
        

icinga2 host definition

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"
}

icinga2 service definition

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
}