Zum Hauptinhalt springen

Anleitungen / Monitoring-Anleitungen: jeder Prüfungstyp, Schritt für Schritt

Assertion-Modus: die vollständige Referenz

Der Assertion-Modus ersetzt die festen Bestanden/Fehlgeschlagen-Felder eines Monitors durch eine Liste selbst geschriebener Regeln, wobei jede Regel genau benennt, was an der Antwort wahr sein muss. Die meisten Uptime-Monitore beurteilen eine Prüfung anhand einer Handvoll fester Felder: ein Statuscode, der als "down" gilt, eine Liste zu ignorierender Status, vielleicht ein Schlüsselwort, das irgendwo im Body erscheinen muss. Diese Felder können nicht ausdrücken, dass eine API legitim mit 404 für eine fehlende Ressource antwortet, dass eine Seite 200 mit einer leeren Hülle zurückgibt, weil die Datenbank ein Timeout hatte, oder dass eine Weiterleitungskette beginnt, über die Domain eines anderen zu laufen.

Der Assertion-Modus von HostTracker ersetzt diese festen Felder durch eine kleine, selbst geschriebene Regelsprache, Regel für Regel, direkt im Monitor-Editor. Jede Regel sagt genau, was an der Antwort wahr sein muss: der Status, ein Teil des Bodys, ein Header, wie lange es gedauert hat, wo eine Weiterleitung endete. Eine Prüfung schlägt nur fehl, wenn eine Ihrer Regeln fehlschlägt. Es ist dieselbe Sprache für eine Website, eine REST-API, eine Datenbankabfrage, einen TCP-Port, ein Ping-Ziel, einen SNMP-Zähler oder eine generische Counter-Prüfung: ein Satz Subjekte, ein Satz Prädikate, überall dort wiederverwendet, wo der Modus vorkommt. Diese Anleitung behandelt jedes Subjekt, jeden Operator, jeden Reducer, jede Sugar-Abkürzung und jede Syntaxform, die die Engine implementiert.

Was der Assertion-Modus ersetzt

Die klassischen Response-Validation-Felder sind weiterhin vorhanden, wenn der Assertion-Modus aus ist: ein erwarteter Statusbereich, eine Liste zu ignorierender Status, ein Schlüsselwort, das (nicht) vorkommen darf. Der Modus ist ein Schalter, der diesen festen Satz gegen eine selbst gebaute Regelliste tauscht, und ihn vor dem Speichern wieder auszuschalten, stellt die klassischen Felder unverändert wieder her. Kein Monitor ist dauerhaft an einen Modus gebunden.

Eine Sprache statt eines Haufens typspezifischer Einzellösungen fügt sich zusammen. Eine Prüfung "muss JSON sein und ein Feld enthalten", eine Prüfung "muss weiterhin 'Add to cart' sagen" und eine Prüfung "darf nicht langsamer geworden sein" sind drei Regeln in derselben Syntax, in derselben Liste, jede für sich bestehend oder fehlschlagend.

Ihn einschalten

Der Assertion-Modus liegt im Abschnitt Response Validation des Monitor-Editors, für HTTP-(Website-) und API-Monitore. Legen Sie den Schalter um, und die klassischen Felder werden durch eine nummerierte Regelliste ersetzt, mit einer Schaltfläche "Add rule" und einem Live-Zähler, der zeigt, wie viele Regeln Sie im Verhältnis zum Limit Ihres Plans bereits verwendet haben.

Assertion mode switched on, with the first rule built and validated

Jede Regel wird beim Aufbau validiert: Eine noch nicht fertige Regel trägt einen eigenen "unfinished"-Status, und eine Regel, die der Editor auswerten kann, wird als vollständig markiert. Jede Regel hat außerdem eine kleine </>-Schaltfläche, die ihre Klartext-Quellform öffnet, sodass Sie den genauen Ausdruck statt nur der Kästchen-für-Kästchen-Ansicht lesen oder kopieren können.

Das mentale Modell: Subjekt, Prädikat, Wert

Jede Regel hat dieselbe Form: ein Subjekt (der Statuscode, der Body, ein Header, die Antwortzeit), ein Prädikat (gleich, enthält, existiert, ist kleiner als) und, für die meisten Prädikate, einen Wert, mit dem verglichen wird. status eq 200 ist Subjekt, Prädikat und Wert; body.json exists ist ein Subjekt und ein Prädikat ohne Wert, weil "exists" nichts weiter braucht.

Eine Regel im Editor zu bauen beginnt damit, auszuwählen, was geprüft werden soll, dann die Bedingung, dann den Wert:

Building a second rule: the field picker lists every subject with its type and an example

Regeln in der Liste werden mit UND verknüpft: Eine Prüfung schlägt fehl, wenn eine einzelne Regel fehlschlägt, und besteht nur, wenn jede Regel besteht. Ein ODER gibt es noch nicht, um also einen von mehreren Status oder Strings zu akzeptieren, drücken Sie das innerhalb einer einzigen Regel aus (status in [200, 301, 302], body containsAny ["In stock", "Pre-order"]). Eine fehlschlagende Regel nennt sich selbst im Alarm, geben Sie also jeder, wo möglich, eine kurze Bezeichnung, und der Alarm sagt, welche Erwartung gebrochen wurde.

Was Sie prüfen können

Die Auswahl gruppiert Subjekte in das eigene Dokument der Antwort (den Body, die Header) und ihren Transport (Status, Timing, Weiterleitungen, TLS). Einige der wichtigsten Subjekte, mit der vollständigen Liste in der folgenden Referenz:

SubjektWas es istBeispiel
statusDer HTTP-Statuscode der endgültigen Antwort, nach Verfolgung aller Weiterleitungenstatus isOk
bodyDer Antwort-Body als Klartextbody contains "Add to cart"
body.json / body.xml / body.html / body.yamlDer Body, aber nur, wenn er sich tatsächlich als dieses Format parsen lässt, andernfalls ist das Subjekt schlicht nicht vorhandenbody.json exists
body.json.path("$.a")Eine JSONPath-Abfrage in einen JSON-Body (dieselbe Abfragesprache funktioniert auch über YAML, da YAML in dasselbe Objektmodell geparst wird)body.json.path("$.status") eq "ok"
body.size / body.hashDie Antwortgröße in Bytes und ein Fingerabdruck des Body-Inhaltsbody.size gt 1kb
header("Name")Ein Antwort-Header, nach Namen nachgeschlagenheader("Content-Type") isJson
time sowie time.connect / time.tls / time.dns / time.headGesamte Antwortzeit, und ihre Netzwerk-, TLS-Handshake-, DNS- und Server-Denkzeit-Phasentime lt 2s
redirects / requestsDie von einer Prüfung durchlaufenen Sprünge, und die vollständige Kette (einschließlich der finalen Antwort)redirects.count eq 0
url und seine Teile (.host, .scheme, .path…)Die finale URL, bei der die Prüfung gelandet isturl.scheme eq "https"
cert.days.leftVerbleibende Tage bis zum Ablauf des TLS-Zertifikatscert.days.left gt 14

Zahlen akzeptieren Einheiten-Suffixe, damit Sie nie von Hand umrechnen müssen: 2s bedeutet 2000 Millisekunden, 1kb bedeutet 1024 Byte. Textvergleiche unterscheiden Groß- und Kleinschreibung, sofern Sie der Regel nicht nocase hinzufügen.

Die vollständige Referenz

Im Folgenden finden Sie jedes Subjekt, jeden Operator, jeden Reducer, jede Sugar-Abkürzung, jeden Filter und jede Syntaxform, die die Assertion-Engine für HTTP- und API-Prüfungen registriert, direkt aus der eigenen Registry der Engine (denselben Daten, die auch die Auswahllisten und die Dokumentation des Regel-Editors speisen). Einträge, die noch nicht allgemein verfügbar sind, tragen einen Hinweis in Klammern: reservierte Felder, die noch von keinem Agenten befüllt werden, Kandidaten, die noch auf Agenten ausgerollt werden, und die zustandsbehaftete Familie, die einen bestimmten Plan braucht. Alles ohne einen solchen Hinweis ist heute auf jedem Plan mit Assertion-Modus live.

Die Referenz folgt der eigenen Gruppierung der Engine: Antwortfelder, dann die Wege, in einen Body hineinzugreifen, dann Timing, Netzwerk und TLS, dann die Operatoren, Reducer und Abkürzungen, die auf allen davon funktionieren, dann die Prüfungsarten jenseits von HTTP, die dieselbe Sprache sprechen.

Antwort

Die Subjekte, die die Antwort selbst beschreiben: ihr Status, ihr roher Body, ihre Header, die URL, von der sie tatsächlich geantwortet hat, und die Kette der Requests, die dorthin geführt haben.

NameWas es istTyp/WerteBeispiel
bodyDer Antwort-Body als dekodierter Text.stringbody contains "Welcome"
headerEin Antwort-Header der finalen Antwort, nach Namen.stringheader("Content-Type") isJson
redirectsDie verfolgten Weiterleitungssprünge, die Request-Kette ohne ihr letztes Element.collectionredirects.count eq 0
statusDer HTTP-Statuscode der finalen Antwort, nach Verfolgung der Weiterleitungen.numberstatus isOk
body.sizeDie Größe des heruntergeladenen Bodys, in Byte.numberbody.size lt 500000
urlDie URL, die nach allen Weiterleitungen tatsächlich geantwortet hat. Vergleichen Sie eine url als Text, oder lesen Sie ihre Teile (url.host, .port, .path, .query, .scheme).urlurl.host eq "www.example.com"
requestsJeder Request dieser Prüfung, in Reihenfolge, die Weiterleitungssprünge und dann der finale Request.collectionrequests.count le 2
url.hostDer Host-Teil der URL.stringurl.host eq "example.com"
url.pathDer Pfad-Teil der URL.stringurl.path startsWith "/api"
url.portDer Port-Teil der URL.numberurl.port eq 443
url.queryDer Query-String der URL.stringurl.query contains "token"
url.schemeDas Schema der URL (http oder https).stringurl.scheme eq "https"
body.hashEin Digest des Antwort-Bodys, vergleichen Sie ihn mit previous.body.hash, um Inhaltsänderungen zu erkennen.stringbody.hash eq previous.body.hash
httpVersion (reserviert, noch nicht befüllt)Die ausgehandelte HTTP-Version.stringhttpVersion eq "HTTP/2"
setCookieDie Set-Cookie-Werte der finalen Antwort, ein Eintrag pro Cookie, gleichen Sie einen mit contains oder matches ab, zählen Sie mit .count.collectionsetCookie exists
steps (noch nicht verfügbar)Die Schritte einer mehrstufigen Prüfung. Noch nicht verfügbar.collectionsteps.count le 1
url.originalDie URL, mit der die Prüfung konfiguriert wurde, vor jeder Weiterleitung. Eine url wie url selbst: sie hat dieselben Teile (url.original.host, .port, .path, .query, .scheme).urlurl.original.scheme eq "http"
url.original.hostDer Host-Teil der URL.stringurl.original.host eq "example.com"
url.original.pathDer Pfad-Teil der URL.stringurl.original.path startsWith "/start"
url.original.portDer Port-Teil der URL.numberurl.original.port eq 80
url.original.queryDer Query-String der URL.stringurl.original.query contains "utm_"
url.original.schemeDas Schema der URL (http oder https).stringurl.original.scheme eq "http"

Zwei Aliasse: redirectCount ist die Kurzform von redirects.count, redirectCount eq 0 liest sich etwas natürlicher als die entsprechende Langform, wenn Sie meinen "die Prüfung hat direkt geantwortet, keine Weiterleitungen". Und setCookie auf oberster Ebene ist die Cookie-Liste der finalen Antwort; derselbe Name taucht pro Sprung innerhalb von requests/redirects erneut auf (siehe Sprung-Subjekte unten) und hält dann nur die Cookies dieses einen Requests.

Werte aus dem Body extrahieren

Diese Subjekte lösen sich nur auf, wenn der Body das von ihnen benannte Format ist: ein JSON-Namensraum auf einer HTML-Seite ist schlicht nicht vorhanden, kein typisierter Fehler. Das macht exists zum Standardweg, das Format zu prüfen, und body.json exists fragt, ob sich der Body als JSON parsen ließ. Die vier Format-Namensräume tragen jeweils eine passende .path(...)-Abfragefunktion (JSONPath für json/yaml, XPath für xml, CSS-Selektoren für html) und ein passendes .regex(...), dazu ein formatunabhängiges body.regex(...), das den rohen Text unabhängig vom Format liest. body.html.a, body.html.script und body.html.link sind fertige Sammlungen jedes Links, Scripts und <link>-Elements der Seite; siehe Elementbereiche unten für die je Element verfügbaren Felder.

NameWas es istTyp/WerteBeispiel
body.jsonDer Antwort-Body, aber nur, wenn er wirklich JSON ist.stringbody.json exists
body.json.pathFragt den JSON-Body mit einem JSONPath-Ausdruck ab.jsonbody.json.path("$.status") eq "ok"
body.htmlDer Antwort-Body, aber nur, wenn er wirklich HTML ist.stringbody.html exists
body.html.pathWählt Seitenelemente mit einem CSS-Selektor aus.collectionbody.html.path("h1").first contains "Welcome"
body.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists
body.xmlDer Antwort-Body, aber nur, wenn er wirklich XML ist.stringbody.xml exists
body.xml.pathFragt den XML-Body mit einem XPath-Ausdruck ab.stringbody.xml.path("//item/@id") exists
body.html.aJeder Link auf der Seite.collectionbody.html.a.count gt 0
body.html.linkJedes <link>, das die Seite deklariert. Eine bloße Nennung meint die Link-Ziele.collectionbody.html.link.count gt 0
body.html.scriptJedes Script, das die Seite lädt. Eine bloße Nennung meint die Script-Quellen.collectionbody.html.script.count gt 0
body.yamlDer Antwort-Body, aber nur, wenn er wirklich YAML ist.stringbody.yaml exists
body.yaml.pathFragt den YAML-Body mit einem JSONPath-Ausdruck ab.jsonbody.yaml.path("$.services.web.image") contains ":1."
body.html.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists
body.json.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists
body.xml.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists
body.yaml.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists

Ein Detail der Regex-Familie ist erwähnenswert: benannte Erfassungsgruppen ((?<id>...)) innerhalb einer .regex(...)-Regel schreiben in einen prüfungsweiten Bindungs-Namensraum, den eine spätere Regel mit bind("id") oder bind[0] nach Position zurücklesen kann, siehe Erfasste Werte unten.

Erfasste Werte

Ein Subjekt lebt in seiner eigenen Registry-Gruppe, weil es nicht direkt die Antwort liest, sondern das, was eine frühere Regel daraus erfasst hat.

NameWas es istTyp/WerteBeispiel
bindEin Wert, den eine frühere Regex-Regel erfasst hat, nach Erfassungsname oder nach Position.stringbind("id") gt 1000

Kombinieren Sie es mit einer früheren Regex-Regel in der Liste: Eine Regel wie body.regex("order-(?<id>\d+)") exists erfasst die Bestell-ID unter dem Namen id, und eine spätere Regel kann sie mit bind("id") gt 1000 oder, für eine positionale (unbenannte) Erfassung, mit bind[0] prüfen.

Timing

Eine Gesamtzeit plus eine Aufschlüsselung nach Phase, sodass ein "langsamer geworden"-Alarm auch sagen kann, welcher Teil langsamer wurde.

NameWas es istTyp/WerteBeispiel
timeGesamte Antwortzeit: Verbindungsaufbau + TLS + Warten + Download. Die DNS-Auflösung ist nicht enthalten.numbertime lt 2000
ttfb (reserviert, noch nicht befüllt)Time to first byte.numberttfb lt 200
time.connectZeit für den Aufbau der TCP-Verbindung.numbertime.connect lt 500
time.dataZeit für den Download des Antwort-Bodys.numbertime.data lt 1000
time.dnsZeit für die Auflösung des Domainnamens. Nicht im bloßen time-Subjekt enthalten.numbertime.dns lt 200
time.headWartezeit auf die Antwort-Header.numbertime.head lt 500
time.tlsZeit für den TLS-Handshake.numbertime.tls lt 300

Das bloße Subjekt time ist Verbindungsaufbau + TLS + Warten-auf-Header + Herunterladen des Bodys. Die DNS-Auflösung ist ausgeschlossen und lebt nur im Geschwisterfeld time.dns, weil DNS oft zwischengespeichert ist und sonst denselben Endpunkt zwischen Prüfungen inkonsistent schnell oder langsam erscheinen ließe.

Netzwerk: DNS und Verbindung

dns und conn sind reine Namensräume in der Registry, eine Gruppe ohne eigenen Wert, sodass eine Regel nie auf dem bloßen Namen enden kann (Editor und Engine lehnen beide eine Kette ab, die allein auf dns oder conn endet, und verweisen auf die echten Felder unten).

NameWas es istTyp/WerteBeispiel
connDie von der Prüfung aufgebaute Netzwerkverbindung, die Adresse, die die Antwort ausgeliefert hat, und etwaige Verbindungsfehler.string-
conn.failedWie viele der aufgelösten Adressen die Verbindung nicht aufbauen konnten.numberconn.failed eq 0
conn.failedIps (Kandidat, wird auf Agenten ausgerollt)Die aufgelösten Adressen, bei denen die Verbindung fehlschlug.collectionconn.failedIps.count eq 0
conn.ipDie IP-Adresse, die die Antwort tatsächlich ausgeliefert hat.stringconn.ip eq "203.0.113.10"
conn.ip.family (Kandidat, wird auf Agenten ausgerollt)Ob die Antwort über IPv4 oder IPv6 ausgeliefert wurde.stringconn.ip.family eq "IPv4"
dnsDNS-Auflösung des überwachten Namens, auf welche Adressen er aufgelöst wurde und welcher Server geantwortet hat.string-
dns.ipsAlle IP-Adressen, auf die der Domainname bei dieser Prüfung aufgelöst wurde.collectiondns.ips contains "1.2.3.4"
dns.serverDer DNS-Server, der die Auflösung beantwortet hat.stringdns.server eq "8.8.8.8"

TLS und Zertifikat

Wie dns und conn sind auch tls und cert reine Namensräume, die Zertifikats-/Handshake-Fakten liegen eine Ebene tiefer.

NameWas es istTyp/WerteBeispiel
cert.days.leftVerbleibende Tage bis zum Ablauf des Seitenzertifikats.numbercert.days.left gt 14
certDas vom Server präsentierte Zertifikat, Tage bis zum Ablauf, Aussteller und Identitätsfelder.string-
cert.daysTage seit Ausstellung des Zertifikats.numbercert.days gt 0
cert.issuerDie Zertifizierungsstelle, die das Seitenzertifikat ausgestellt hat.stringcert.issuer contains "Let's Encrypt"
cert.sanDie Domainnamen, für die das Zertifikat gültig ist.collectioncert.san contains "www.example.com"
cert.serialDie Seriennummer des Zertifikats.stringcert.serial exists
cert.subject (reserviert, noch nicht befüllt)Der Subject des Zertifikats. Noch nicht erfasst, kommt mit einer künftigen Agentenversion.stringcert.subject contains "example.com"
tlsDer TLS-Handshake der gesicherten Verbindung, ausgehandelte Protokollversion und Cipher.string-
tls.cipherDie ausgehandelte Cipher Suite.stringtls.cipher contains "AES"
tls.protocolDie ausgehandelte TLS-Version.stringtls.protocol eq "Tls13"

cert.subject ist hier der Vollständigkeit halber aufgeführt, aber noch nicht befüllt, siehe den Abschnitt Ehrlichkeit unten dafür, was "reserviert" in der Praxis bedeutet. Die alltägliche Zertifikatsregel ist cert.days.left gt 14, behandelt im Abschnitt mit den ausgearbeiteten Regeln.

Sprung-Subjekte: Felder innerhalb von requests und redirects

requests und redirects sind Sammlungen, und jedes Element ist ein vollständiger Request-/Response-Datensatz mit einem eigenen, reduzierten Feldsatz. Nicht jedes Subjekt der obersten Ebene ergibt pro Sprung Sinn (ein Sprung hat kein eigenes Zertifikat), und ein Feld existiert nur pro Sprung: hstsHeader, der Strict-Transport-Security-Header dieses Requests in der Kette.

NameWas es istTyp/WerteBeispiel
statusDer Statuscode dieses Requests in der Kette.numberstatus eq 200
urlDie URL, an die dieser Request ging.urlurl startsWith "https://"
headerEin Antwort-Header dieses Requests. Ein Sprung führt einen reduzierten Header-Datensatz mit einem Wert je Header, listenförmige Prädikate (containsAny, containsAll, unique) gelten nur für den Header der finalen Antwort.stringheader("Content-Type") contains "json"
hstsHeaderDer Strict-Transport-Security-Header dieses Requests.stringrequests[0].hstsHeader exists
setCookieDie Set-Cookie-Header-Werte dieses Requests.collectionsetCookie exists
url.originalDie URL, mit der die Prüfung konfiguriert wurde, vor jeder Weiterleitung. Eine url wie url selbst: sie hat dieselben Teile (url.original.host, .port, .path, .query, .scheme).urlurl.original.scheme eq "http"
url.hostDer Host-Teil der URL.stringurl.host eq "example.com"
url.portDer Port-Teil der URL.numberurl.port eq 443
url.pathDer Pfad-Teil der URL.stringurl.path startsWith "/api"
url.queryDer Query-String der URL.stringurl.query contains "token"
url.schemeDas Schema der URL (http oder https).stringurl.scheme eq "https"
url.original.hostDer Host-Teil der URL.stringurl.original.host eq "example.com"
url.original.portDer Port-Teil der URL.numberurl.original.port eq 80
url.original.pathDer Pfad-Teil der URL.stringurl.original.path startsWith "/start"
url.original.queryDer Query-String der URL.stringurl.original.query contains "utm_"
url.original.schemeDas Schema der URL (http oder https).stringurl.original.scheme eq "http"

Das pro-Sprung header(...) führt einen reduzierten Datensatz mit einem Wert je Header: listenförmige Prädikate wie containsAny oder unique ergeben nur bei der vollständigen Header-Map der finalen Antwort Sinn, sie gelten also dort und nicht pro Sprung. Die beiden Sammlungen bedeuten Unterschiedliches. requests ist die gesamte Kette einschließlich der finalen Antwort, die geantwortet hat, also nie leer, selbst bei einem direkten 200, während redirects nur die auf dem Weg dorthin verfolgten Sprünge sind, leer, wenn nichts weitergeleitet wurde.

Elementbereiche: Felder innerhalb eines Sammlungselements

Ein Elementbereich ist der Feldsatz, der für EIN Element einer Sammlung verfügbar ist, nach Indizierung hinein (requests[0]) oder beim Filtern mit where(current. ...) (siehe den nächsten Abschnitt). Sechs Sammlungen tragen einen eigenen Elementbereich: Die vier HTML-Element-Sammlungen teilen sich eine Form, und requests/redirects teilen sich die oben dokumentierte Sprung-Subjekt-Form.

ElementbereichWie ein Element aussieht
body.html.pathEin von einer body.html.path("selector")-CSS-Abfrage getroffenes Element.
body.html.aEin <a>-Link-Element aus body.html.a.
body.html.scriptEin <script>-Element aus body.html.script.
body.html.linkEin <link>-Element aus body.html.link.
requestsEin Request in der vollständigen Kette (siehe die Sprung-Subjekt-Tabelle oben).
redirectsEin verfolgter Weiterleitungssprung (dieselben Felder wie requests, siehe oben).

Die gemeinsame Form für body.html.path(...), body.html.a, body.html.script und body.html.link, eine Zeile pro Link, Script-Tag oder <link>-Element:

NameWas es istTyp/WerteBeispiel
urlDas Link-Ziel genau so, wie es das Markup schreibt.stringbody.html.a.url contains "/checkout"
textDer sichtbare Text des Elements.stringbody.html.a.text contains "Sign in"
absoluteDas Link-Ziel, gegen die Seiten-URL zu einer absoluten Adresse aufgelöst, eine Liste von URLs, mit den URL-Teilen je Element verfügbar (.host, .path, .port, .query, .scheme).urlbody.html.a.absolute.scheme in ["https"]
relDas rel-Attribut des Elements.stringbody.html.a.where(current.rel eq "nofollow").count eq 0
absolute.hostDer Host-Teil der URL.stringbody.html.a.absolute.host.unique.count le 3
absolute.portDer Port-Teil der URL.numberbody.html.a.absolute.port in [443]
absolute.pathDer Pfad-Teil der URL.stringbody.html.a.absolute.path startsWith "/"
absolute.queryDer Query-String der URL.stringbody.html.a.absolute.query not contains "session"
absolute.schemeDas Schema der URL (http oder https).stringbody.html.a.absolute.scheme in ["https"]

Zwei Standardregeln gelten, bevor Sie eine Regel gegen diese Sammlungen schreiben. Eine bloße Nennung von body.html.a (oder .script/.link) meint ihre .url-Projektion, sodass body.html.a.count gt 0 Hrefs zählt, und eine gespeicherte Regel liest sich mit ausgeschriebenem .url zurück, weil eine gespeicherte Regel immer genau sagt, was sie auswertet. Und .url ist das rohe href-Attribut genau so, wie das Markup es geschrieben hat, ein relativer Link bleibt also relativ; .absolute ist derselbe Link, gegen die eigene URL der Seite aufgelöst, was Sie wollen, wenn Sie Schema oder Host ausgehender Links prüfen (body.html.a.absolute.scheme in ["https"]).

Operatoren

Die Prädikat-Hälfte jeder Regel: welcher Test gegen das Subjekt läuft. Alle 15 werden über jede Prüfungsart hinweg geteilt, und welche zu einem gegebenen Subjekt passen, hängt von dessen Typ ab (ein Statuscode nimmt lt/gt, ein Body nimmt contains, eine Sammlung nimmt exists/unique/in).

NameWas es istGilt fürBeispiel
eqGleich. Gegenüber einem json("…")/xml("…")/yaml("…")-Literal ist es ein EXAKTER struktureller Abgleich: gleiche Schlüssel (beliebige Reihenfolge), Arrays in Reihenfolge, gleiche Werte.beliebiger Typbody.json eq json("{\"ok\": true}")
ltKleiner als.Zahlentime lt 2000
leKleiner oder gleich.Zahlencert.days.left le 30
gtGrößer als.Zahlenbody.size gt 0
geGrößer oder gleich.Zahlenstatus ge 500
containsEnthält den Text, bei einer Liste besteht es, wenn der Wert eines der Elemente IST (exakter Abgleich, verwenden Sie matches, um innerhalb von Elementen zu suchen). Gegenüber einem json("…")/xml("…")/yaml("…")-Literal ist es STRUKTURELLE Enthaltenheit: alles, was das Literal angibt, muss vorhanden sein und übereinstimmen, die Antwort darf mehr haben.Text oder Listebody.json contains json("{\"status\": \"ok\"}")
startsWithBeginnt mit dem Text, bei einer Liste, wenn IRGENDEIN Element das tut.Texturl.path startsWith "/api"
endsWithEndet mit dem Text, bei einer Liste, wenn IRGENDEIN Element das tut.Texturl.path endsWith ".json"
matchesTrifft den regulären Ausdruck irgendwo im Text, bei einer Liste, wenn IRGENDEIN Element das tut.Textbody matches "order-\\d+"
containsAnyEnthält mindestens einen der aufgelisteten Werte (bei einer Liste: ein Element ENTSPRICHT einem davon).Listebody containsAny ["In stock", "Pre-order"]
containsAllEnthält jeden der aufgelisteten Werte (bei einer Liste: jeder Wert entspricht einem Element, die Belege dürfen unterschiedlich sein).Listebody.html.a.text containsAll ["Home", "Contact"]
inIst einer der aufgelisteten Werte oder Bereiche, bei einer Liste, jedes Element ist es.Wert(e) oder Bereichstatus in [200, 301, 302]
existsDas Subjekt ist vorhanden.beliebiges Subjektheader("ETag") exists
isNumberDer Wert liest sich als Zahl.Text oder beliebigbind("id") isNumber
uniqueDie Liste hat keine Duplikate.Listedns.ips unique

Zwei Operatoren bedeuten etwas Engeres, als sie klingen. contains bei einer Liste ist exakte Mitgliedschaft: Der Wert muss einem ganzen Element entsprechen, nicht als Teilstring darin vorkommen, greifen Sie also zu matches, wenn Sie Teilstring-Verhalten über Elemente einer Sammlung wollen. Und eq gegenüber einem json(...)/xml(...)/yaml(...)-Literal ist ein vollständiger struktureller Abgleich (gleiche Schlüssel, Arrays in derselben Reihenfolge, gleiche Werte), während contains gegenüber demselben Literaltyp strukturelle Enthaltenheit ist: alles, was das Literal angibt, muss vorhanden sein, aber die echte Antwort darf mehr tragen.

Reducer

Ein Reducer reduziert eine Sammlung auf einen Wert und kann nur am Ende einer Kette stehen. Die folgenden Beispiele verwenden requests.status, die eine natürlich numerische Sammlung, die HTTP-Subjekte bilden, als Illustration; dieselben acht Reducer funktionieren über jeder numerischen Sammlung in jeder Prüfungsart (die Umlaufzeiten einer Ping-Prüfung, eine gefilterte Menge Datenbankzeilen).

NameWas es reduziertGilt fürBeispiel
countWie viele Elemente die Liste hat.beliebige Sammlungrequests.count le 2
minDie kleinste Zahl in der Liste.numerische Sammlungrequests.status.min ge 200
maxDie größte Zahl in der Liste.numerische Sammlungrequests.status.max lt 500
sumDie Summe der Zahlen in der Liste.numerische Sammlungrequests.status.sum gt 0
avgDer Durchschnitt der Zahlen in der Liste.numerische Sammlungrequests.status.avg lt 300
firstDas erste Element der Liste.beliebige Sammlungredirects.status.first eq 301
lastDas letzte Element der Liste.beliebige Sammlungrequests.status.last eq status
uniqueDie Liste ohne Duplikate.beliebige Sammlungdns.ips.unique.count le 3

unique ist doppelt belegt, und die Schreibweise unterscheidet die zwei Bedeutungen. Als Operator ohne Punkt geschrieben (x unique) ist es ein Prädikat, "diese Sammlung hat keine Duplikate", und es scheitert, indem es die Wiederholung benennt. Als Reducer mit Punkt geschrieben (x.unique) ist es eine Transformation, die deduplizierte Sammlung selbst, die immer noch etwas danach braucht (x.unique.count eq 1). Ein baumelndes x.unique ohne etwas Folgendem ist ein Syntaxfehler, weil die Engine nicht raten kann, welche der beiden Bedeutungen Sie meinten.

Sugar

Sugar-Prädikate sind Abkürzungen, die die Engine in gewöhnliche Kern-Prädikate umwandelt, bevor die Regel je an einen Agenten gesendet wird, ein Sugar-Prädikat hinzuzufügen kostet nichts extra (kein Agent-Bundle, keine Versionsuntergrenze), weil es bereits wie eine gewöhnliche Regel aussieht, sobald es auf der Leitung ankommt. Bevorzugen Sie Sugar, wo immer es existiert: Es liest sich besser und ist exakt gleichwertig damit, die lange Form von Hand auszuschreiben.

NameWas es bedeutetGilt fürBeispiel
isOkDer Status ist ein Erfolgscode (200-299).status-
isRedirectDer Status ist ein Weiterleitungscode (300-399).statusstatus isRedirect
isClientErrorDer Status ist ein Client-Fehler (400-499).statusstatus isClientError
isServerErrorDer Status ist ein Server-Fehler (500-599).statusstatus isServerError
isJsonDer Inhalt ist wirklich JSON.Dokument oder Medientyp-Textheader("Content-Type") isJson
isXmlDer Inhalt ist wirklich XML, der Body parst als XML, oder ein Header nennt einen XML-Medientyp.Dokument oder Medientyp-Textbody isXml
isHtmlDer Inhalt ist wirklich HTML, der Body parst als HTML, oder ein Header nennt einen HTML-Medientyp.Dokument oder Medientyp-Textbody isHtml
isFormEin Medientyp nennt eine Formularkodierung: application/x-www-form-urlencoded oder multipart/form-data. Anders als isJson/isXml/isHtml gibt es keinen passenden Body-Namensraum, das gilt also nur für einen Medientyp-Wert wie einen Content-Type-Header.nur Medientyp-Textheader("Content-Type") isForm
isEmptyNichts da: ein leerer Text, eine Größe von null oder eine leere Liste.Text, Größe oder Listebody isEmpty
isNullDer Wert ist null.beliebiger Wertbody.json.path("$.deletedAt") isNull
absentDas Subjekt ist überhaupt nicht vorhanden.beliebiges Subjektheader("X-Debug") absent
betweenEine Zahl innerhalb eines einschließenden Bereichs.Zahlen (2 Operanden)body.size between 50 and 500kb

isJson/isXml/isHtml sind absichtlich kontextabhängig, und worauf Sie sie schreiben, entscheidet, welche Bedeutung gilt. Auf dem Dokument selbst geschrieben (body isJson) bedeuten sie "lässt sich das als dieses Format parsen", genau wie body.json exists. Auf einem Textwert geschrieben, der einen Medientyp nennt, etwa einem Header (header("Content-Type") isJson), bedeuten sie "nennt dies die MIME-Familie dieses Formats"; siehe MIME-Familien unten dafür, welche Medientypen infrage kommen. isForm hat nur die zweite Bedeutung, da es keinen body.form-Namensraum zum Parsen gibt, sodass body isForm ein statischer Fehler ist statt einer Regel, die nie wahr sein könnte.

Der Filter where(...)

Behält nur die passenden Elemente und macht von dort weiter. Es ist die einzige Filterkonstruktion der Sprache und hat genau eine Form: where(current.<feld> <bedingung> <wert>).

Filtern unterscheidet sich von Projizieren: requests.url contains "cart" fragt, ob ein solcher Sprung irgendwo in der Kette existiert, während requests.where(current.url contains "cart").status fragt, was dieser Sprung zurückgegeben hat. Filtern reduziert die Liste nicht, schließen Sie also mit .first, einer in [...]-Prüfung oder .count ab. Es geht nur eine Ebene tief und nimmt genau eine Bedingung.

TeilWas er benenntHinweise
current.<feld>Ein Feld jedes gefilterten Elements, geschrieben nach current.Das ist die Hälfte, die am häufigsten falsch gemacht wird: current.url ist die URL des einzelnen Sprungs, nicht die der finalen Antwort. Nur die eigenen Felder des Elements können nach current. folgen.
die BedingungJedes gewöhnliche Prädikat, einschließlich not und nocaseJede Bedingung, die auf oberster Ebene einer Regel funktioniert, funktioniert auch hier.
der WertWomit das Feld jedes Elements verglichen wirdMeist ein einfacher Wert. Ein hier geschriebenes Subjekt wird aus der ÄUSSEREN Antwort gelesen, nicht aus dem Element, where(current.url eq url.original) vergleicht jeden Sprung mit der URL, mit der die Prüfung konfiguriert wurde, weshalb die Element-Seite current. ausdrücklich sagen muss.

Beispiel: requests.where(current.url contains "cart").status.first eq 301, behält nur die Sprünge, deren URL "cart" enthält, und sieht sich dann den Status des ersten passenden an.

Zwei weitere Grenzen, beide vom Parser mit eigener Meldung erzwungen: where kann nicht in ein anderes where verschachtelt werden, und sein Argument ist genau eine Bedingung, ohne and/or darin. Es gilt nur für eine Sammlung, deren Elemente benannte Felder tragen (requests, body.html.a), nicht für eine schlichte projizierte Liste wie dns.ips, wo es nichts gibt, das current. benennen könnte.

Syntaxreferenz

Alles Weitere, was die Grammatik definiert: wie Sie eine Regel benennen, wie Sie Bereiche und Listen schreiben, was ein bloßes Subjekt bedeutet, und die kleinen Interpunktionsformen, die in vielen Regeln auftauchen.

FormWas sie tutArtBeispiel
whereBehält nur die passenden Elemente und macht von dort weiter.Sammlungsfilterrequests.where(current.url contains "cart").status.first eq 301
notKehrt die folgende Bedingung um.Flagbody not contains "error"
nocaseVergleicht Text ohne Rücksicht auf Groß- und Kleinschreibung.Flagbody contains "welcome" nocase
currentBenennt innerhalb von where(…) das eine gefilterte Element.Elementreferenz (innerhalb where)requests.where(current.status eq 301)
rangeEin Zahlenbereich, beide Enden EINGESCHLOSSEN.Zahlenbereichstatus in [200..299]
listEine Liste von Werten zum Vergleich.Wertlistestatus in [200, 301, 302]
docLiteralEin typisierter Dokumentwert für strukturellen Vergleich: der zitierte Text wird beim Speichern der Regel als JSON, XML oder YAML geparst.json/xml/yaml-Textbody.json contains json("{\"user\": {\"active\": true}}")
implicitExistsEine Regel, die nur ein Subjekt nennt, prüft, dass es vorhanden ist: allein body.json zu schreiben speichert als body.json exists.reine Subjektzeilebody.json
indexWählt EIN Element einer Liste nach Position aus, gezählt ab 0.nullbasierte Ganzzahlrequests[0].status
labelEin optionaler Name für die Regel, geschrieben vor einem Doppelpunkt.Name vor einem Doppelpunkt"json ok": body.json exists
commentAlles nach # ist eine Notiz für Sie selbst; es beeinflusst die Prüfung nicht.nachgestellter #-Textstatus isOk # the happy path

Einige verdienen eine Erklärung in Klartext. label gibt einer Regel einen Namen, der im Alarm statt des gerenderten Ausdrucks erscheint; schreiben Sie ihn vor einem Doppelpunkt, wie in "json ok": body.json exists. implicitExists bedeutet, dass eine Zeile, die nur ein Subjekt und kein Prädikat nennt, eine Kurzform für exists ist: body.json zu schreiben speichert als body.json exists, und beim erneuten Öffnen der Regel erscheint die ausgeschriebene Form. range und list sind die zwei Formen, die ein Wert nach in annehmen kann: ein Bereich ([200..299], beide Enden eingeschlossen) oder eine explizite Liste ([200, 301, 302]), und ein Wert kann auf beiden Seiten offen sein ([400..]). docLiteral ist der json(...)/xml(...)/yaml(...)-Wrapper für strukturellen Vergleich mit dem Body (behandelt oben unter Operatoren und unten in den ausgearbeiteten Regeln). index wählt ein Element einer Sammlung nach Position, ab 0, genauso wie bind[0] eine positionale Erfassung liest. current hat nur innerhalb eines where(...)-Filters eine Bedeutung, behandelt im eigenen Abschnitt oben.

Wrapper: previous, delta und delta2

Drei Formen, die rückwärts blicken statt nur auf die aktuelle Antwort, jede an Pläne mit zustandsbehafteten Assertions gebunden, und jede vollständig erklärt unter "Gegen die vorherige Prüfung vergleichen" weiter unten.

NameWas es istTyp/WerteBeispiel
delta (braucht einen Plan mit zustandsbehafteten Assertions)Wie stark sich ein numerischer Wert seit der vorherigen Prüfung geändert hat, optional als Rate pro ms/s/m/h.numberdelta(body.size, h) lt 1mb
delta2 (braucht einen Plan mit zustandsbehafteten Assertions)Die Änderung der Änderung, beschleunigt sich ein Wert?numberdelta2(time) gt 0
previous (braucht einen Plan mit zustandsbehafteten Assertions)Der Wert, den dieses Subjekt bei der vorherigen Prüfung hatte.anystatus eq previous.status

Flags: not und nocase

Zwei Modifikatoren, die sich an eine Regel anhängen, statt selbst als Subjekt oder Prädikat zu stehen.

FlagWas es tutArtBeispiel
notKehrt die folgende Bedingung um.Flag (an eine Regel angehängt)body not contains "error"
nocaseVergleicht Text ohne Rücksicht auf Groß- und Kleinschreibung.Flag (an eine Regel angehängt)body contains "welcome" nocase

not verbindet sich mit dem folgenden Prädikat, statt die ganze Regel als Einheit zu negieren, x not != y liest sich als x eq y, nicht als doppelte Verneinung. Wenn ein Subjekt komplett fehlen könnte, bevorzugen Sie das Sugar absent gegenüber not exists: Beide bedeuten exakt dasselbe, aber absent sagt es direkt. nocase ändert nur bei einem wirklich textuellen Vergleich etwas; der Editor (und diese Referenz) lassen Sie es trotzdem überall schreiben, aber bei einem numerischen Test wie status eq 200 nocase ist es stillschweigend bedeutungslos.

MIME-Familien

Die Nachschlagetabellen hinter isJson, isXml, isHtml und isForm, wenn sie auf einen Medientyp-Wert wie einen Header angewendet werden. Jede Familie trifft den offensichtlichen Medientyp der obersten Ebene plus, für JSON und XML, jeden Typ, der auf das passende strukturierte Syntax-Suffix endet, was header("Content-Type") isJson korrekt bei application/problem+json oder application/vnd.api+json und nicht nur beim reinen application/json bestehen lässt.

FamilieTrifftZugehöriges SugarBeispiel
jsonapplication/json, text/json, oder jeder Medientyp, der auf +json endet (application/problem+json, application/vnd.api+json, application/ld+json, …).Sugar: isJsonheader("Content-Type") isJson
xmlapplication/xml, text/xml, oder jeder Medientyp, der auf +xml endet (image/svg+xml, application/atom+xml, …).Sugar: isXmlheader("Content-Type") isXml
htmltext/html oder application/xhtml+xml.Sugar: isHtmlheader("Content-Type") isHtml
formapplication/x-www-form-urlencoded oder multipart/form-data.Sugar: isFormheader("Content-Type") isForm

Der Abgleich ignoriert alles ab dem ersten ; (sodass application/json; charset=utf-8 weiterhin trifft) und unterscheidet nicht zwischen Groß- und Kleinschreibung.

Subjekte für Datenbank-, Counter-, SNMP-, Port- und Ping-Prüfungen

Jeder Operator, Reducer, jede Sugar-Abkürzung und Syntaxform oben ist für diese fünf Prüfungsarten identisch: Die Engine registriert dieselben 15 Operatoren, 8 Reducer, 12 Sugar-Prädikate und 11 Syntaxformen für alle sechs Arten ohne Ausnahme. Was sich je Art unterscheidet, ist die Subjektliste. Jede Art stellt einen kleinen Satz eigener Subjekte für das bereit, was sie misst, plus eine Teilmenge der oben bereits dokumentierten Netzwerk-/Timing-/TLS-Subjekte, deren Bedeutung sich an die Art anpasst (das time einer Datenbankprüfung ist Verbindungsaufbau-plus-Abfrage statt Verbindungsaufbau-plus-TLS-plus-Download, da es keine HTTP-Antwort zum Herunterladen gibt).

Datenbankprüfungen

Teilt sich time, time.connect und time.dns mit den oben dokumentierten Subjekten (neu bezogen auf eine Datenbankverbindung: Verbindungsaufbau-plus-Abfrage, DNS-Auflösung des Datenbank-Hosts). Eigen für Datenbankprüfungen:

NameWas es istTyp/WerteBeispiel
scalarDer einzelne Wert, den die Abfrage zurückgegeben hat (Scalar-Modus).any-
rowsDie Zeilen, die die Abfrage betroffen oder zurückgegeben hat (NonQuery-Modus).collection-
time.queryZeit, die die Abfrage selbst gebraucht hat.number-

Ein ausgearbeitetes Beispiel steht im nächsten Abschnitt: Verwenden Sie rows.count, um zu prüfen, wie viele Zeilen eine Abfrage betroffen oder zurückgegeben hat, und scalar, um einen einzelnen zurückgegebenen Wert direkt zu prüfen.

Counter-Prüfungen

Teilt sich time mit den oben dokumentierten Subjekten, speziell als Feld mit Kandidatenstatus für Counter-Prüfungen (Umlaufzeit des Counter-Requests; siehe den Abschnitt Ehrlichkeit dafür, was "Kandidat" bedeutet). Eigen für Counter-Prüfungen:

NameWas es istTyp/WerteBeispiel
valueDer gemessene Counter-Wert.number-

SNMP-Prüfungen

Teilt sich time und time.dns mit den oben dokumentierten Subjekten (Hostname-Auflösung plus der SNMP-Request selbst). Eigen für SNMP-Prüfungen:

NameWas es istTyp/WerteBeispiel
time.requestZeit, die der SNMP-Request gebraucht hat.number-
valueDer von der OID zurückgegebene Wert.any-
value.type (Kandidat, wird auf Agenten ausgerollt)Der SNMP-Datentypname des zurückgegebenen Werts.string-

value.type hat Kandidatenstatus, siehe den Abschnitt Ehrlichkeit. Hinweis zur Verfügbarkeit: Der Response-Validation-Schalter für den Assertion-Modus hat den SNMP-Monitor-Editor noch nicht erreicht. Er zeigt ein "Coming soon"-Panel, das diese zwei Subjekte nennt, statt einer funktionierenden Regelliste. Die Subjekte und der Evaluator darunter sind bereits registriert; nur die SNMP-Editor-Oberfläche steht noch aus.

Port-Prüfungen

Die größte gemeinsame Liste jeder Nicht-HTTP-Art. Eine TCP-Port-Prüfung trägt im Wesentlichen dieselben Verbindungs-, DNS-, TLS- und Zertifikatssubjekte wie eine HTTP-Prüfung, da eine Port-Prüfung ebenfalls TLS aushandeln kann: bind, cert und seine sechs Unterfelder, conn und seine vier Unterfelder, dns und seine zwei Unterfelder, time/time.connect/time.dns/time.tls, und tls/tls.cipher/tls.protocol, alle in den obigen Abschnitten mit derselben Bedeutung dokumentiert. Eigen für Port-Prüfungen:

NameWas es istTyp/WerteBeispiel
bannerDie nach dem Verbindungsaufbau vom Socket gelesenen Daten.string-
banner.hash (Kandidat, wird auf Agenten ausgerollt)Ein Digest des Banners, vergleichen Sie ihn mit previous.banner.hash, um Dienständerungen zu erkennen.string-
banner.regexVergleicht den Text mit einem regulären Ausdruck und übernimmt, was er erfasst hat.stringbody.regex("order-(?<id>\\d+)") exists
banner.size (Kandidat, wird auf Agenten ausgerollt)Die Größe des Banners, in Byte.number-

banner.hash und banner.size haben Kandidatenstatus, siehe den Abschnitt Ehrlichkeit. banner.regex ist bereits heute live und funktioniert genau wie body.regex(...) bei einer HTTP-Prüfung: benannte Erfassungen speisen denselben bind(...)-Namensraum.

Ping-Prüfungen

Teilt sich die Verbindungs- und DNS-Subjekte mit den obigen Abschnitten: conn, conn.failed, conn.failedIps, conn.ip, conn.ip.family, dns, dns.ips, dns.server, time (hier die durchschnittliche Umlaufzeit der erfolgreichen Antworten) und time.dns. Eigen für Ping-Prüfungen:

NameWas es istTyp/WerteBeispiel
lossDer Prozentsatz der Echo-Requests, die keine Antwort erhielten.numberloss eq 0
replyDie erfolgreichen Echo-Antworten.collection-
sentCount (Kandidat, wird auf Agenten ausgerollt)Wie viele Echo-Requests gesendet wurden.number-
time.maxDie Umlaufzeit der langsamsten Antwort.number-
time.minDie Umlaufzeit der schnellsten Antwort.number-
ttlDie TTL der ersten erfolgreichen Antwort, vergleichen Sie mit previous.ttl, um Routenänderungen zu erkennen.number-

sentCount hat Kandidatenstatus, siehe den Abschnitt Ehrlichkeit. ttl ist auch abseits einer strikten Bestanden/Fehlgeschlagen-Regel gut zu kennen: Es mit previous.ttl zu kombinieren (siehe Wrapper oben) zeigt einen Routenwechsel zwischen Prüfungen an, da die Time-to-live eines Pakets bei Ankunft widerspiegelt, wie viele Hops es durchlaufen hat.

Regeln, die man tatsächlich schreiben will

Die Seite ist erreichbar und sagt tatsächlich das Richtige

Ein Statuscode allein kann Ihnen nicht sagen, ob eine Seite korrekt gerendert hat, eine 200-mit-leerer-Hülle-Antwort ist der klassische stille Fehler, den eine reine Statusprüfung übersieht.

status isOk
body contains "Add to cart"

Eine API antwortet mit JSON und dem erwarteten Feld

Prüfen Sie, dass der Endpunkt noch JSON spricht, und greifen Sie dann hinein. Die erste Zeile fängt eine HTML-Fehlerseite ab, die dort ausgeliefert wird, wo JSON stehen sollte, eine häufige Ausfallform hinter einem Proxy; die zweite prüft den eigenen gemeldeten Gesundheitszustand der API, nicht nur ihren Transportstatus.

body isJson
body.json.path("$.status") eq "ok"

Die Antwort wurde langsamer, als sie sein sollte

Schlüsseln Sie es auf, wenn Sie wissen müssen, was zu reparieren ist, statt nur dass etwas langsam ist, time.connect, time.tls, time.dns und time.head trennen Netzwerk-, Handshake-, Resolver- und Anwendungszeit.

time lt 2s

Eine Weiterleitung hat Besucher von der eigenen Domain weggeschickt

Vergleicht, wo die Prüfung gelandet ist, mit der von Ihnen konfigurierten URL, sie schlägt in dem Moment fehl, in dem eine Weiterleitungskette, gekapert, falsch konfiguriert oder einfach durch ein Deployment geändert, irgendwo landet, das Sie nicht beabsichtigt haben.

url.host eq url.original.host

Die Seite hat sich seit der letzten Prüfung geändert

Nützlich bei Inhalten, die zwischen Prüfungen stabil bleiben sollten, Preise, Bedingungen, eine veröffentlichte Richtlinie, und dient nebenbei als einfaches Defacement-Signal.

previous.body.hash eq body.hash

Eine Zahl innerhalb eines Bereichs, kurz geschrieben

Fängt sowohl eine abgespeckte als auch eine ausgeuferte Seite in einer einzigen Regel ab, ohne einen expliziten Bereich auszuschreiben.

body.size between 50 and 500kb

Ein bald ablaufendes Zertifikat

Die mit Abstand häufigste TLS-Prüfung, und eine, die ein einfacher Up/Down-Monitor überhaupt nicht ausdrücken kann, ein Zertifikat, das heute noch validiert, aber nächste Woche verfällt, gibt sonst kein Warnzeichen. Kombinieren Sie es mit cert.issuer, wenn Sie zusätzlich ein still von der falschen Stelle ausgestelltes Zertifikat erfassen wollen.

cert.days.left gt 14

Eine Datenbankabfrage, die die falsche Anzahl Zeilen zurückgibt

Bei einer Datenbankprüfung ist rows die Sammlung, die eine Abfrage betroffen oder zurückgegeben hat, sie zu zählen fängt ab, dass eine Abfrage, die genau einen Kontodatensatz zurückgeben sollte, still anfängt, null zurückzugeben (gelöscht, oder ein kaputter Join) oder mehr als einen (ein Duplikat, das nicht existieren sollte).

rows.count eq 1

Ein SNMP-Wert, der aus dem Bereich driftet

Ein SNMP-Gerät, das überhaupt antwortet, ist nicht dasselbe wie ein gesundes, eine überwachte OID (Speicherauslastung, Warteschlangentiefe, Temperatur) kann weit über einen sicheren Schwellenwert steigen, während das Gerät selbst einwandfrei erreichbar bleibt. Den abgefragten value gegen einen Bereich zu vergleichen, erfasst, was eine reine Erreichbarkeitsprüfung nicht kann.

value lt 90

Ein TCP-Dienst, der mit dem falschen Banner antwortet

Ein Port, der Verbindungen annimmt, ist nicht dasselbe wie der richtige, darauf lauschende Dienst, ein hängender Prozess, ein falsch konfigurierter Proxy oder ein herabgestufter/ausgetauschter Dienst können alle trotzdem einen TCP-Handshake abschließen. Den Begrüßungstext zu lesen, den ein Dienst direkt nach dem Verbindungsaufbau sendet (ein SMTP-, FTP- oder ähnliches Banner), erfasst, was eine bloße Port-offen-Prüfung nicht kann.

banner contains "220"

Gegen die vorherige Prüfung vergleichen

Eine Handvoll Subjekte blickt rückwärts statt nur auf die aktuelle Antwort: Stellen Sie previous. vor ein Subjekt, um zu lesen, was es bei der letzten Prüfung war, oder umschließen Sie es mit delta(...), um den Unterschied zwischen damals und jetzt zu erhalten, oder mit delta2(...), um die Änderung dieser Änderung zu erhalten, nützlich, um einen sich beschleunigenden statt driftenden Wert zu erkennen (eine Antwortzeit, die mit jeder Prüfung schneller steigt). previous.body.hash eq body.hash oben ist genau das, "stimmt der Fingerabdruck des Bodys mit dem von letztem Mal überein". delta(body.size, h) liest die Änderung als Rate pro Stunde statt als rohe Differenz, für Werte, von denen Sie stetiges statt sprunghaftes Wachstum erwarten.

Beim ersten Lauf einer solchen Regel gibt es nichts zum Vergleichen, sie wird also übersprungen statt zu scheitern: Die Prüfung wird als "warming up" markiert, nicht als defekt, und das Hinzufügen der Regel löst keinen falschen Alarm aus. Warming gilt nur, wenn die aktuelle Lesung stimmt und nur die Basislinie fehlt. Scheitert die aktuelle Lesung selbst (etwa weil der Body diesmal kein gültiges JSON ist), scheitert die Regel genau wie ihre einfache, nicht-previous.-Version es täte. Eine solche Regel braucht außerdem, dass sich der Wert zwischen Prüfungen ändert, was sie bei einer Prüfmethode bedeutungslos macht, die den Zustand nie weiterbewegt, etwa ein HEAD-Request.

Der Vergleich mit der vorherigen Prüfung braucht einen höherstufigen Plan; ohne ihn erscheinen diese Subjekte im Editor ausgegraut, mit einer Erklärung.

Grenzen, und was absichtlich fehlt

Wie viele Regeln Sie hinzufügen können, hängt von Ihrem Plan ab, angezeigt als Live-Zähler neben "Add rule". Die Engine erzwingt zudem eine absolute Obergrenze für jede Prüfung, unabhängig vom Plan, eine Absicherung gegen Missbrauch statt eine Grenze für den gewöhnlichen Gebrauch: Eine Prüfung mit annähernd so vielen Regeln wäre bereits ungewöhnlich groß.

Es gibt keine Möglichkeit, eigenes JavaScript für eine Regel zu schreiben, und das wird es nie geben. Jede Regel wird aus einem festen, benannten Wortschatz von Subjekten und Prädikaten gebaut statt aus einer offenen Skript-Sandbox, was eine Regel auf einen Blick lesbar hält und sicher macht, auf jedem Monitoring-Agenten weltweit zu laufen.

Nicht jede Regel funktioniert überall, sobald sie geschrieben ist: Manche neueren Bedingungen brauchen eine aktuelle Version des Monitoring-Agenten, der Ihre Prüfung ausführt, eine neue Fähigkeit braucht also Zeit, um jede Prüfung Ihres Kontos zu erreichen, während Agenten sich im Hintergrund aktualisieren. Regeln, die auf dem stabilen Kern der Sprache aufbauen, sind davon nicht betroffen.

Eine Handvoll Einträge in dieser Referenz ist noch nicht vollständig live, und jeder ist in seiner Tabelle oben entsprechend gekennzeichnet:

  • Reserviert (deklariert, aber von keinem Agenten befüllt): ttfb, httpVersion, cert.subject.
  • Kandidat (wird bereits ausgerollt, aber noch nicht auf jedem Agenten): conn.ip.family und conn.failedIps bei HTTP-, Port- und Ping-Prüfungen, value.type bei SNMP-Prüfungen, banner.hash und banner.size bei Port-Prüfungen, sentCount bei Ping-Prüfungen, und das eigene time der Counter-Prüfung.
  • Noch nicht verfügbar: steps, reserviert für eine künftige mehrstufige Prüfungsart.
  • Braucht einen Plan mit zustandsbehafteten Assertions: die gesamte Wrapper-Familie previous/delta/delta2, bei jeder Prüfungsart.

Alles Übrige in dieser Referenz ist heute auf jedem Plan mit Assertion-Modus live.

Wo der Assertion-Modus heute funktioniert

Der Response-Validation-Schalter für den Assertion-Modus erscheint bei HTTP-(Website-) und API-Monitoren, die sich denselben Regel-Editor und dieselbe Syntax teilen. Dieselbe Sprache und derselbe Evaluator laufen bereits unter Datenbank-, Counter-, Port-, Ping- und SNMP-Prüfungen auf Protokollebene: Die Registry oben bedient alle sechs Prüfungsarten, und eine für eine gespeicherte Regel liest sich gleich, falls der Modus später den Editor einer anderen Art erreicht.

SNMP zeigt die deutlichste Vorschau: Sein Editor hat bereits ein Assertion-Rules-Panel, das value und value.type nennt, mit der Kennzeichnung "Coming soon", noch ohne funktionierende Regelliste dahinter. Datenbank-, Counter- und Ping-Prüfungen zeigen überhaupt kein Assertion-Modus-Panel, obwohl ihre Subjekte in der Engine darunter genauso live sind.

Eine echte Prüfung einrichten

Wenn Sie eine REST-API statt einer reinen Webseite validieren, beginnen Sie bei API-Response-Validierung, die Erreichbarkeit, Antwortzeit und Body Ihrer eigenen API gemeinsam abdeckt. Für eine Seite oder Website, die überall dort erreichbar bleiben und korrekt antworten muss, wo Ihre Nutzer sind, ist globales Uptime-Monitoring von über 300 Standorten das größere Bild, in das der Assertion-Modus sich einfügt. Um Regeln über Code statt über das Panel zu setzen, erstellt und aktualisiert HostTrackers eigene API v2 die Assertion-Regeln eines Monitors genauso wie der Editor. Für die Zertifikatsablauf-Regel oben und alles andere zu TLS deckt Domain- und TLS-Zertifikats-Monitoring die Prüfungsart ab, auf der cert.days.left und die anderen TLS-Subjekte leben. Um eine Regel jetzt sofort gegen eine echte URL auszuwerten, ohne Konto, nutzen Sie das kostenlose HTTP-Check-Tool. Für die Statuscodes, mit denen das Subjekt status vergleicht, beginnen Sie bei 200 OK, und die Monitoring-Anleitungen behandeln die Einrichtung jeder Prüfungsart, unter der diese Sprache läuft.

Häufig gestellte Fragen

Was passiert mit meinen alten Statuscode- und Schlüsselwort-Einstellungen, wenn ich den Assertion-Modus einschalte?

Sie werden durch die Regelliste ersetzt, solange der Modus an ist. Ihn vor dem Speichern wieder auszuschalten, stellt die klassischen Felder exakt wie zuvor wieder her: Nichts wird gelöscht, die beiden Modi können nur nicht gleichzeitig aktiv sein.

Kann ich mehrere Bedingungen in einem Monitor kombinieren?

Ja: Jede Regel in der Liste muss bestehen. Ein "ODER" zwischen getrennten Regeln gibt es noch nicht, um also einen von mehreren Werten zu akzeptieren, verwenden Sie eine einzelne Regel mit in [...] oder containsAny [...].

Wird der Assertion-Modus mir jemals erlauben, ein eigenes Skript zu schreiben?

Nein. Jede Regel wird aus dem festen Satz von Subjekten und Prädikaten der Sprache zusammengesetzt. Es gibt kein eigenes JavaScript, mit Absicht.

Was passiert beim ersten Mal, wenn ich eine Regel hinzufüge, die mit der vorherigen Prüfung vergleicht?

Es gibt noch nichts zum Vergleichen, sie wird also als "warming up" markiert und übersprungen statt als fehlgeschlagen gewertet. Eine "hat sich das geändert"-Regel hinzuzufügen löst nie von selbst einen falschen Alarm aus.

Brauche ich einen bestimmten Plan, um den Assertion-Modus zu nutzen?

Der Modus selbst und die alltäglichen Regeln (Status, Body, Header, Timing, Weiterleitungen) sind breit verfügbar; wie viele Regeln Sie gleichzeitig hinzufügen können, hängt von Ihrem Plan ab und wird live im Editor angezeigt. Regeln, die mit einer vorherigen Prüfung vergleichen (previous, delta, delta2), brauchen einen höherstufigen Plan und sind ausgegraut, mit einer Erklärung.

Funktioniert der Assertion-Modus bei API-Monitoren genauso wie bei Website-Monitoren?

Ja. HTTP- und API-Monitore teilen sich denselben Regel-Editor, dieselben Subjekte und Prädikate, und eine für einen geschriebene Regel liest sich beim anderen identisch.

Was macht where(...) eigentlich, und wann brauche ich es?

Es filtert eine Sammlung auf die zu einer Bedingung passenden Elemente herunter, bevor Sie ein Feld des Ergebnisses lesen. Verwenden Sie es, wenn eine einfache Projektion wie requests.status nicht spezifisch genug ist und Sie einen bestimmten Sprung, Link oder ein bestimmtes Element statt der ganzen Sammlung brauchen (siehe den Abschnitt oben).

Kann ich heute schon eine Regel gegen eine Datenbankabfrage, einen SNMP-Wert, ein Port-Banner oder ein Ping-Ergebnis schreiben?

Die Sprache und der Evaluator unterstützen alle davon, und die Subjekttabellen oben decken jede einzelne ab. Der Regel-Editor tut es nicht: Nur HTTP- und API-Monitore zeigen heute den Response-Validation-Schalter. SNMP zeigt eine "Coming soon"-Vorschau seiner zwei Subjekte, und Datenbank-, Counter- und Ping-Prüfungen zeigen überhaupt kein Assertion-Modus-Panel.

Warum sagen manche Subjekte in dieser Referenz "reserviert" oder "Kandidat" statt einfach normal aufgelistet zu sein?

"Reserviert" bedeutet, das Feld ist in der Registry deklariert, aber noch von keinem Agenten befüllt; "Kandidat" bedeutet, es wird bereits auf Agenten ausgerollt, hat aber noch nicht alle erreicht. Beides wird überall dort, wo es in dieser Referenz auftaucht, und in der zusammenfassenden Liste im Abschnitt Grenzen oben eigens gekennzeichnet.

Jetzt prüfen

Führen Sie die kostenlose Prüfung für Ihre eigene Website aus - ganz ohne Konto.

Web api validation

Dauerhaft überwachen

Werden Sie benachrichtigt, sobald etwas ausfällt: HostTracker prüft von über 300 Standorten aus und benachrichtigt Sie per E-Mail, SMS, Slack, Telegram und mehr.

HostTracker Funktionen

Mehr in diesem Bereich: Monitoring-Anleitungen: jeder Prüfungstyp, Schritt für Schritt