nagiosplugin - eine Python-Bibliothek für Monitoring-Plugins
-
Upload
christian-kauhaus -
Category
Technology
-
view
1.165 -
download
1
description
Transcript of nagiosplugin - eine Python-Bibliothek für Monitoring-Plugins
NAGIOSPLUGINEINE PYTHON-KLASSENBIBLIOTHEK FÜR NAGIOS/ICINGA-
PLUGINSChristian Kauhaus
(Lloyd S. Nelson)
“ The most important figures that oneneeds for management are unknown or
unknowable. ”
CHRISTIAN KAUHAUSseit 2008 bei goceptSysadminHosting/Data Center
FlyingCircus.io
ÜBERBLICKIntroKonzepteBasics
DatenerhebungDatenbewertungPräsentation
AdvancedLogging & OutputPersistente DatenFehlerbehandlung
Fazit
BEIPACKZETTELDIESER VORTRAG ENTHÄLT
Einführung in nagiospluginviele Code-BeispieleLive-Demos
DIESER VORTRAG ENTHÄLT NICHT
die gesamte nagiosplugin-APIKonfiguration von Nagios/Icinga-Servern
INTROPlugins sind primäre Methode der
Informationsgewinnung bei Nagios/Icinga
Input: KommandozeileOutput: Text auf stdout, Exit-CodePlugin API:
Plugin Development Guidelines:http://nagios.sourceforge.net/docs/3_0/pluginapi.html
http://nagiosplug.sourceforge.net/developer-guidelines.html
PLUGIN SCHREIBEN? IST DOCH EASY!#!/bin/sh# 31131 disk plugin codez# (C) 1999,2004-2006,2011 by wArEzGuY# if you don't understand this go away
echo "wArEzGuY's kewl disk plugin is running!!!"
df /srv/app01/data | grep '̂/' | awk '{ print $3 }' | \ grep '[1-5].....' || { echo "OMG!!! *** disk is screwed!!!"; exit 2}
echo "disk is ok"exit 0
# XXX should never reach this
NAGIOS PLUGIN API
timeout standard options output spec
exit codes range syntaxperformance data multi-threshold status line
long output
BEISPIEL: OUTPUT SPEC
CHECK - status line | perf1 perf2 long output long output | perf3 perf4 perf5 perf6
BEISPIEL: RANGE-SYNTAX
9-6:8~:3-2.25:@5:7.5
NAGIOSPLUGIN IST...Python-KlassenbibliothekOpen Source (ZPL-Lizenz)entstanden aus -Eigenbedarfseit 2010 kontinuierlich weiterentwickeltPython 3-kompatibel
Release-Stand:
alte 0.4.x API wird nicht mehr weiterentwickeltInhalt des Vortrags neue 1.0 API
gocept
KONZEPTETerminlogie bei #monitoringsucks –
ResourceMetricContextEventAction
watch your language
KONZEPTE IM NAGIOS-KONTEXT
ZENTRALE KLASSEN
BASICS #1: DATENERHEBUNG
RESOURCEDomain ModelSubklasse von Resourceprobe() erzeugt Metriken
class Resource:
@property def name(self): return self.__class__.__name__
def probe(self): return []
BEISPIEL: CHECK_WORLDimport nagiosplugin
class World(nagiosplugin.Resource):
def probe(self): return [ nagiosplugin.Metric('world', True, context='null') ]
def main(): check = nagiosplugin.Check(World()) check.main()
if __name__ == '__main__': main()
METRICStrukturiertes Value-Objekt für einzelnen Datenpunkt
class Metric:
def __init__(self, name, value, uom=None, min=None, max=None, context=None): ...
BEISPIEL: CHECK_LOADclass Load(nagiosplugin.Resource):
def __init__(self, percpu=False): self.percpu = percpu
def cpus(self): return int(subprocess.check_output(['nproc']))
def probe(self): with open('/proc/loadavg') as loadavg: load = loadavg.readline().split()[0:3] cpus = self.cpus() if self.percpu else 1 load = [float(l) / cpus for l in load] for i, period in enumerate([1, 5, 15]): yield nagiosplugin.Metric('load%d' % period, load[i], min=0, context='default')
BASICS #2: DATENBEWERTUNG
CONTEXTerzeugt Result aus Metric und Resourceerzeugt Performance Dataerzeugt Klartext-Beschreibung
class Context:
def __init__(self, name, ...): ...
def evaluate(self, metric, resource): return Result(...)
def performance(self, metric, resource): return Performance(...)
def describe(self, metric): return '...'
SCALARCONTEXTHäufig gebrauchter Spezialfallwarning und critical Ranges
Verwendung direkt in Check-Initialisierung:
class ScalarContext(Context):
def __init__(self, name, warning, critical, ...): ...
check = nagiosplugin.Check( nagiosplugin.ScalarContext('load', args.warning, args.critical), ...)
ZUORDNUNG METRIC/CONTEXTJede Metric benennt den zuständigen Context
Standard-Contexts:
null - tut gar nichtsdefault - gibt Performance-Daten aus
# Load.probe() for period, i in zip([1, 5, 15], itertools.count()): yield nagiosplugin.Metric('load%d' % period, load[i], min=0, context='load')
# main()check = nagiosplugin.Check( Load(), nagiosplugin.ScalarContext('load', args.warning, args.critical), ...)
BASICS #3: PRÄSENTATION
SUMMARYStatuszeile ist wichtig!
erscheint in Mails, in SMS, auf Pagerin 80-140 Zeichen die „Message“ herüberbringenmuss nachts 3:30 Uhr verständlich sein
NICHT HILFREICH
SUMMARY – STANDARDIMPLEMENTIERUNGclass Summary:
def ok(self, results): return str(results[0])
def problem(self, results): try: return str(results.first_significant) except IndexError: return 'no check results'
def verbose(self, results): msgs = [] for result in results: if result.state == Ok: continue msgs.append('{}: {}'.format(result.state, result)) return msgs
BEISPIEL: CHECK_LOADclass LoadSummary(nagiosplugin.Summary):
def __init__(self, percpu): self.percpu = percpu
def ok(self, results): if self.percpu: what = 'loadavg per cpu' else: what = 'loadavg' return '{} is {}'.format(what, ', '.join( str(results[r].metric) for r in ['load1', 'load5', 'load15']))
ADVANCED #1: LOGGING & OUTPUTSetup:
Logging:
def main(): ... argp.add_argument('-v', '--verbose', action='count', default=0, help='increase verbosity') ... check.main(verbose=args.verbose)
def list_users(self): logging.info('querying users with "%s" command', self.who_cmd) users = [] ...
VERBOSE=0
Status und Perfdata auf einer ZeileLoglevel warning und höherSummary.verbose() wird nicht angezeigt
$ check_usersUSERS OK - 4 users logged in | total=4;;;0 unique=1;;;0
VERBOSE=1
mehrzeilige Ausgabesollte Standard sein für Server, die long outputverarbeitenLoglevel warning und höherSummary.verbose() wird angezeigt
$ check_users -vUSERS OK - 4 users logged inusers: ckauhaus, ckauhaus, ckauhaus, ckauhaus| total=4;;;0 unique=1;;;0
VERBOSE=2
Konfigurationsinformationen zum Pluginz.B. Commandlines externer AufrufeLoglevel info und höher
$ check_users.py -vvUSERS OK - 4 users logged inusers: ckauhaus, ckauhaus, ckauhaus, ckauhausquerying users with "who" command (check_users.py:34)| total=4;;;0 unique=1;;;0
VERBOSE=3
Debugging-Informationenz.B. ZwischenergebnisseLoglevel debug und höher
$ check_users.py -vvvUSERS OK - 4 users logged inusers: ckauhaus, ckauhaus, ckauhaus, ckauhausquerying users with "who" command (check_users.py:34)who output: b'ckauhaus tty1 2012-10-29 12:36' (check_users.py:38)...| total=4;;;0 unique=1;;;0
FORMATIERUNG VON METRIKENContext ist für „seine“ Metriken zuständig
Variante 1: String-Template
Variante 2: Callable
Context(..., fmt_metric='{name} is {valueunit}')
def format_usercount(metric, context): return '...'
Context(..., fmt_metric=format_usercount)
ADVANCED #2: PERSISTENTE DATENZustand zwischen Plugin-Aufrufen behalten
CookieLogTail
COOKIEpersistentes dictSerialisierung mit JSONLocking
Inhalt von statefile:
with nagiosplugin.Cookie(self.statefile) as cookie: self.timestamp = cookie.get('last_seen', '') metrics = self.do_something() cookie['last_seen'] = self.timestamp
{ "last_seen": "2012-10-28 12:08:25"}
LOGTAILInkrementelles Lesen von wachsenden Logfiles
baut auf Cookie auferkennt Log-RotationWiederaufsetzen nach Exceptions
def parse_log(self): cookie = nagiosplugin.Cookie(self.statefile) with nagiosplugin.LogTail(self.logfile, cookie) as lf: for line in lf: ...
ADVANCED #3: FEHLERBEHANDLUNGWas ist, wenn es nicht so läuft wie geplant?
Wichtige Fehlerklassen:
Resource nicht da/nicht abfragbarFehlerhafte Kommandozeilen-ParameterUmgebungsfehlerProgrammierfehler
@NAGIOSPLUGIN.GUARDEDSchützt die main()-Funktion bei Exceptions:
Exit-Status 3API-konforme AusgabeTraceback bei verbose ≥ 1
@nagiosplugin.guardeddef main(): argp = argparse.ArgumentParser() argp.add_argument(...) args = argp.parse_args() check = nagiosplugin.Check(Load(args.percpu), ...) check.main()
BEISPIEL: EXCEPTION IN PROBE()
Ausgabe (verbose=0):
class Fail(nagiosplugin.Resource):
def probe(self): raise RuntimeError("I'm feeling bad")
@nagiosplugin.guardeddef main(): argp = argparse.ArgumentParser() argp.add_argument('-v', action='count', default=0) args = argp.parse_args() check = nagiosplugin.Check(Fail()) check.main(args.verbose)
$ check_fail.pyFAIL UNKNOWN: RuntimeError: I'm feeling bad# exit 3
FAZITMit nagiosplugin macht das
Schreiben von Plugins beinahe Spaß. ;-)
Trennung der Verantwortlichkeitenwartbarer, objekt-orientierter Codevolle Unterstützung der Plugin-APIkleine Helferrobustes Verhalten im Fehlerfall
USE THE SOURCE, LUKE
Download:
Code:
Wiki/Tracker/Forum:
http://pypi.python.org/pypi/nagiosplugin
https://bitbucket.org/gocept/nagiosplugin
https://projects.gocept.com/projects/nagiosplugin/wiki
DANKE!FRAGEN?