1. Einleitung
Der Livestatus ist die wichtigste Schnittstelle in Checkmk. Durch sie bekommen Sie schnellstmöglich und live Zugriff auf alle Daten der überwachten Hosts und Services. So werden z.B. die Daten im Overview direkt über diese Schnittstelle abgerufen. Da diese direkt aus dem RAM geholt werden, werden langsame Festplattenzugriffe vermieden und es gibt einen schnellen Zugriff auf das Monitoring, ohne das System zu sehr zu belasten.
Um die Daten zu strukturieren, werden sie in Tabellen und Spalten geordnet. Die
Tabelle hosts
enthält dann z.B. die Spalten name
,
state
und viele weitere. Jede Zeile in der Tabelle hosts
repräsentiert dabei einen Host, in der Tabelle services
einen
Service usw. Auf diese Weise können die Daten einfach durchsucht und
abgerufen werden.
Dieser Artikel soll Ihnen helfen, diese Schnittstelle für eigene Abfragen, Erweiterungen und Anpassungen zu nutzen. Alle Abfragen und Kommandos in diesem Artikel können Sie als Instanzbenutzer durch Copy&Paste direkt ausprobieren.
2. Die Livestatus Query Language (LQL)
2.1. Nutzung der LQL in der Shell
Der Zugriff zum Livestatus erfolgt über einen Unix-Socket unter Benutzung der Livestatus Query Language (LQL). Diese ist in ihrer Syntax an HTTP angelehnt.
Sie können auf der Kommandozeile auf verschiedene Arten auf die Schnittstelle
zugreifen. Eine Möglichkeit ist es, über die Kommandos printf
und
unixcat
den Befehl an den Socket zu leiten. Checkmk liefert für
den Instanzbenutzer das Tool unixcat
bereits mit. Wichtig:
Alle Eingaben an den Socket unterscheiden Groß- und Kleinschreibung, so
dass diese immer eingehalten werden muss:
OMD[mysite]:~$ printf "GET hosts\nColumns: name\n" | unixcat ~/tmp/run/live
Die Schnittstelle erwartet alle Befehle und Header in jeweils einer eigenen
Zeile. Markieren Sie daher jeden Zeilenumbruch mit einem \n
. Als
Alternative zu dem Kommando oben können Sie auch den Skriptbefehl lq
nutzen, welcher Ihnen einiges bei der Eingabe abnimmt:
OMD[mysite]:~$ lq "GET hosts\nColumns: name"
Oder Sie starten den interaktiven Eingabe-Stream und geben dann den Befehl und die Header nacheinander ein. Mit einer Leerzeile führen Sie den Befehl mit seinen Headern aus und eine weitere Zeile beendet den Zugriff auf den Socket. Beachten Sie, dass in dem Beispiel alles vor der ersten Leerzeile zum dem Befehl gehört und alles zwischen der ersten und zweiten Leerzeile die Antwort ist:
OMD[mysite]:~$ lq
GET hosts
Columns: name
myserver123
myserver124
myserver125
OMD[mysite]:~$
Die folgenden Beispiele werden immer mit dem lq
-Befehl ausgeführt; in direkter
Form, wenn der Aufruf kurz ist und als Eingabe-Stream bei einem längeren.
Befehle der LQL
In den ersten Beispielen haben Sie bereits den ersten der beiden Befehle
gesehen: Mit GET
können Sie alle verfügbaren Tabellen abrufen. In
der Befehlsreferenz finden Sie eine vollständige Liste aller verfügbaren
Tabellen mit einer Beschreibung In diesem
Artikel wird die generelle Benutzung des Livestatus gezeigt.
Mit COMMAND
können Sie Kommandos direkt an den Core schicken,
um z.B. eine Downtime zu setzen oder Benachrichtigungen komplett zu
deaktivieren. Eine Liste aller verfügbaren Kommandos finden Sie ebenfalls
in der Befehlsreferenz bei den Commands.
Header in der LQL
Zu jedem GET-Befehl können Sie verschiedene Header hinzufügen, um das Ergebnis der Abfrage einzugrenzen, nur bestimmte Spalten einer Tabelle auszugeben und vieles mehr. Die beiden wichtigsten Header sind die folgenden:
Header | Beschreibung |
---|---|
Columns |
Es werden nur die angegebenen Spalten einer Abfrage ausgegeben. |
Filter |
Es werden nur die Einträge ausgegeben, auf die eine bestimmte Bedingung zutrifft. |
Eine Liste aller Header mit einer Kurzbeschreibung finden Sie hier.
Verfügbare Spalten und Tabellen anzeigen
Sie werden sich nicht alle Tabellen und deren Spalten merken können und
haben vielleicht auch nicht immer auf dieses Handbuch (mit den Referenzen
in der Online-Version) Zugriff. Es lässt sich jedoch schnell eine Abfrage
erstellen, welche die gewünschten Informationen bereit stellt. Um eine Liste
aller verfügbaren Tabellen zu bekommen führen Sie die folgende Abfrage aus
und entfernen in der Ausgabe die duplizierten Zeilen mit sort
. In
der Ausgabe sehen Sie die ersten vier Zeilen als Beispielausgabe:
OMD[mysite]:~$ lq "GET columns\nColumns: table" | sort -u
columns
commands
comments
contactgroups
Für die Abfrage aller Spalten zu einer Tabelle müssen Sie diese natürlich
angeben. Ersetzen Sie daher hosts
durch die gewünschte Tabelle. Auch
hier sind die ersten vier Zeilen der Ausgabe als Beispiel zu sehen:
OMD[mysite]:~$ lq "GET columns\nFilter: table = hosts\nColumns: name"
accept_passive_checks
acknowledged
acknowledgement_type
action_url
2.2. Nutzung der LQL in Python
Da Checkmk sehr stark auf Python aufbaut, bieten sich Skripten in dieser Sprache an. Für den Zugriff auf den Socket des Livestatus können Sie das folgende Skript als Ausgangsbasis nutzen:
#!/usr/bin/env python
# Sample program for accessing Livestatus from Python
import json, os, socket
# for local site only: file path to socket
address = "%s/tmp/run/live" % os.getenv("OMD_ROOT")
# for local/remote sites: TCP address/port for Livestatus socket
# address = ("localhost", 6557)
# connect to Livestatus
family = socket.AF_INET if type(address) == tuple else socket.AF_UNIX
sock = socket.socket(family, socket.SOCK_STREAM)
sock.connect(address)
# send our request and let Livestatus know we're done
sock.sendall(str.encode("GET status\nOutputFormat: json\n"))
sock.shutdown(socket.SHUT_WR)
# receive the reply as a JSON string
chunks = []
while len(chunks) == 0 or chunks[-1] != "":
data = sock.recv(4096)
chunks.append(str(data.decode("utf-8")))
sock.close()
reply = "".join(chunks)
# print the parsed reply
print(json.loads(reply))
2.3. Nutzung der Livestatus-API
Checkmk stellt auch eine API für die Programmiersprachen Python, Perl und C++ zur Verfügung, welche den Zugriff auf den Livestatus vereinfachen. Zu jeder Sprache steht Ihnen Beispielcode zur Verfügung, welcher die Nutzung erläutert. Die Pfade zu diesen Beispielen finden Sie in dem Kapitel Dateien und Verzeichnisse.
3. Einfache Abfragen
3.1. Spalten abfragen (Columns)
Bisher wurden in den Beispielen alle Informationen zu allen Hosts abgefragt. In
der Praxis möchten Sie aber wahrscheinlich nur bestimmte Informationen
(Spalten) haben. Mit dem bereits erwähnten Header Columns
können
Sie die Ausgabe auf diese Spalten eingrenzen. Die einzelnen Spaltennamen
werden durch ein einfaches Leerzeichen getrennt.
OMD[mysite]:~$ lq "GET hosts\nColumns: name address"
myserver123;192.168.0.42
myserver234;192.168.0.73
Wie Sie sehen, erfolgt die Trennung der einzelnen Werte einer Zeile wiederum durch ein Semikolon.
Wichtig: Wenn Sie diesen Header benutzen, werden die Kopfzeilen in der Ausgabe unterdrückt. Sie können diese aber mit dem Header ColumnHeaders der Ausgabe wieder hinzufügen.
3.2. Einfache Filter setzen (Filter)
Um die Abfrage nur auf bestimmte Zeilen einzugrenzen, können Sie Spalten auf bestimmte Inhalte filtern. Wenn Sie also nur Services mit einem bestimmten Status suchen, können Sie das durch einen Filter realisieren:
OMD[mysite]:~$ lq "GET services\nColumns: host_name description state\nFilter: state = 2"
myserver123;Filesystem /;2
myserver234;ORA MYINST Processes;2
In dem Beispiel wird nach allen Services gesucht, deren Status CRIT ist; anschließend werden der Hostname, die Servicebeschreibung und dessen Status ausgegeben. Sie können solche Filter natürlich auch kombinieren und weiter einschränken auf Services, deren Status CRIT ist und noch nicht bestätigt wurde:
OMD[mysite]:~$ lq "GET services\nColumns: host_name description state\nFilter: state = 2\nFilter: acknowledged = 0"
myserver234;Filesystem /;2
Wie Sie sehen, kann man auch nach Spalten filtern, die nicht in Columns
aufgelistet sind.
Operatoren und reguläre Ausdrücke
Bisher haben Sie nur auf die Übereinstimmung von Zahlen gefiltert. Sie können das vorläufige Ergebnis einer Abfrage aber auch auf „kleiner als“ bei Zahlen oder auf Zeichenketten durchsuchen. Die Ihnen zur Verfügung stehenden Operatoren finden Sie im Kapitel Operatoren der Befehlsreferenz. Dadurch können Sie z.B. auch über reguläre Ausdrücke in den Spalten filtern:
OMD[mysite]:~$ lq "GET services\nColumns: host_name description state\nFilter: description ~~ exchange database|availability"
myserver123;Exchange Database myinst1;1
myserver123;Exchange Availability Service;0
myserver234;Exchange Database myinst3;0
Mit dem richtigen Operator können Sie auf verschiedene Art und Weise
mit regulären Ausdrücken die Spalten durchsuchen. Der Livestatus
wird einen solchen Ausdruck grundsätzlich immer als „kann irgendwo in
der Spalte vorkommen“ interpretieren, sofern das nicht entsprechend
anders definiert wurde. Auf den Anfang einer Zeile verweisen Sie z.B. mit
dem Zeichen ^
, während Sie mit dem Zeichen $
auf das
Ende einer Zeile hinweisen. Eine ausführliche Liste aller Sonderzeichen
für Reguläre Ausdrücke in Checkmk finden Sie in dem Artikel für
Reguläre Ausdrücke.
3.3. Ausgabe sortieren (OrderBy)
Mit dem Header OrderBy
können Sie die Ausgabe nach den Inhalten beliebiger Spalten oder auch den Werten beliebiger Dictionary-Schlüssel sortieren.
So lässt sich bspw. eine alphabetische Auflistung aller Host erstellen:
OMD[mysite]:~$ lq "GET hosts\nColumns: name\nOrderBy: name"
ahost
anotherhost
yetanotherhost
Implizit wird die Ausgabe erwartungsgemäß aufsteigend sortiert (asc
).
Sie können die gewünschte Sortierung aber auch explizit angeben und durch die Angabe von desc
umdrehen:
OMD[mysite]:~$ lq "GET hosts\nColumns: name\nOrderBy: name desc"
yetanotherhost
anotherhost
ahost
Mit etwas längeren Abfragen und bspw. einer Sortierung nach Performance-Daten, können interessante Ranglisten entstehen. Im folgenden Beispiel werden die Hosts absteigend nach ihrer Uptime sortiert ausgegeben:
OMD[mysite]:~$ lq "GET services\nColumns: host_name performance_data\nFilter: description = Uptime\nOrderBy: performance_data.uptime desc"
anotherhost;uptime|249531.1
yetanotherhost;uptime|149142.3
ahost;uptime|48959
4. Komplexe Abfragen
4.1. Filter für Listen
Manche Spalten einer Tabelle liefern nicht nur einen Wert zurück,
sondern gleich eine ganze Liste davon. Damit Sie auch diese
effektiv durchsuchen können, haben die Operatoren hier eine andere
Bedeutung. Eine vollständige Liste der Operatoren finden Sie bei den
Operatoren für Listen.
So hat z.B. der Operator >=
die Bedeutung „enthält“. Mit diesem
können Sie z.B. nach einem bestimmten Kontakt suchen:
OMD[mysite]:~$ lq "GET hosts\nColumns: name address contacts\nFilter: contacts >= hhirsch"
myserver123;192.168.0.42;hhirsch,hhirsch,mfrisch
myserver234;192.168.0.73;hhirsch,wherrndorf
Wie Sie in dem Beispiel sehen, werden die Kontakte in der Spalte
contacts
kommasepariert aufgelistet. Dadurch lassen sie sich eindeutig
von dem Beginn einer neuen Spalte unterscheiden. Eine Besonderheit stellt
bei den Listen der Gleichheitsoperator dar. Er prüft, ob eine Liste leer ist:
OMD[mysite]:~$ lq "GET hosts\nColumns: name contacts\nFilter: contacts ="
myserver345;
myserver456;
4.2. Filter kombinieren
Bereits vorher wurden mehrere Filter kombiniert. Dabei erscheint es intuitiv,
dass die Daten alle Filter passieren müssen, um angezeigt zu werden. Die
Filter werden also mit einem logischen und verknüpft. Um bestimmte
Filter mit einem logischen oder zu verknüpfen, können Sie am Ende der
Filterreihe ein Or:
gefolgt von einer Ganzzahl einfügen. Der Counter
bestimmt, wie viele der letzten Zeilen zu einem oder zusammengefasst
werden. Dadurch können Sie Gruppen bilden und diese beliebig kombinieren. Ein
einfaches Beispiel ist das folgende. Hier werden zwei Filter so kombiniert,
dass alle Services angezeigt werden, die entweder den Status WARN oder
UNKNOWN haben:
OMD[mysite]:~$ lq
GET services
Columns: host_name description state
Filter: state = 1
Filter: state = 3
Or: 2
myserver123;Log /var/log/messages;1
myserver123;Interface 3;1
myserver234;Bonding Interface SAN;3
OMD[mysite]:~$
Sie können das Ergebnis einer Kombination aber auch negieren oder Gruppen
wiederum zu Gruppen zusammenfassen. In dem Beispiel werden alle Services
angezeigt, deren Status nicht OK ist und deren Beschreibung entweder nicht
mit Filesystem
anfängt oder einen anderen Status als UNKNOWN hat:
OMD[mysite]:~$ lq
GET services
Columns: host_name description state
Filter: state = 3
Filter: description ~ Filesystem
And: 2
Filter: state = 0
Or: 2
Negate:
myserver123;Log /var/log/messages;1
myserver123;Interface 3;1
myserver234;Filesystem /media;2
myserver234;Filesystem /home;2
4.3. Das Ausgabeformat festlegen
Sie können das Ausgabeformat auf zwei verschiedene Arten festlegen. Zum einen können Sie die Separatoren der Standardausgabe neu definieren. Zum anderen kann die Ausgabe auch Python- oder JSON-konform erfolgen.
csv
anpassen
Wie bereits beschrieben, können Sie die genaue Formatierung des Standardausgabeformates csv
(kleingeschrieben!)
anpassen und definieren, wie die einzelnen Elemente voneinander getrennt werden
sollen. Checkmk kennt hier vier verschiedene Separatoren, um die Daten zu
strukturieren. Nach dem Doppelpunkt geben Sie dazu die entsprechenden Standard-ASCII-Werte an, so dass der Filter wie folgt aufgebaut ist:
Separators: 10 59 44 124
Diese Trenner haben nun die folgende Bedeutung:
Trenner für die Datensätze:
10
(Zeilenumbruch)Trenner für die Spalten eines Datensatzes:
59
(Semikolon)Trenner für die Elemente einer Liste:
44
(Komma)Trenner für die Elemente einer Serviceliste:
124
(Pipe)
Jeden dieser Werte können Sie anpassen, um die Ausgabe nach den eigenen Wünschen zu strukturieren. In dem folgenden Beispiel werden die einzelnen Spalten eines Datensatzes nicht mit Hilfe eines Semikolons (59), sondern mit einem Tabulator (9) getrennt:
OMD[mysite]:~$ lq
GET services
Columns: host_name description state
Filter: description ~ Filesystem
Separators: 10 9 44 124
myserver123 Filesystem /opt 0
myserver123 Filesystem /var/some/path 1
myserver123 Filesystem /home 0
Wichtig: Die Reihenfolge der Separatoren ist fest und darf daher nicht vertauscht werden.
Ausgabeformat ändern
Neben einer Ausgabe in csv
kann Livestatus für Sie auch andere
Formate erzeugen. Diese haben den Vorteil, dass sie sich in höheren
Programmiersprachen leichter und sauberer parsen lassen. Sie können sich die
Ausgabe demnach in den folgenden Formaten kodieren lassen:
Format | Beschreibung |
---|---|
python |
Erzeugt die Ausgabe als Liste kompatibel zu Python 2.x. Text wird in Unicode formatiert. |
python3 |
Erzeugt ebenso die Ausgabe als Liste und berücksichtigt dabei Änderungen in den Datentypen, wie z.B. die automatische Konvertierung von Text zu Unicode. |
json |
Die Ausgabe wird ebenfalls als Liste zurückgegeben. Es werden dabei jedoch nur JSON-kompatible Formate verwendet. |
CSV |
Formatiert die Ausgabe nach RFC-4180. |
csv |
Siehe |
Verwechseln Sie das CSV-Format
bitte nicht
mit der csv
-Ausgabe des Livestatus, welches verwendet wird, wenn
kein Ausgabeformat festgelegt wurde. Eine korrekte Groß-/Kleinschreibung
ist daher absolut notwendig. Für die Anpassung übergeben Sie am Ende ein
OutputFormat
statt des Separator
:
OMD[mysite]:~$ lq
GET services
Columns: host_name description state
Filter: description ~ Filesystem
OutputFormat: json
[["myserver123","Filesystem /opt",0]
["myserver123","Filesystem /var/some/path",1]
["myserver123","Filesystem /home",0]]
5. Statistiken abrufen (Stats)
5.1. Einleitung
Es wird Situationen geben, in denen Sie gar nicht daran interessiert sind,
wie der Status eines einzelnen oder einer Gruppe von Services ist. Vielmehr
ist die Anzahl der Services wichtig, welche gerade WARN sind oder die
Anzahl der überwachten Datenbanken. Livestatus ist in der Lage mit
Stats
Statistiken zu erstellen und auszugeben.
5.2. Zählen
Der Overview bekommt seine Daten, indem er über Livestatus Statistiken zu Hosts, Services und Events abruft und dann in der Oberfläche von Checkmk darstellt. Mit dem direkten Zugriff auf Livestatus können Sie ebenfalls eigene Aufsummierungen erstellen:
OMD[mysite]:~$ lq
GET services
Stats: state = 0
Stats: state = 1
Stats: state = 2
Stats: state = 3
34506;124;54;20
Solche Statistiken lassen sich übrigens auch mit allen Filtern kombinieren.
5.3. Gruppieren
Auch Statistiken lassen sich mit and/or
zusammenfassen. Die Header
heißen dann StatsAnd
oder StatsOr
. Wenn Sie die Ausgabe
umkehren wollen, benutzen Sie StatsNegate
. In dem Beispiel wird
die Gesamtzahl der Hosts ausgegeben (das erste Stats
) und dazu die
Anzahl derer, die als stale
markiert wurden und sich nicht in einer
Downtime befinden (Stats 2 und 3 werden mit einem logischen UND verknüpft):
OMD[mysite]:~$ lq
GET hosts
Stats: state >= 0
Stats: staleness >= 3
Stats: scheduled_downtime_depth = 0
StatsAnd: 2
734;23
Verwechseln Sie nicht die unterschiedlichen Möglichkeiten, die Ergebnisse der
Filter und Statistiken zusammenzufassen. Während bei dem Header
Filter
alle Hosts ausgegeben werden, auf die
die Bedingungen zutreffen, wird bei den Statistiken die Summe ausgegeben, wie oft
die Stats
-Filter zutreffen.
5.4. Minimum, Maximum, Durchschnitt etc.
Sie können auch Berechnungen an Werten durchführen und z.B. den Durchschnittswert oder das Maximum ausgeben lassen. Eine vollständige Liste der möglichen Operatoren finden Sie hier.
In dem folgenden Beispiel wird die durchschnittliche, minimale und maximale Zeit ausgegeben, welche die Check-Plugins eines Hosts für die Berechnung eines Status benötigen:
OMD[mysite]:~$ lq
GET services
Filter: host_name = myserver123
Stats: avg execution_time
Stats: max execution_time
Stats: min execution_time
0.0107628;0.452087;0.008593
Berechnungen von Metriken werden etwas besonders behandelt. Auch hier sind
alle Funktionen des Stats
-Header möglich. Diese werden jedoch auf
alle Metriken eines Service einzeln angewandt. Nachfolgend werden
als Beispiel die Metriken der CPU-Benutzung einer Host-Gruppe aufsummiert:
OMD[mysite]:~$ lq
GET services
Filter: decription ~ CPU utilization
Filter: host_groups >= cluster_a
Stats: sum perf_data
guest=0.000000 steal=0.000000 system=34.515000 user=98.209000 wait=23.008000
6. Begrenzung der Ausgabe (Limit)
Die Anzahl der Zeilen in der Ausgabe ist begrenzbar. Das kann z.B. nützlich sein, wenn Sie nur sehen wollen, ob überhaupt eine Antwort auf eine Livestatus-Anfrage zurückkommt, aber eine seitenlange Ausgabe verhindern wollen:
OMD[mysite]:~$ lq "GET hosts\nColumns: name\nLimit: 3"
myserver123
myserver234
myserver345
Beachten Sie, dass dieses Limit auch funktioniert, wenn Sie es mit anderen
Headern kombinieren. Wenn Sie z.B. mit Stat
zählen, wie viele Hosts den Status UP
haben und die Ausgabe auf 10 begrenzen, werden nur die ersten 10 Hosts
berücksichtigt.
7. Zeitbeschränkungen (Timelimit)
Sie können nicht nur die Anzahl der ausgegebenen Zeilen einschränken. Auch die maximale Zeit, wie lange eine Abfrage dauern darf, können Sie begrenzen. Damit verhindern Sie, dass eine Livestatus-Abfrage nicht für immer eine Verbindung blockiert, weil sie aus irgendwelchen Gründen hängt. Die Zeitbeschränkung gibt dabei die Zeit in Sekunden an, die die Verarbeitung einer Abfrage dauern darf:
OMD[mysite]:~$ lq "GET hosts\nTimelimit: 1"
8. Kopfzeilen aktivieren (ColumnHeaders)
Mit den ColumnHeaders
können Sie zu der Ausgabe die Namen der
Spalten ausgeben lassen. Diese werden normalerweise unterdrückt, um die
Weiterbearbeitung zu vereinfachen:
OMD[mysite]:~$ lq "GET hosts\nColumns name address groups\nColumnHeaders: on"
name;address;groups
myserver123;192.168.0.42;cluster_a,headnode
myserver234;192.168.0.43;cluster_a
myserver345;192.168.0.44;cluster_a
9. Berechtigungen (AuthUser)
Wenn Sie Skripten auf Basis des Livestatus zur Verfügung stellen möchten,
sollen die Nutzer wahrscheinlich nur die Daten sehen, für die sie auch
berechtigt sind. Checkmk stellt dafür den Header AuthUser
mit
der Einschränkung zur Verfügung, dass dieser nicht in den folgenden
Tabellen benutzt werden kann:
columns
commands
contacts
contactgroups
eventconsolerules
eventconsolestatus
status
timeperiods
Umgekehrt bedeutet es, dass Sie diesen Header in allen Tabellen nutzen können,
die auf die Tabellen hosts
oder services
zugreifen. Ob ein
Nutzer nun berechtigt ist, hängt dabei von seinen Kontaktgruppen ab.
Auf diese Weise werden bei einer Abfrage nur diejenigen Daten ausgegeben,
die der Kontakt auch sehen darf. Beachten Sie hier den Unterschied
zwischen strict
und loose
bei den
Berechtigungseinstellungen:
OMD[mysite]:~$ lq "GET services\nColumns: host_name description contacts\nAuthUser: hhirsch"
myserver123;Uptime;hhirsch
myserver123;TCP Connections;hhirsch
myserver123;CPU utilization;hhrisch,kkleber
myserver123;File /etc/resolv.conf;hhirsch
myserver123;Kernel Context Switches;hhrisch,kkleber
myserver123;File /etc/passwd;hhirsch
myserver123;Filesystem /home;hhirsch
myserver123;Kernel Major Page Faults;hhrisch
myserver123;Kernel Process Creations;hhirsch
myserver123;CPU load;hhrisch,kkleber
10. Verzögerungen (Wait)
Mit den Wait-Headern erstellen Sie Abfragen, um bestimmte Datensätze zu bekommen, ohne wissen zu müssen, wann die Bedingungen für die Daten erfüllt sind. Das kann nützlich sein, wenn Sie zu einem bestimmten Fehlerbild Vergleichsdaten benötigen, aber das System nicht durchgehend sinnlos belasten wollen. Informationen werden demnach nur dann abgerufen, wenn Sie auch wirklich benötigt werden.
Eine vollständige Liste der Wait-Header finden Sie hier.
In dem folgenden Beispiel wird der Service Disk IO SUMMARY eines
ESXi-Servers ausgegeben, sobald der Status des Service CPU load auf einer
bestimmten VM CRIT wird. Durch den Header WaitTimeout
wird die
Abfrage auch dann ausgeführt, wenn sie nach 10000 Millisekunden
nicht eingetreten ist. Das verhindert, dass die Livestatus-Verbindung lange
blockiert wird:
OMD[mysite]:~$ lq
GET services
WaitObject: myvmserver CPU load
WaitCondition: state = 2
WaitTrigger: state
WaitTimeout: 10000
Filter: host_name = myesxserver
Filter: description = Disk IO SUMMARY
Columns: host_name description plugin_output
myesxserver;Disk IO SUMMARY;OK - Read: 48.00 kB/s, Write: 454.54 MB/s, Latency: 1.00 ms
Ein weiterer Anwendungsfall ist die Kombination mit einem Kommando. Sie können ein Kommando absetzen und die Ergebnisse abrufen, sobald diese verfügbar sind. In dem nachfolgenden Beispiel werden die aktuellen Daten eines Services abgerufen und angezeigt. Dafür wird zuerst das Kommando übergeben und danach eine normale Abfrage erstellt. Diese prüft, ob die Daten des Service Checkmk jünger sind als der definierte Zeitpunkt. Sobald die Bedingung erfüllt ist, wird der Status des Service Memory ausgegeben.
OMD[mysite]:~$ lq "COMMAND [$(date +%s)] SCHEDULE_FORCED_SVC_CHECK;myserver;Check_MK;$(date
+%s)"
OMD[mysite]:~$ lq
GET services
WaitObject: myserver Check_MK
WaitCondition: last_check >= 1517914646
WaitTrigger: check
Filter: host_name = myserver
Filter: description = Memory
Columns: host_name description state
myserver;Memory;0
Wichtig: Achten Sie darauf,
dass der Zeitstempel in last_check
aus dem Beispiel durch einen
aktuellen ersetzt werden muss. Andernfalls ist die Bedingung immer erfüllt
und die Ausgabe kommt sofort.
11. Zeitzonen (Localtime)
Viele größere Monitoring-Umgebungen rufen auf globaler Ebene Hosts und Services ab. Da kann es schnell zu einer Situation kommen, bei der die beteiligten Monitoring-Instanzen in verschiedenen Zeitzonen arbeiten. Da Checkmk die zeitzonenunabhängige Unixzeit benutzt, sollte es hier zu keinen Problemen kommen.
Falls einer der Server jedoch einer falschen Zeitzone zugeordnet wurde, können
Sie diese Differenz mit dem Header Localtime
ausgleichen. Übergeben
Sie dazu der Abfrage die aktuelle Zeit. Checkmk wird dann selbstständig
auf die näher liegende halbe Stunde runden und die Differenz ausgleichen. Sie können
die Zeit automatisch übergeben, wenn Sie eine direkte Abfrage nutzen:
OMD[mysite]:~$ lq "GET hosts\nColumns: name last_check\nFilter: name = myserver123\nLocaltime: $(date +%s)"
myserver123;1511173526
Ansonsten übergeben Sie das Ergebnis aus date +%s
, wenn Sie den
Eingabe-Stream nutzen möchten:
OMD[mysite]:~$ lq
GET hosts
Columns: name last_check
Filter: name = myserver123
Localtime: 1511173390
myserver123;Memory;1511173526
12. Statuscodes (ResponseHeader)
Wenn Sie eine API schreiben, wollen Sie sehr wahrscheinlich auch einen
Statuscode als Rückmeldung haben, um die Ausgabe besser verarbeiten zu
können. Der Header ResponseHeader
unterstützt die Werte off
(Standard) und fixed16
und bietet damit eine exakt 16 Bytes lange
Statusnachricht in der ersten Zeile der Antwort. Im Falle eines Fehlers
enthalten die weiteren Zeilen eine ausführliche Fehlerbeschreibung zu
dem Statuscode. Sie eignet sich dadurch auch gut für eine Fehlersuche in
der Abfrage.
Die Statusnachricht der ersten Zeile setzt sich folgendermaßen zusammen:
Byte 1-3: Der Statuscode. Die komplette Tabelle der möglichen Codes finden Sie hier.
Byte 4: Ein einfaches Leerzeichen (ASCII-Zeichen: 32).
Byte 5-15: Die Länge der eigentlichen Antwort als Ganzzahl. Nicht benötigte Bytes werden mit Leerzeichen aufgefüllt.
Byte 16: Ein Zeilenvorschub (ASCII-Zeichen: 10).
In dem folgenden Beispiel führen Sie eine fehlerhafte Abfrage aus, indem Sie einen Filter falsch setzen bzw. mit dem Namen einer Spalte verwechseln.
OMD[mysite]:~$ lq "GET hosts\nName: myserver123\nResponseHeader: fixed16"
400 33
Coluns: undefined request header
Wichtig: Das Ausgabeformat ist im Fehlerfall immer eine Fehlermeldung in Textform. Das gilt unabhängig davon, wie Sie es angepasst haben.
13. Verbindung aufrecht erhalten (KeepAlive)
Gerade bei Skripten, welche eine Livestatus-Verbindung über das
Netzwerk aufbauen, wollen Sie vielleicht den Kanal
offen halten, um sich den Overhead des Verbindungsaufbaus zu sparen. Sie
erreichen das mit dem Header KeepAlive
und sind so in der Lage, sich
einen Kanal zu reservieren. Nach einem Kommando
bleibt eine Livestatus-Verbindung übrigens immer offen. Sie benötigen dafür
keine Angabe eines zusätzlichen Headers.
Wichtig: Da der Kanal für die Dauer der Verbindung für andere Prozesse blockiert ist, kann das zu einem Problem werden, wenn keine Verbindungen mehr zur Verfügung stehen. Andere Prozesse müssen dann warten, bis wieder eine Verbindung frei ist. In der Standardkonfiguration hält Checkmk 20 Verbindungen bereit — erhöhen Sie bei Bedarf die maximale Anzahl dieser Verbindungen in Setup > General > Global Settings > Monitoring Core > Maximum concurrent Livestatus connections.
Kombinieren Sie KeepAlive
immer mit dem
ResponseHeader
, um die
einzelnen Antworten voneinander korrekt unterscheiden zu können:
OMD[mysite]:~$ lq
GET hosts
ResponseHeader: fixed16
Columns: name
KeepAlive: on
200 33
myserver123
myserver234
myserver345
GET services
ResponseHeader: fixed16
Columns: host_name description last_check
Filter: description = Memory
200 58
myserver123;Memory;1511261122
myserver234;Memory;1511261183
Achten Sie darauf, dass es zwischen der ersten Antwort und der zweiten Abfrage anders als sonst keine Leerzeile gibt. Sobald Sie in einer Abfrage den Header weglassen, wird die Verbindung nach der darauf folgenden Ausgabe durch die übliche Leerzeile geschlossen.
14. Logs abrufen
14.1. Übersicht
Über die Tabelle log
im Livestatus haben Sie direkten Zugriff
auf die Monitoring-Historie des Cores, so dass Sie mit der LQL bequem nach
bestimmten Ereignissen filtern können. Verfügbarkeiten werden zum Beispiel
auf Basis dieser Tabelle berechnet. Um die Übersicht zu erhöhen und eine
Abfrage thematisch einzugrenzen, haben Sie auf die folgenden Log-Klassen
zugriff:
Klasse | Beschreibung |
---|---|
0 |
Alle Nachrichten, welche nicht über andere Klassen abgedeckt sind |
1 |
Host- und Service-Alerts |
2 |
Wichtige Ereignisse des Programms |
3 |
Benachrichtigungen |
4 |
Passive Checks |
5 |
Externe Kommandos |
6 |
Initiale oder aktuelle Statuseinträge (z.B. nach einer Rotation des Logs) |
7 |
Änderungen des Programmstatus |
Mit Hilfe dieser Log-Klassen können Sie bereits sehr gut eingrenzen, welche Art von Einträgen angezeigt werden soll. Zusätzlich dazu wird der Zeitraum eingeschränkt, der bei der Abfrage berücksichtigt werden soll. Das ist wichtig, da andernfalls die gesamte Historie der Instanz durchsucht wird. Das kann logischerweise das System aufgrund der Informationsflut stark ausbremsen.
Eine weitere sinnvolle Einschränkung der Ausgabe sind die Spalten
(Columns
), die zu einem Eintrag angezeigt werden sollen. In dem
folgenden Beispiel wird nach allen Benachrichtigungen gesucht, welche in der
letzten Stunde geloggt wurden:
OMD[mysite]:~$ lq "GET log\nFilter: class = 3\nFilter: time >= $$(date +%s)-3600\nColumns: host_name service_description time state"
myserver123;Memory;1511343365;0
myserver234;CPU load;1511343360;3
myserver123;Memory;1511343338;2
myserver234;CPU load;1511342512;0
Wichtig: Achten Sie darauf, dass Sie im interaktiven Modus des Eingabe-Streams keine Variablen wie in dem Beispiel nutzen können. Und schränken Sie die Abfragen immer auf einen Zeitraum ein.
14.2. Die Monitoring-Historie konfigurieren
Sie haben die Möglichkeit, die Rotation der Dateien und deren maximale Größe zu beeinflussen. Zusätzlich können Sie auch bestimmen, wie viele Zeilen einer Datei eingelesen werden sollen, bevor Checkmk abbricht. Das alles kann, abhängig von dem Aufbau der Instanz, Auswirkungen auf die Performance Ihrer Abfragen haben. Es stehen dabei die folgenden drei Parameter zur Verfügung, welche Sie in unter Setup > General > Global Settings > Monitoring Core finden und anpassen können:
Name | Beschreibung |
---|---|
History log rotation: Regular interval of rotations |
Hier wird festgelegt, in welchem Zeitintervall die Historie in einer neuen Datei weitergeführt wird. |
History log rotation: Rotate by size (Limit of the size) |
Unabhängig von dem Zeitintervall wird hier die maximale Größe einer Datei festgelegt. Die Größe stellt einen Kompromiss zwischen der möglichen Leserate und den möglichen IOs dar. |
Maximum number of parsed lines per log file |
Nach der angegeben Anzahl an Zeilen wird eine Datei nicht weiter gelesen. Das verhindert Timeouts, falls eine Datei aus irgendwelchen Gründen doch sehr groß geworden sein sollte. |
15. Verfügbarkeiten prüfen
Mit der Tabelle statehist
können Sie die Rohdaten zu der
Verfügbarkeit von Hosts und Services abfragen und haben somit auf alle
Informationen Zugriff, die auch bei der Verfügbarkeit in der
Oberfläche genutzt werden. Geben Sie auch hier immer einen Zeitraum an,
da sonst alle verfügbaren Logs durchsucht werden, was das System sehr stark
auslasten kann. Zusätzlich gelten folgende Besonderheiten:
Der Zeitraum, in der ein Host/Service einen bestimmten Status hatte, kann sowohl absolut in Unix-Zeit ausgegeben werden, als auch relativ als prozentualer Anteil zum abgefragten Zeitraum.
In Zeiten, in denen ein Host/Service nicht überwacht wurde, ist der Status
-1
.
Die Überprüfung, ob, wann und wie lange ein Host/Service überwacht wurde, ist in Checkmk durch das Logging von initialen Status möglich. Dadurch können Sie nicht nur sehen, welcher Status zu einem bestimmten Zeitpunkt bestand, sondern auch nachvollziehen ob dieser zu diesem Zeitpunkt überhaupt überwacht wurde. Wichtig: Auch bei dem Nagios-Core ist dieses Logging aktiviert. Hier können Sie es jedoch deaktivieren:
log_initial_states=0
In dem folgenden Beispiel sehen Sie, wie die Abfrage einer prozentualen Verteilung und absoluten Zeiten von bestimmten Status aussieht. Als Zeitraum wurden hier die letzten 24 Stunden eingestellt und die Abfrage wurde auf die Verfügbarkeit eines Service von einem bestimmten Host eingeschränkt:
OMD[mysite]:~$ lq
GET statehist
Columns: host_name service_description
Filter: time >= 1511421739
Filter: time < 1511436139
Filter: host_name = myserver123
Filter: service_description = Memory
Stats: sum duration_ok
Stats: sum duration_warning
Stats: sum duration_critical
Stats: sum duration_part_ok
Stats: sum duration_part_warning
Stats: sum duration_part_critical
myserver123;Memory;893;0;9299;0.0620139;0;0.645764
Wie Sie eine vollständige Liste der verfügbaren Spalten abrufen, wird in der Befehlsreferenz näher erläutert.
16. Variablen im Livestatus
Sie können an verschiedenen Stellen in der Checkmk-Oberfläche Variablen
nutzen, um Hosts/Services kontextbezogen zuzuweisen. Einige dieser Daten
sind auch über Livestatus abrufbar. Da diese Variablen auch aufgelöst werden
müssen, stehen solche Spalten in einer Tabelle doppelt zur Verfügung:
Einmal als wörtlicher Eintrag und einmal als Variante, in der die Variable
durch den entsprechenden Wert ersetzt wurde. Ein Beispiel dafür ist die
Spalte notes_url
, welche eine URL mit der Variable ausgibt:
OMD[mysite]:~$ lq "GET hosts\nColumns: name notes_url"
myserver123;https://mymonitoring/heute/wiki/doku.php?id=hosts:$HOSTNAME$
Wenn Sie jedoch stattdessen die Spalte note_url_expanded
abfragen,
bekommen Sie den eigentlichen Wert des Makros ausgegeben:
OMD[mysite]:~$ lq "GET hosts\nColumns: name notes_url_expanded"
myserver123;https://mymonitoring/heute/wiki/doku.php?id=hosts:myserver123
17. Livestatus über das Netzwerk nutzen
17.1. Verbindung per TCP/IP
Um über das Netzwerk auf den Livestatus zuzugreifen, können Sie den Unix-Socket des Livestatus an einen TCP-Port binden. Auf diese Weise können Sie Skripte über das auf entfernten Maschinen ausführen und die Daten direkt dort erheben, wo sie auch verarbeitet werden sollen.
Den Zugriff über TCP aktivieren Sie bei abgeschalteter Site mit dem
omd
-Befehl:
OMD[mysite]:~$ omd config set LIVESTATUS_TCP on
Nach dem Start der Instanz ist Livestatus per TCP in der Regel auf dem Standardport 6557 aktiv. Bei Checkmk-Servern mit mehreren Sites, die Livestatus per TCP nutzen, wird der nächsthöhere freie Port gewählt.
Alle Einstellungen wie Port und berechtigte IP-Adressen können Sie per omd config
vornehmen.
Alternativ sind diese Einstellungen im Setup möglich.
In Checkmk ist SSL-Verschlüsselung der Livestatus-Kommunikation standardmäßig aktiviert:
Lokaler Test der SSL-Verbindung
Livestatus nutzt ein Zertifikat, welches beim Erstellen der Site automatisch generiert wird.
Dieses befindet sich mit allen anderen CA-Zertifikaten, denen die Site vertraut in der Datei var/ssl/ca-certificates.crt
.
Damit das Kommandozeilentool openssl s_client
das vom Livestatus-Server genutzte Zertifikat validieren kann, muss diese Datei als Certificate Authority File bekannt gemacht werden.
Die Ausgabe des Kommandozeilenaufrufs haben wir hier stark gekürzt, […]
zeigt die Auslassungen an:
OMD[mysite]:~$ openssl s_client -CAfile var/ssl/ca-certificates.crt -connect localhost:6557
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 CN = Site 'mysite' local CA
verify return:1
depth=0 CN = mysite
verify return:1
---
Certificate chain
0 s:CN = mysite
i:CN = Site 'mysite' local CA
1 s:CN = Site 'mysite' local CA
i:CN = Site 'mysite' local CA
---
Server certificate
[...]
Start Time: 1664965470
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
Erfolgt keine weitere Ausgabe mehr, können Sie interaktiv LQL-Kommandos absetzen, welche Sie mit einer Leerzeile (zweimal Return-Taste) abschließen.
Klappt dies, können Sie Livestatus-Abfragen auch per Pipeline übergeben, der zusätzliche Parameter -quiet
unterdrückt hier Debugging-Ausgaben:
OMD[mysite]:~$ echo -e "GET hosts\nColumns: name\n\n" | \
openssl s_client -quiet -CAfile var/ssl/ca-certificates.crt -connect localhost:6557
Can't use SSL_get_servername
depth=1 CN = Site 'mysite' local CA
verify return:1
depth=0 CN = mysite
verify return:1
myserver23
myserver42
myserver123
myserver124
Die Ausgabe vor den vier Hostnamen schreibt openssl
auf STDERR, Sie können diese durch anhängen von 2>/dev/null
unterdrücken.
Remote-Zugriff auf Livestatus
Wenn Sie von entfernten Rechnern auf Livestatus zugreifen, sollten Sie auf diesen nicht die gesamte Liste der von der Checkmk-Site vertrauten Zertifikate verwenden. Lesen Sie stattdessen alleine das Zertifikat der Site-CA aus dem Setup aus.
Begeben Sie sich hierfür nach Global Settings > Site management > Trusted certificate authorities for SSL.
Hier können Sie das verwendete Zertifikat der Site-CA per Copy and Paste übernehmen.
Kopieren Sie den kompletten Text des ersten Zertifikats unter Content of CRT/PEM file in eine Datei, im Beispiel verwenden wir /tmp/mysite_ca.pem
.
Wenn der entfernte Host nun für den Livestatus-Zugriff freigeschaltet wurde, sind mit dieser Zertifikatsdatei Livestatus-Abfragen per Skript möglich:
user@host:~$ echo -e "GET hosts\nColumns: name\n\n" | \
openssl s_client -quiet -CAfile /tmp/mysite_ca.pem -connect cmkserver:6557
Beachten Sie: Die Zertifikatsdatei bietet keine Authentifizierung, sie stellt lediglich die Transportverschlüsselung sicher! Zugriffsschutz wird ausschließlich über die IP-Adressen geregelt, welche auf den Livestatus-Port zugreifen dürfen.
Livestatus mit stunnel
Falls Sie einen entfernten verschlüsselten Livestatus Port als lokal unverschlüsselten Port erreichbar machen wollen, können Sie das Programm stunnel verwenden.
[pinning client]
client = yes
accept = 0.0.0.0:6557
connect = <myremotesiteip>:6557
verifyPeer = yes
CAfile = /etc/stunnel/myremotesite.pem
Nach Neustart des stunnel ist der Zugriff auf den lokalen Port unverschlüsselt möglich:
user@host:~$ echo -e "GET hosts\nColumns: name\n\n" | nc localhost 6557
SSL im Skript
Falls Sie per Skript via SSL auf Livestatus zugreifen wollen, verwenden Sie möglichst nicht openssl s_client
.
Primärer Zweck dieses Tools ist der Test des Verbindungsaufbaus und das Debugging von Zertifikatsketten.
Um im Falle von Verbindungsabbrüchen zu erkennen, ob die erwartete Ausgabe vollständig war, empfehlen wir, den ResponseHeader
auszuwerten.
Ein gut gepflegtes API, welches SSL und Header-Auswertung unterstützt, ist jenes für Python, das Sie unter share/doc/check_mk/livestatus/api/python
finden.
Weitere APIs listet das Kapitel Dateien und Verzeichnisse.
17.2. Verbindung über SSH
Wenn Zugriff auf Livestatus von außerhalb Ihres lokalen Netzwerkes erforderlich ist, mag Zugriffsschutz alleine auf Basis von IP-Adressen nicht praktikabel sein. Der einfachste Weg, authentifizierten Zugriff zu erlangen, ist hier die Verwendung der Secure Shell.
Mit SSH haben Sie die Möglichkeit, ein Kommando zu übergeben, welches auf dem entfernten Server ausgeführt wird:
user@host:~$ ssh mysite@myserver 'lq "GET hosts\nColumns: name"'
myserver123
myserver234
Alternativ können Sie den Livestatus-Port per SSH-Tunnel auf den Host weiterleiten, auf dem Sie aktuell arbeiten:
user@host:~$ ssh -L 6557:localhost:6557 mysite@myserver
Wenn die Verbindung steht, können Sie in einer zweiten Konsolensitzung testen, ob mit openssl s_client
Zugriff möglich ist:
user@host:~$ openssl s_client -CAfile /tmp/mysite_ca.pem -connect localhost:6557
Klappt dieser Test, können Sie jedes Skript, dass Sie für direkten Livestatus-Netzwerkzugriff geschrieben haben, auf localhost
einsetzen.
18. Kommandos setzen
18.1. Übersicht
Sie können Livestatus nicht nur für die Abfrage von Daten nutzen,
sondern auch, um Kommandos live und direkt an den Core (CMC oder Nagios) zu
schicken. Ein korrektes Kommando enthält immer einen Zeitstempel. Dieser
kann zwar beliebig sein. Da er aber in den Logs dazu
benutzt wird, den Zeitpunkt der Ausführung nachzuvollziehen, ist es
sinnvoll, möglichst die exakte Zeit anzugeben. Kommandos mit fehlendem
Zeitstempel werden ohne Fehlermeldung und lediglich mit einem Eintrag im
cmc.log
verworfen!
Damit der Zeitstempel so genau, wie möglich ist, bietet es sich an, das Kommando nicht über den Eingabe-Stream zu setzen, sondern direkt zu übergeben. Sie haben in diesem Fall auch Zugriff auf Variablen und können automatisch die gerade aktuelle Zeit übergeben:
OMD[mysite]:~$ lq "COMMAND [$(date +%s)] DISABLE_NOTIFICATIONS"
Dieses Format funktioniert sowohl mit dem Nagios-Core von Checkmk Raw, als auch mit dem CMC der kommerziellen Editionen. Allerdings überschneiden sich bei den beiden Cores nur teilweise die Kommandos. Eine vollständige Liste der Kommandos für den Nagios-Core finden Sie direkt auf der Internetseite von Nagios. Die für Checkmk relevanten und für den CMC verfügbaren Kommandos finden Sie in der Befehlsreferenz.
18.2. Besonderheiten bei Nagios
In der Liste der Kommandos werden Sie die Syntax in der folgenden Form vorfinden:
#!/bin/sh
# This is a sample shell script showing how you can submit the CHANGE_CUSTOM_HOST_VAR command
# to Nagios. Adjust variables to fit your environment as necessary.
now=`date +%s`
commandfile='/usr/local/nagios/var/rw/nagios.cmd'
/bin/printf "[%lu] CHANGE_CUSTOM_HOST_VAR;host1;_SOMEVAR;SOMEVALUE\n" $now > $commandfile
Wie Sie gelernt haben, benutzt Checkmk ein sehr viel einfacheres Format für die Übergabe des Kommandos. Um dieses Format für Checkmk kompatibel zu übertragen, benötigen Sie lediglich das Kommando, den Zeitstempel und gegebenenfalls die Variablen:
OMD[mysite]:~$ lq "COMMAND [$(date +%s)] CHANGE_CUSTOM_HOST_VAR;host1;_SOMEVAR;SOMEVALUE"
19. Dateien und Verzeichnisse
Pfad | Bedeutung |
---|---|
|
Der Unix-Socket zur Übergabe der Abfragen und Kommandos. |
|
Skriptbefehl für die einfachere Übergabe der Abfragen und Kommandos and den Unix-Socket des Livestatus. |
|
Die Logdatei des CMC, in der unter anderem die Abfragen/Kommandos dokumentiert werden. |
|
Die Logdatei des CMC, in der alle zur Laufzeit des Core auftretenden Änderungen eingetragen werden, wie z.B. Statusänderungen eines Host/Service. |
|
Hier werden die |
|
Die Logdatei des Nagios-Core, in der unter anderem die Abfragen/Kommandos dokumentiert werden. |
|
Hier werden die |
|
In diesem Verzeichnis finden Sie einige Beispiele zu Livestatus-Abfragen, die Sie ausprobieren können. Die Beispiele werden an den Skriptbefehl |
|
In diesem Verzeichnis finden Sie die API zu Python sowie einige Beispiele. Lesen Sie auch das |
|
Die API zu Perl finden Sie hier. Auch hier gibt es wieder ein |
|
Zu der Programmiersprache C++ finden Sie hier ebenfalls Beispielcode. Der Code zu der API selbst liegt ebenfalls unkompiliert vor, so dass Sie maximalen Einblick in die Funktionsweise der API haben. |