Skip to content

Instantly share code, notes, and snippets.

@angeloxx
Last active July 29, 2022 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angeloxx/c654ce47659cc4ed5c9038d4a9e09b07 to your computer and use it in GitHub Desktop.
Save angeloxx/c654ce47659cc4ed5c9038d4a9e09b07 to your computer and use it in GitHub Desktop.
Nagios/Icinga2 monitor perfdata
#!/usr/bin/python3
import os, glob, time, sys, argparse
# The script navigate Nagios/Icinga2's perfdata and read it in order to create additional treshold based on last value or the trend in a specific timespan.
# python3 scripts/check_perfdata.py -H SERVER -S ILO_HEALTH -V Inlet_Ambient -C 21 -W 19.1 --trend-period-minutes 10 -P var/spool/icinga2/perfdata/ --trend-warning=1 --trend-critical=2
INVALIDVALUE = -999
latestValue = INVALIDVALUE
latestValueTime = INVALIDVALUE
trendFirstValue = INVALIDVALUE
valueTrend = INVALIDVALUE
valueNameFound = False
# 0->OK, 1->WARNING, 2->CRITICAL, 3->UNKNOWN
exitState = 0
exitString = []
exitStateString = ""
def nagiosFields(_in, _yourValue):
ret = {}
for field in _in:
(key,value) = field.split("::")
ret[key] = value
ret["PERFORMANCES"] = {}
for performance in ret['SERVICEPERFDATA'].split(" "):
(key,value) = performance.split('=')
(current,warning,critical) = value.split(";")
ret["PERFORMANCES"][key] = float(current.replace("%",""))
if _yourValue == key:
ret["PERFORMANCE"] = float(current.replace("%",""))
return ret
parser = argparse.ArgumentParser(description='Process performance data')
parser.add_argument('-P', '--path', dest="datapath", default="/var/spool/icinga2/perfdata/", required=False, help='Performance data path')
parser.add_argument('-H', '--host', dest="hostname", default="LOCALHOST", required=True, help='Nagios/Icinga2 Hostname')
parser.add_argument('-S', '--service', dest="service", default="UPTIME", required=True, help='Service name')
parser.add_argument('-V', '--value', dest="value", default="freespace", required=True, help='Performance field name')
parser.add_argument('-C', '--warning', dest="warning", default=20, type=float, required=True, help='Warning absolute value')
parser.add_argument('-W', '--critical', dest="critical", default=30, type=float, required=True, help='Critical absolute value')
parser.add_argument('--trend-period-minutes', dest="tperiod", default=INVALIDVALUE, type=int, required=False, help='Trend change period')
parser.add_argument('--trend-warning', dest="twarning", default=INVALIDVALUE, type=float, required=False, help='Warning trend change value')
parser.add_argument('--trend-critical', dest="tcritical", default=INVALIDVALUE, type=float, required=False, help='Critical trend change value')
args = parser.parse_args()
perfdataFiles = filter( os.path.isfile, glob.glob(args.datapath + 'service-perfdata.*') )
perfdataFiles = sorted( perfdataFiles, key = os.path.getmtime, reverse = True)
for perfdataFile in perfdataFiles:
# Break if all data was already acquired
if latestValue != INVALIDVALUE:
if args.tperiod != INVALIDVALUE and trendFirstValue != INVALIDVALUE:
break
if args.tperiod == INVALIDVALUE:
break
with open(perfdataFile, "r") as f:
for line in f:
fieldsRaw=line.rstrip().split("\t")
if f"HOSTNAME::{args.hostname}" in fieldsRaw and f"SERVICEDESC::{args.service}" in fieldsRaw:
data = nagiosFields(fieldsRaw, args.value)
if "PERFORMANCE" in data:
if latestValue == INVALIDVALUE:
valueNameFound = True
latestValue = float(data["PERFORMANCE"])
latestValueTime = int(data["TIMET"])
else:
if args.tperiod != INVALIDVALUE and trendFirstValue == INVALIDVALUE and (latestValueTime-(args.tperiod*60)) >= int(data["TIMET"]):
trendFirstValue = float(data["PERFORMANCE"])
valueTrend = latestValue - trendFirstValue
if valueNameFound == False:
exitState = 3
exitString.append(f"unable to find {args.value} in performance data ({args.datapath}) for {args.hostname}")
else:
if args.tperiod == INVALIDVALUE:
exitString.append(f"performance {args.value} is latest={latestValue}")
else:
exitString.append(f"performance {args.value} is latest={latestValue} and trend({args.tperiod} min)={valueTrend}")
if latestValue >= args.critical:
exitState = 2
exitString.append(f"above absolute critical {args.critical}")
if exitState <= 1 and latestValue >= args.warning:
exitState = 1
exitString.append(f"above absolute warning {args.warning}")
if args.tperiod != INVALIDVALUE:
if valueTrend >= args.tcritical:
exitState = 2
exitString.append(f"above trend critical {args.tcritical}")
if exitState <= 1 and valueTrend >= args.twarning:
exitState = 2
exitString.append(f"above trend warning {args.twarning}")
if exitState <= 0:
pass
if exitState == 0: exitCodeString = "OK"
if exitState == 1: exitCodeString = "WARNING"
if exitState == 2: exitCodeString = "CRITICAL"
if exitState == 3: exitCodeString = "UNKNOWN"
print(exitCodeString + ": " + ', '.join(exitString))
sys.exit(exitState)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment