Tryb asercji: pełny słownik weryfikacji odpowiedzi
Tryb asercji zastępuje stałe pola przejścia/niepowodzenia monitora listą reguł, które piszesz sam, a każda reguła nazywa dokładnie to, co musi być prawdą w odpowiedzi. Większość monitorów uptime osądza sprawdzenie na podstawie garstki stałych pól: kodu statusu, który liczy się jako "Down", listy statusów do zignorowania, może słowa kluczowego, które musi się gdzieś pojawić w treści. Te pola nie potrafią wyrazić API, które zgodnie z zamierzeniem odpowiada 404 dla brakującego zasobu, strony, która zwraca 200 z pustą powłoką, bo baza danych przekroczyła czas oczekiwania, albo łańcucha przekierowań, który zaczyna prowadzić przez cudzą domenę.
Tryb asercji HostTracker zastępuje te stałe pola niewielkim językiem reguł, który piszesz sam, regułę po regule, wewnątrz edytora monitora. Każda reguła mówi dokładnie, co musi być prawdą w odpowiedzi: status, fragment treści, nagłówek, jak długo to trwało, dokąd trafiło przekierowanie. Sprawdzenie zawodzi tylko wtedy, gdy zawiedzie jedna z Twoich reguł. To ten sam język dla strony internetowej, REST API, zapytania do bazy danych, portu TCP, celu Ping, licznika SNMP czy ogólnego sprawdzenia Counter: jeden zestaw podmiotów, jeden zestaw predykatów, używany wszędzie tam, gdzie pojawia się ten tryb. Ten poradnik omawia każdy podmiot, operator, reduktor, skrót cukru składniowego i formę składni, którą implementuje silnik.
Co zastępuje tryb asercji
Klasyczne pola Weryfikacji odpowiedzi wciąż tam są, gdy tryb asercji jest wyłączony: oczekiwany zakres statusu, lista statusów do zignorowania, słowo kluczowe, które musi (lub nie może) się pojawić. Tryb to przełącznik, który zamienia ten stały zestaw na listę reguł budowaną przez Ciebie, a jego ponowne wyłączenie przed zapisaniem przywraca klasyczne pola dokładnie takimi, jakie były. Żaden monitor nie jest przypisany na stałe do jednego trybu.
Jeden język zamiast stosu osobnych gadżetów dla każdego typu składa się w całość. Sprawdzenie "musi być JSON i zawierać pole", sprawdzenie "musi nadal mówić Add to cart" i sprawdzenie "nie może zwolnić" to trzy reguły w tej samej składni, na tej samej liście, każda przechodzi lub zawodzi niezależnie.
Włączanie trybu
Tryb asercji znajduje się wewnątrz sekcji Weryfikacja odpowiedzi edytora monitora, dla monitorów HTTP (strona) i API. Przełącz przełącznik, a klasyczne pola zostaną zastąpione numerowaną listą reguł z przyciskiem "Add rule" i żywym licznikiem pokazującym, ile reguł wykorzystałeś względem limitu swojego planu.

Każda reguła jest walidowana w miarę budowania: reguła jeszcze nieukończona niesie odrębny stan "niedokończona", a reguła, którą edytor potrafi obliczyć, jest oznaczana jako kompletna. Każda reguła ma też mały przycisk </>, który otwiera jej formę w postaci zwykłego tekstu, więc możesz odczytać lub skopiować dokładne wyrażenie zamiast patrzeć tylko na widok pole po polu.
Model myślowy: podmiot, predykat, wartość
Każda reguła ma tę samą postać: podmiot (kod statusu, treść, nagłówek, czas odpowiedzi), predykat (równe, zawiera, istnieje, jest mniejsze niż) i, dla większości predykatów, wartość do porównania. status eq 200 to podmiot, predykat i wartość; body.json exists to podmiot i predykat bez wartości, bo "exists" niczego więcej nie potrzebuje.
Budowanie reguły w edytorze zaczyna się od wybrania, co sprawdzić, potem warunku, potem wartości:

Reguły na liście są łączone przez AND: sprawdzenie zawodzi, gdy zawiedzie choćby jedna reguła, i przechodzi tylko wtedy, gdy przejdą wszystkie. OR jeszcze nie istnieje, więc żeby zaakceptować jeden z kilku statusów lub ciągów znaków, wyraź to wewnątrz jednej reguły (status in [200, 301, 302], body containsAny ["In stock", "Pre-order"]). Reguła, która zawodzi, nazywa samą siebie w alercie, więc nadawaj każdej krótką etykietę tam, gdzie możesz, a alert powie, które oczekiwanie zostało złamane.
Co możesz sprawdzać
Selektor grupuje podmioty według własnego dokumentu odpowiedzi (treść, nagłówki) i jej transportu (status, czas, przekierowania, TLS). Kilka najważniejszych podmiotów, z pełną listą w dalszym słowniku:
| Podmiot | Co to jest | Przykład |
|---|---|---|
status | Kod statusu HTTP odpowiedzi końcowej, po przejściu przekierowań | status isOk |
body | Treść odpowiedzi jako zwykły tekst | body contains "Add to cart" |
body.json / body.xml / body.html / body.yaml | Treść, ale tylko gdy rzeczywiście da się ją sparsować w tym formacie - w przeciwnym razie podmiot po prostu nie istnieje | body.json exists |
body.json.path("$.a") | Zapytanie JSONPath do treści JSON (ten sam język zapytań działa też nad YAML, bo YAML parsuje się do tego samego modelu obiektowego) | body.json.path("$.status") eq "ok" |
body.size / body.hash | Rozmiar odpowiedzi w bajtach i odcisk palca treści | body.size gt 1kb |
header("Name") | Jeden nagłówek odpowiedzi, wyszukany po nazwie | header("Content-Type") isJson |
time oraz time.connect / time.tls / time.dns / time.head | Całkowity czas odpowiedzi oraz jego fazy: sieć, handshake TLS, DNS i czas myślenia serwera | time lt 2s |
redirects / requests | Przeskoki, przez które przeszło sprawdzenie, i cały łańcuch (łącznie z odpowiedzią końcową) | redirects.count eq 0 |
url i jego części (.host, .scheme, .path...) | Końcowy URL, na którym sprawdzenie wylądowało | url.scheme eq "https" |
cert.days.left | Dni pozostałe do wygaśnięcia certyfikatu TLS | cert.days.left gt 14 |
Liczby przyjmują sufiksy jednostek, więc nigdy nie musisz przeliczać ręcznie: 2s oznacza 2000 milisekund, 1kb oznacza 1024 bajty. Porównania tekstu są wrażliwe na wielkość liter, chyba że dodasz do reguły nocase.
Pełny słownik
Poniżej znajduje się każdy podmiot, operator, reduktor, skrót cukru składniowego, filtr i forma składni, które silnik asercji rejestruje dla sprawdzeń HTTP i API, zaczerpnięte wprost z własnego rejestru silnika (te same dane, które zasilają selektory edytora reguł i jego dokumentację). Wpisy, które nie są jeszcze w pełni dostępne, niosą notatkę w nawiasie: zarezerwowane pola, których silnik jeszcze nie zaczął wypełniać, kandydaci wciąż wdrażani na agentów, oraz rodzina ze stanem, wymagająca konkretnego planu. Wszystko bez takiej notatki działa już dziś na każdym planie z trybem asercji.
Słownik podąża za własnym grupowaniem silnika: najpierw pola odpowiedzi, potem sposoby sięgania w głąb treści, potem czas, sieć i TLS, potem operatory, reduktory i skróty działające na nich wszystkich, a na końcu rodzaje sprawdzeń poza HTTP mówiące tym samym językiem.
Odpowiedź
Podmioty opisujące samą odpowiedź: jej status, surową treść, jej nagłówki, URL, z którego faktycznie odpowiedziała, oraz łańcuch żądań, które do niej doprowadziły.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
body | Treść odpowiedzi jako zdekodowany tekst. | string | body contains "Welcome" |
header | Jeden nagłówek odpowiedzi końcowej, po nazwie. | string | header("Content-Type") isJson |
redirects | Przeskoki przekierowań, które zostały przebyte - łańcuch żądań bez jego ostatniego elementu. | collection | redirects.count eq 0 |
status | Kod statusu HTTP odpowiedzi końcowej, po przejściu przekierowań. | number | status isOk |
body.size | Rozmiar pobranej treści, w bajtach. | number | body.size lt 500000 |
url | URL, który faktycznie odpowiedział, po wszystkich przekierowaniach. url: porównaj go jako tekst albo odczytaj jego części (url.host, .port, .path, .query, .scheme). | url | url.host eq "www.example.com" |
requests | Każde żądanie wykonane przez to sprawdzenie, w kolejności - przeskoki przekierowań, a potem żądanie końcowe. | collection | requests.count le 2 |
url.host | Część URL z hostem. | string | url.host eq "example.com" |
url.path | Część URL ze ścieżką. | string | url.path startsWith "/api" |
url.port | Część URL z portem. | number | url.port eq 443 |
url.query | Ciąg zapytania URL. | string | url.query contains "token" |
url.scheme | Schemat URL (http lub https). | string | url.scheme eq "https" |
body.hash | Skrót treści odpowiedzi - porównaj z previous.body.hash, aby wykryć zmiany treści. | string | body.hash eq previous.body.hash |
httpVersion (zarezerwowane - jeszcze niewypełniane) | Wynegocjowana wersja HTTP. | string | httpVersion eq "HTTP/2" |
setCookie | Wartości Set-Cookie odpowiedzi końcowej, po jednym elemencie na ciasteczko - dopasuj jedno przez contains lub matches, policz przez .count. | collection | setCookie exists |
steps (jeszcze niedostępne) | Kroki sprawdzenia wieloetapowego. Jeszcze niedostępne. | collection | steps.count le 1 |
url.original | URL, z którym skonfigurowano sprawdzenie, przed jakimkolwiek przekierowaniem. url taki jak sam url: te same części (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.original.host | Część URL z hostem. | string | url.original.host eq "example.com" |
url.original.path | Część URL ze ścieżką. | string | url.original.path startsWith "/start" |
url.original.port | Część URL z portem. | number | url.original.port eq 80 |
url.original.query | Ciąg zapytania URL. | string | url.original.query contains "utm_" |
url.original.scheme | Schemat URL (http lub https). | string | url.original.scheme eq "http" |
Dwa aliasy: redirectCount to skrót od redirects.count - redirectCount eq 0 brzmi trochę naturalniej niż równoważna długa forma, gdy chodzi Ci o "sprawdzenie odpowiedziało bezpośrednio, bez przekierowań." A setCookie na najwyższym poziomie to lista ciasteczek odpowiedzi końcowej; ta sama nazwa pojawia się ponownie per-przeskok wewnątrz requests/redirects (zobacz Podmioty przeskoków poniżej), przechowując ciasteczka tylko tego jednego żądania.
Wyciąganie wartości z treści
Te podmioty rozwiązują się tylko wtedy, gdy treść jest w formacie, który nazywają: przestrzeń nazw JSON na stronie HTML po prostu nie istnieje, to nie jest typowany błąd. To sprawia, że exists jest standardowym sposobem sprawdzenia formatu, a body.json exists pyta, czy treść sparsowała się jako JSON. Każda z czterech przestrzeni nazw formatów niesie pasującą funkcję zapytania .path(...) (JSONPath dla json/yaml, XPath dla xml, selektory CSS dla html) i pasujące .regex(...), plus niezależne od formatu body.regex(...), które odczytuje surowy tekst niezależnie od formatu. body.html.a, body.html.script i body.html.link to gotowe kolekcje każdego linku, skryptu i elementu <link> na stronie; zobacz Zakresy elementów poniżej dla pól dostępnych na każdym z nich.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
body.json | Treść odpowiedzi, ale tylko gdy rzeczywiście jest JSON. | string | body.json exists |
body.json.path | Zapytaj treść JSON wyrażeniem JSONPath. | json | body.json.path("$.status") eq "ok" |
body.html | Treść odpowiedzi, ale tylko gdy rzeczywiście jest HTML. | string | body.html exists |
body.html.path | Wybierz elementy strony selektorem CSS. | collection | body.html.path("h1").first contains "Welcome" |
body.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml | Treść odpowiedzi, ale tylko gdy rzeczywiście jest XML. | string | body.xml exists |
body.xml.path | Zapytaj treść XML wyrażeniem XPath. | string | body.xml.path("//item/@id") exists |
body.html.a | Każdy link na stronie. | collection | body.html.a.count gt 0 |
body.html.link | Każdy <link> zadeklarowany przez stronę. Sama wzmianka oznacza cele linków. | collection | body.html.link.count gt 0 |
body.html.script | Każdy skrypt wczytywany przez stronę. Sama wzmianka oznacza źródła skryptów. | collection | body.html.script.count gt 0 |
body.yaml | Treść odpowiedzi, ale tylko gdy rzeczywiście jest YAML. | string | body.yaml exists |
body.yaml.path | Zapytaj treść YAML wyrażeniem JSONPath. | json | body.yaml.path("$.services.web.image") contains ":1." |
body.html.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
body.json.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
body.yaml.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
Szczegół rodziny regex wart wspomnienia: nazwane grupy przechwytujące ((?<id>...)) wewnątrz reguły .regex(...) zapisują się do przestrzeni powiązań w zasięgu sprawdzenia, którą późniejsza reguła może odczytać przez bind("id") lub bind[0] po pozycji - zobacz Przechwycone wartości poniżej.
Przechwycone wartości
Jeden podmiot ma własną grupę w rejestrze, bo nie czyta odpowiedzi bezpośrednio - czyta to, co przechwyciła z niej wcześniejsza reguła.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
bind | Wartość przechwycona przez wcześniejszą regułę regex, po nazwie przechwycenia lub po pozycji. | string | bind("id") gt 1000 |
Połącz to z regułą regex wcześniej na liście: reguła taka jak body.regex("order-(?<id>\d+)") exists przechwytuje id zamówienia pod nazwą id, a późniejsza reguła może to przetestować przez bind("id") gt 1000 albo, dla przechwycenia pozycyjnego (bez nazwy), bind[0].
Czas
Jedna suma plus podział na fazy, żeby alert "spowolniło" mógł też powiedzieć, która część zwolniła.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
time | Całkowity czas odpowiedzi: connect + TLS + oczekiwanie + pobieranie. Rozwiązywanie DNS nie jest wliczone. | number | time lt 2000 |
ttfb (zarezerwowane - jeszcze niewypełniane) | Czas do pierwszego bajtu. | number | ttfb lt 200 |
time.connect | Czas ustanowienia połączenia TCP. | number | time.connect lt 500 |
time.data | Czas pobrania treści odpowiedzi. | number | time.data lt 1000 |
time.dns | Czas rozwiązania nazwy domeny. Niewliczony do samego podmiotu time. | number | time.dns lt 200 |
time.head | Czas oczekiwania na nagłówki odpowiedzi. | number | time.head lt 500 |
time.tls | Czas handshake TLS. | number | time.tls lt 300 |
Sam podmiot time to connect + TLS + oczekiwanie na nagłówki + pobieranie treści. Rozwiązywanie DNS jest wykluczone i żyje tylko w bratnim time.dns, bo DNS jest często cache'owany i w przeciwnym razie ten sam endpoint wyglądałby na niespójnie szybki lub wolny między sprawdzeniami.
Sieć: DNS i połączenie
dns i conn to czyste przestrzenie nazw w rejestrze - grupa bez własnej wartości, więc reguła nigdy nie może zakończyć się na samej nazwie (zarówno edytor, jak i silnik odrzucają łańcuch kończący się na samym dns lub conn, kierując Cię do prawdziwych pól poniżej).
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
conn | Połączenie sieciowe wykonane przez sprawdzenie - adres, który obsłużył odpowiedź, i wszelkie błędy połączenia. | string | - |
conn.failed | Ile z rozwiązanych adresów nie udało się połączyć. | number | conn.failed eq 0 |
conn.failedIps (kandydat - wdrażane na agentów) | Rozwiązane adresy, które nie połączyły się. | collection | conn.failedIps.count eq 0 |
conn.ip | Adres IP, który faktycznie obsłużył odpowiedź. | string | conn.ip eq "203.0.113.10" |
conn.ip.family (kandydat - wdrażane na agentów) | Czy odpowiedź została obsłużona przez IPv4, czy IPv6. | string | conn.ip.family eq "IPv4" |
dns | Rozwiązywanie DNS monitorowanej nazwy - na jakie adresy się rozwiązała i który serwer odpowiedział. | string | - |
dns.ips | Wszystkie adresy IP, na które rozwiązała się nazwa domeny podczas tego sprawdzenia. | collection | dns.ips contains "1.2.3.4" |
dns.server | Serwer DNS, który odpowiedział na rozwiązanie. | string | dns.server eq "8.8.8.8" |
TLS i certyfikat
Podobnie jak dns i conn, tls i cert to czyste przestrzenie nazw - fakty o certyfikacie/handshake żyją jeden poziom niżej.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
cert.days.left | Dni pozostałe do wygaśnięcia certyfikatu witryny. | number | cert.days.left gt 14 |
cert | Certyfikat przedstawiony przez serwer - dni do wygaśnięcia, wystawca i pola tożsamości. | string | - |
cert.days | Dni od wystawienia certyfikatu. | number | cert.days gt 0 |
cert.issuer | Urząd certyfikacji, który wystawił certyfikat witryny. | string | cert.issuer contains "Let's Encrypt" |
cert.san | Nazwy domen, dla których certyfikat jest ważny. | collection | cert.san contains "www.example.com" |
cert.serial | Numer seryjny certyfikatu. | string | cert.serial exists |
cert.subject (zarezerwowane - jeszcze niewypełniane) | Podmiot certyfikatu. Jeszcze nieprzechwytywane - pojawi się z przyszłą wersją agenta. | string | cert.subject contains "example.com" |
tls | Handshake TLS zabezpieczonego połączenia - wynegocjowana wersja protokołu i szyfr. | string | - |
tls.cipher | Wynegocjowany zestaw szyfrów. | string | tls.cipher contains "AES" |
tls.protocol | Wynegocjowana wersja TLS. | string | tls.protocol eq "Tls13" |
cert.subject jest wymieniony tutaj dla kompletności, ale nie jest jeszcze wypełniany - zobacz sekcję Uczciwość poniżej, co w praktyce oznacza "zarezerwowane". Codzienna reguła certyfikatu to cert.days.left gt 14, omówiona w sekcji gotowych reguł.
Podmioty przeskoków: pola wewnątrz requests i redirects
requests i redirects to kolekcje, a każdy element to pełny rekord żądania/odpowiedzi z własnym, zredukowanym zestawem pól. Nie każdy podmiot najwyższego poziomu ma sens per-przeskok (przeskok nie ma własnego certyfikatu), a jedno pole istnieje tylko per-przeskok: hstsHeader, nagłówek Strict-Transport-Security tego żądania w łańcuchu.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
status | Kod statusu tego żądania w łańcuchu. | number | status eq 200 |
url | URL, do którego wykonano to żądanie. | url | url startsWith "https://" |
header | Nagłówek odpowiedzi tego żądania. Przeskok trzyma zredukowany, jednowartościowy rekord nagłówka - predykaty listowe (containsAny, containsAll, unique) stosują się tylko do nagłówka odpowiedzi końcowej. | string | header("Content-Type") contains "json" |
hstsHeader | Nagłówek Strict-Transport-Security tego żądania. | string | requests[0].hstsHeader exists |
setCookie | Wartości nagłówka Set-Cookie tego żądania. | collection | setCookie exists |
url.original | URL, z którym skonfigurowano sprawdzenie, przed jakimkolwiek przekierowaniem. url taki jak sam url: te same części (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.host | Część URL z hostem. | string | url.host eq "example.com" |
url.port | Część URL z portem. | number | url.port eq 443 |
url.path | Część URL ze ścieżką. | string | url.path startsWith "/api" |
url.query | Ciąg zapytania URL. | string | url.query contains "token" |
url.scheme | Schemat URL (http lub https). | string | url.scheme eq "https" |
url.original.host | Część URL z hostem. | string | url.original.host eq "example.com" |
url.original.port | Część URL z portem. | number | url.original.port eq 80 |
url.original.path | Część URL ze ścieżką. | string | url.original.path startsWith "/start" |
url.original.query | Ciąg zapytania URL. | string | url.original.query contains "utm_" |
url.original.scheme | Schemat URL (http lub https). | string | url.original.scheme eq "http" |
Per-przeskokowy header(...) trzyma zredukowany, jednowartościowy rekord: predykaty listowe, takie jak containsAny czy unique, mają sens tylko na pełnej mapie nagłówków odpowiedzi końcowej, więc stosują się tam, a nie per-przeskok. Te dwie kolekcje znaczą coś innego. requests to cały łańcuch łącznie z odpowiedzią końcową, więc nigdy nie jest pusty nawet dla bezpośredniej odpowiedzi 200, podczas gdy redirects to tylko przeskoki przebyte po drodze, pusty, gdy nic nie przekierowało.
Zakresy elementów: pola wewnątrz jednego elementu kolekcji
Zakres elementu to zestaw pól dostępnych na JEDNYM elemencie kolekcji - po zaindeksowaniu do niego (requests[0]) albo przy filtrowaniu przez where(current. ...) (zobacz kolejną sekcję). Sześć kolekcji ma własny zakres elementu: cztery kolekcje elementów HTML dzielą jeden kształt, a requests/redirects dzielą kształt podmiotów przeskoku udokumentowany powyżej.
| Zakres elementu | Jak wygląda jeden element |
|---|---|
body.html.path | Jeden element dopasowany przez zapytanie CSS body.html.path("selector"). |
body.html.a | Jeden element linku <a> z body.html.a. |
body.html.script | Jeden element <script> z body.html.script. |
body.html.link | Jeden element <link> z body.html.link. |
requests | Jedno żądanie w pełnym łańcuchu (zobacz tabelę podmiotów przeskoku powyżej). |
redirects | Jeden przebyty przeskok przekierowania (te same pola co requests, zobacz powyżej). |
Wspólny kształt dla body.html.path(...), body.html.a, body.html.script i body.html.link - jeden wiersz na link, tag script albo element <link>:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
url | Cel linku dokładnie tak, jak zapisuje go znacznik. | string | body.html.a.url contains "/checkout" |
text | Widoczny tekst elementu. | string | body.html.a.text contains "Sign in" |
absolute | Cel linku rozwiązany względem URL strony do adresu absolutnego - lista url, z częściami url dostępnymi na element (.host, .path, .port, .query, .scheme). | url | body.html.a.absolute.scheme in ["https"] |
rel | Atrybut rel elementu. | string | body.html.a.where(current.rel eq "nofollow").count eq 0 |
absolute.host | Część URL z hostem. | string | body.html.a.absolute.host.unique.count le 3 |
absolute.port | Część URL z portem. | number | body.html.a.absolute.port in [443] |
absolute.path | Część URL ze ścieżką. | string | body.html.a.absolute.path startsWith "/" |
absolute.query | Ciąg zapytania URL. | string | body.html.a.absolute.query not contains "session" |
absolute.scheme | Schemat URL (http lub https). | string | body.html.a.absolute.scheme in ["https"] |
Zanim napiszesz regułę wobec tych kolekcji, obowiązują dwa domyślne ustawienia. Sama wzmianka body.html.a (albo .script/.link) oznacza jej projekcję .url, więc body.html.a.count gt 0 liczy hrefy, a zapisana reguła odczytuje się z powrotem z wypisanym .url, bo zapisana reguła zawsze mówi dokładnie, co ocenia. A .url to surowy atrybut href dokładnie tak, jak zapisał go znacznik, więc link względny zostaje względny; .absolute to ten sam link rozwiązany względem własnego URL strony, czego chcesz przy sprawdzaniu schematu czy hosta linków wychodzących (body.html.a.absolute.scheme in ["https"]).
Operatory
Połowa predykatowa każdej reguły: jaki test uruchomić wobec podmiotu. Wszystkie 15 jest wspólnych dla każdego rodzaju sprawdzenia, a to, które pasują do danego podmiotu, zależy od jego typu (kod statusu przyjmuje lt/gt, treść przyjmuje contains, kolekcja przyjmuje exists/unique/in).
| Nazwa | Co to jest | Stosuje się do | Przykład |
|---|---|---|---|
eq | Równe. Wobec literału json("…") / xml("…") / yaml("…") to DOKŁADNE dopasowanie strukturalne: te same klucze (w dowolnej kolejności), tablice w kolejności, te same wartości. | dowolny typ | body.json eq json("{\"ok\": true}") |
lt | Mniejsze niż. | liczby | time lt 2000 |
le | Mniejsze lub równe. | liczby | cert.days.left le 30 |
gt | Większe niż. | liczby | body.size gt 0 |
ge | Większe lub równe. | liczby | status ge 500 |
contains | Zawiera tekst - nad listą przechodzi, gdy wartość JEST jednym z elementów (dopasowanie dokładne; użyj matches, żeby szukać wewnątrz elementów). Wobec literału json("…") / xml("…") / yaml("…") to STRUKTURALNE zawieranie: wszystko, co stwierdza literał, musi być obecne i pasować; odpowiedź może mieć więcej. | tekst lub lista | body.json contains json("{\"status\": \"ok\"}") |
startsWith | Zaczyna się od tekstu - nad listą, gdy KTÓRYKOLWIEK element tak zaczyna. | tekst | url.path startsWith "/api" |
endsWith | Kończy się tekstem - nad listą, gdy KTÓRYKOLWIEK element tak się kończy. | tekst | url.path endsWith ".json" |
matches | Pasuje do wyrażenia regularnego gdziekolwiek w tekście - nad listą, gdy pasuje KTÓRYKOLWIEK element. | tekst | body matches "order-\\d+" |
containsAny | Zawiera co najmniej jedną z wymienionych wartości (nad listą: jakiś element RÓWNA SIĘ jednej z nich). | lista | body containsAny ["In stock", "Pre-order"] |
containsAll | Zawiera każdą z wymienionych wartości (nad listą: każda wartość równa się jakiemuś elementowi - świadkowie mogą się różnić). | lista | body.html.a.text containsAll ["Home", "Contact"] |
in | Jest jedną z wymienionych wartości lub zakresów - nad listą, każdy element jest. | wartość/wartości lub zakres | status in [200, 301, 302] |
exists | Podmiot jest obecny. | dowolny podmiot | header("ETag") exists |
isNumber | Wartość da się odczytać jako liczbę. | tekst lub dowolne | bind("id") isNumber |
unique | Lista nie ma duplikatów. | lista | dns.ips unique |
Dwa operatory znaczą coś węższego, niż brzmią. contains nad listą to dokładne członkostwo: wartość musi równać się całemu elementowi, a nie pojawiać się jako podciąg wewnątrz jednego, więc sięgnij po matches, gdy chcesz zachowania podciągu w elementach kolekcji. A eq wobec literału json(...)/xml(...)/yaml(...) to pełne dopasowanie strukturalne (te same klucze, tablice w tej samej kolejności, te same wartości), podczas gdy contains wobec tego samego rodzaju literału to strukturalne zawieranie: wszystko, co stwierdza literał, musi być obecne, ale prawdziwa odpowiedź może nieść więcej.
Reduktory
Reduktor zwija kolekcję do jednej wartości i może pojawić się tylko na końcu łańcucha. Poniższe przykłady używają requests.status, naturalnie numerycznej kolekcji tworzonej przez podmioty HTTP, jako ilustracji; tych samych osiem reduktorów działa na dowolnej kolekcji numerycznej w dowolnym rodzaju sprawdzenia (czasy round-trip sprawdzenia Ping, przefiltrowany zestaw wierszy bazy danych).
| Nazwa | Co zwija | Stosuje się do | Przykład |
|---|---|---|---|
count | Ile elementów ma lista. | dowolna kolekcja | requests.count le 2 |
min | Najmniejsza liczba na liście. | kolekcja numeryczna | requests.status.min ge 200 |
max | Największa liczba na liście. | kolekcja numeryczna | requests.status.max lt 500 |
sum | Suma liczb na liście. | kolekcja numeryczna | requests.status.sum gt 0 |
avg | Średnia liczb na liście. | kolekcja numeryczna | requests.status.avg lt 300 |
first | Pierwszy element listy. | dowolna kolekcja | redirects.status.first eq 301 |
last | Ostatni element listy. | dowolna kolekcja | requests.status.last eq status |
unique | Lista z usuniętymi duplikatami. | dowolna kolekcja | dns.ips.unique.count le 3 |
unique jest przeciążone, a zapis odróżnia dwa znaczenia. Zapisane jako operator bez kropki (x unique) to predykat, "ta kolekcja nie ma duplikatów", i zawodzi, nazywając powtórkę. Zapisane jako reduktor z kropką (x.unique) to transformacja, sama zdeduplikowana kolekcja, która wciąż potrzebuje czegoś po sobie (x.unique.count eq 1). Wiszące x.unique bez niczego po sobie to błąd składni, bo silnik nie potrafi odgadnąć, które z dwóch znaczeń miałeś na myśli.
Cukier składniowy
Predykaty cukru składniowego to skróty, które silnik rozwija w zwykłe predykaty rdzenia, zanim reguła w ogóle zostanie wysłana do agenta - dodanie predykatu cukru nie kosztuje nic dodatkowego (żadnego pakietu agenta, żadnego progu wersji), bo zanim dotrze na drut, już wygląda jak zwykła reguła. Preferuj cukier, gdziekolwiek istnieje: czyta się lepiej i jest dokładnie równoważny ręcznemu wypisaniu długiej formy.
| Nazwa | Co oznacza | Stosuje się do | Przykład |
|---|---|---|---|
isOk | Status to kod sukcesu (200-299). | status | - |
isRedirect | Status to kod przekierowania (300-399). | status | status isRedirect |
isClientError | Status to błąd klienta (400-499). | status | status isClientError |
isServerError | Status to błąd serwera (500-599). | status | status isServerError |
isJson | Treść rzeczywiście jest JSON. | dokument lub tekst typu media | header("Content-Type") isJson |
isXml | Treść rzeczywiście jest XML - treść parsuje się jako XML, albo nagłówek nazywa typ media XML. | dokument lub tekst typu media | body isXml |
isHtml | Treść rzeczywiście jest HTML - treść parsuje się jako HTML, albo nagłówek nazywa typ media HTML. | dokument lub tekst typu media | body isHtml |
isForm | Typ media nazywa kodowanie formularza: application/x-www-form-urlencoded lub multipart/form-data. W odróżnieniu od isJson/isXml/isHtml nie ma pasującej przestrzeni nazw treści, więc to stosuje się tylko do wartości typu media, na przykład nagłówka Content-Type. | tylko tekst typu media | header("Content-Type") isForm |
isEmpty | Nic tam nie ma: pusty tekst, zerowy rozmiar albo pusta lista. | tekst, rozmiar lub lista | body isEmpty |
isNull | Wartość jest null. | dowolna wartość | body.json.path("$.deletedAt") isNull |
absent | Podmiot w ogóle nie jest obecny. | dowolny podmiot | header("X-Debug") absent |
between | Liczba w zakresie domkniętym. | liczby (2 operandy) | body.size between 50 and 500kb |
isJson/isXml/isHtml są celowo zależne od kontekstu, a to, na czym je zapiszesz, decyduje, które znaczenie się stosuje. Zapisane na samym dokumencie (body isJson) oznaczają "czy to parsuje się jako ten format", tak samo jak body.json exists. Zapisane na wartości tekstowej nazywającej typ media, na przykład na nagłówku (header("Content-Type") isJson), oznaczają "czy to nazywa tę rodzinę MIME formatu"; zobacz Rodziny MIME poniżej, które typy media się kwalifikują. isForm ma tylko to drugie znaczenie, bo nie istnieje przestrzeń nazw body.form do sparsowania, więc body isForm to błąd statyczny, a nie reguła, która nigdy nie mogłaby być prawdziwa.
Filtr where(...)
Zachowaj tylko elementy, które pasują, a potem kontynuuj od nich. To jedyna konstrukcja filtrująca w języku i ma dokładnie jeden kształt: where(current.<pole> <warunek> <wartość>).
Filtrowanie różni się od projekcji: requests.url contains "cart" pyta, czy taki przeskok istnieje gdziekolwiek w łańcuchu, podczas gdy requests.where(current.url contains "cart").status pyta, co ten przeskok zwrócił. Filtrowanie nie zwija listy, więc zakończ przez .first, sprawdzenie in [...] albo .count. Idzie tylko jeden poziom i przyjmuje dokładnie jeden warunek.
| Część | Co nazywa | Uwagi |
|---|---|---|
current.<pole> | Pole każdego filtrowanego elementu, zapisane po current. | To połowa, którą ludzie mylą: current.url to URL pojedynczego przeskoku, nie odpowiedzi końcowej. Po current. mogą następować tylko własne pola elementu. |
| warunek | Dowolny zwykły predykat, łącznie z not i nocase | Każdy warunek, który działa na najwyższym poziomie reguły, działa też tutaj. |
| wartość | Z czym porównywane jest pole każdego elementu | Zwykle zwykła wartość. Podmiot zapisany tutaj jest czytany z ZEWNĘTRZNEJ odpowiedzi, nie z elementu - where(current.url eq url.original) porównuje każdy przeskok z URL, z którym skonfigurowano sprawdzenie, dlatego strona elementu musi wprost powiedzieć current.. |
Przykład: requests.where(current.url contains "cart").status.first eq 301 - zachowaj tylko przeskoki, których URL zawiera "cart", potem spójrz na status pierwszego z pasujących.
Jeszcze dwa ograniczenia, oba egzekwowane przez parser z własnym komunikatem: where nie może być zagnieżdżone wewnątrz innego where, a jego argument to dokładnie jeden warunek, bez and/or w środku. Stosuje się tylko do kolekcji, której elementy niosą nazwane pola (requests, body.html.a), nie do zwykłej zrzutowanej listy, takiej jak dns.ips, gdzie nie ma niczego, co mogłoby nazwać current..
Słownik składni
Wszystko inne, co definiuje gramatyka: jak nazwać regułę, jak zapisywać zakresy i listy, co oznacza sam podmiot bez niczego więcej, i drobne formy interpunkcyjne pojawiające się w wielu regułach.
| Forma | Co robi | Rodzaj | Przykład |
|---|---|---|---|
where | Zachowaj tylko elementy, które pasują, a potem kontynuuj od nich. | filtr kolekcji | requests.where(current.url contains "cart").status.first eq 301 |
not | Odwraca warunek, który następuje. | flaga | body not contains "error" |
nocase | Porównaj tekst bez rozróżniania wielkości liter. | flaga | body contains "welcome" nocase |
current | Wewnątrz where(…) nazywa jeden filtrowany element. | odniesienie do elementu (wewnątrz where) | requests.where(current.status eq 301) |
range | Zakres liczb, oba końce WŁĄCZONE. | zakres liczb | status in [200..299] |
list | Lista wartości do porównania. | lista wartości | status in [200, 301, 302] |
docLiteral | Typowana wartość dokumentu do porównania strukturalnego: cytowany tekst jest parsowany jako JSON, XML lub YAML przy zapisie reguły. | tekst json/xml/yaml | body.json contains json("{\"user\": {\"active\": true}}") |
implicitExists | Reguła nazywająca tylko podmiot sprawdza, że jest obecny: samo napisanie body.json zapisuje się jako body.json exists. | linia z samym podmiotem | body.json |
index | Wybiera JEDEN element listy po pozycji, licząc od 0. | liczba całkowita od 0 | requests[0].status |
label | Opcjonalna nazwa reguły, zapisana przed dwukropkiem. | nazwa przed dwukropkiem | "json ok": body.json exists |
comment | Wszystko po # to notatka dla Ciebie samego; nie wpływa na sprawdzenie. | tekst # na końcu | status isOk # the happy path |
Kilka wartych zwykłego omówienia. label nadaje regule nazwę, która pojawia się w alercie zamiast wyrenderowanego wyrażenia; zapisz ją przed dwukropkiem, jak w "json ok": body.json exists. implicitExists oznacza, że linia nazywająca tylko podmiot bez predykatu to skrót od exists: zapisanie body.json zapisuje się jako body.json exists, a ponowne otwarcie reguły pokazuje wypisaną formę. range i list to dwa kształty, jakie może przyjąć wartość po in: zakres ([200..299], oba końce włączone) albo jawna lista ([200, 301, 302]), a wartość może być otwarta na jednym z końców ([400..]). docLiteral to opakowanie json(...)/xml(...)/yaml(...) używane do porównania strukturalnego z treścią (omówione w Operatorach powyżej i w gotowych regułach poniżej). index wybiera jeden element kolekcji po pozycji, licząc od 0, tak samo jak bind[0] odczytuje przechwycenie pozycyjne. current ma znaczenie tylko wewnątrz filtra where(...), omówionego we własnej sekcji powyżej.
Opakowania: previous, delta i delta2
Trzy formy patrzące wstecz zamiast tylko na bieżącą odpowiedź - każda jest zablokowana za planami z asercjami stanowymi, a każda jest wyjaśniona w pełni w sekcji "Porównywanie z poprzednim sprawdzeniem" poniżej.
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
delta (wymaga planu z asercjami stanowymi) | Jak bardzo wartość numeryczna zmieniła się od poprzedniego sprawdzenia - opcjonalnie jako tempo na ms/s/m/h. | number | delta(body.size, h) lt 1mb |
delta2 (wymaga planu z asercjami stanowymi) | Zmiana zmiany - czy wartość przyspiesza? | number | delta2(time) gt 0 |
previous (wymaga planu z asercjami stanowymi) | Wartość tego podmiotu z poprzedniego sprawdzenia. | dowolne | status eq previous.status |
Flagi: not i nocase
Dwa modyfikatory dołączane do reguły, a nie stojące jako samodzielne podmioty czy predykaty.
| Flaga | Co robi | Rodzaj | Przykład |
|---|---|---|---|
not | Odwraca warunek, który następuje. | flaga (dołącza się do reguły) | body not contains "error" |
nocase | Porównaj tekst bez rozróżniania wielkości liter. | flaga (dołącza się do reguły) | body contains "welcome" nocase |
not łączy się z predykatem, który następuje, a nie neguje całej reguły jako jednostki - x not != y czyta się jak x eq y, nie jak podwójne zaprzeczenie. Gdy podmiot może być całkowicie nieobecny, preferuj cukier absent zamiast not exists: te dwa znaczą dokładnie to samo, ale absent mówi to wprost. nocase zmienia coś tylko przy porównaniu naprawdę tekstowym; edytor (i ten słownik) wciąż pozwala zapisać to wszędzie, ale jest bez znaczenia przy teście numerycznym, jak status eq 200 nocase.
Rodziny MIME
Tabele wyszukiwania stojące za isJson, isXml, isHtml i isForm, gdy stosuje się je do wartości typu media, takiej jak nagłówek. Każda rodzina dopasowuje oczywisty typ media najwyższego poziomu plus, dla JSON i XML, dowolny typ kończący się pasującym sufiksem składni strukturalnej - to sprawia, że header("Content-Type") isJson poprawnie przechodzi na application/problem+json czy application/vnd.api+json, a nie tylko na zwykłym application/json.
| Rodzina | Dopasowuje | Sparowany cukier | Przykład |
|---|---|---|---|
json | application/json, text/json albo dowolny typ media kończący się na +json (application/problem+json, application/vnd.api+json, application/ld+json, ...). | cukier: isJson | header("Content-Type") isJson |
xml | application/xml, text/xml albo dowolny typ media kończący się na +xml (image/svg+xml, application/atom+xml, ...). | cukier: isXml | header("Content-Type") isXml |
html | text/html albo application/xhtml+xml. | cukier: isHtml | header("Content-Type") isHtml |
form | application/x-www-form-urlencoded albo multipart/form-data. | cukier: isForm | header("Content-Type") isForm |
Dopasowanie ignoruje wszystko od pierwszego ; wzwyż (więc application/json; charset=utf-8 wciąż pasuje) i nie rozróżnia wielkości liter.
Podmioty dla sprawdzeń bazy danych, licznika, SNMP, portu i ping
Każdy operator, reduktor, skrót cukru i forma składni powyżej jest identyczny dla tych pięciu rodzajów sprawdzeń: silnik rejestruje te same 15 operatorów, 8 reduktorów, 12 predykatów cukru i 11 form składni dla wszystkich sześciu rodzajów bez wyjątku. Tym, co różni się w zależności od rodzaju, jest lista podmiotów. Każdy rodzaj eksponuje mały zestaw podmiotów unikalnych dla tego, co mierzy, plus podzbiór podmiotów sieciowych/czasowych/TLS już udokumentowanych powyżej, ze znaczeniem dostosowanym do rodzaju (time sprawdzenia Database to connect-plus-zapytanie, a nie connect-plus-TLS-plus-pobieranie, bo nie ma odpowiedzi HTTP do pobrania).
Sprawdzenia bazy danych
Dzieli time, time.connect i time.dns z podmiotami udokumentowanymi powyżej (przeskalowane do połączenia z bazą danych: connect-plus-zapytanie, rozwiązywanie DNS hosta bazy danych). Unikalne dla sprawdzeń bazy danych:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
scalar | Pojedyncza wartość zwrócona przez zapytanie (tryb Scalar). | dowolne | - |
rows | Wiersze, na które zapytanie wpłynęło lub które zwróciło (tryb NonQuery). | collection | - |
time.query | Czas, jaki zajęło samo zapytanie. | number | - |
Gotowy przykład jest w kolejnej sekcji: użyj rows.count, żeby sprawdzić, na ile wierszy wpłynęło lub ile zwróciło zapytanie, i scalar, żeby sprawdzić bezpośrednio pojedynczą zwróconą wartość.
Sprawdzenia licznika
Dzieli time z podmiotami udokumentowanymi powyżej - jako pole ze statusem kandydata specyficznie dla sprawdzeń Counter (czas round-trip żądania licznika; zobacz sekcję Uczciwość, co znaczy "kandydat"). Unikalne dla sprawdzeń licznika:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
value | Zmierzona wartość licznika. | number | - |
Sprawdzenia SNMP
Dzieli time i time.dns z podmiotami udokumentowanymi powyżej (rozwiązywanie nazwy hosta plus samo żądanie SNMP). Unikalne dla sprawdzeń SNMP:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
time.request | Czas, jaki zajęło żądanie SNMP. | number | - |
value | Wartość zwrócona przez OID. | dowolne | - |
value.type (kandydat - wdrażane na agentów) | Nazwa typu danych SNMP zwróconej wartości. | string | - |
value.type ma status kandydata; zobacz sekcję Uczciwość. Uwaga o dostępności: przełącznik Weryfikacji odpowiedzi trybu asercji nie dotarł jeszcze do edytora monitora SNMP. Pokazuje panel "Wkrótce" nazywający te dwa podmioty zamiast działającej listy reguł. Podmioty i leżący pod nimi ewaluator są już zarejestrowane; tylko interfejs edytora SNMP wciąż czeka.
Sprawdzenia portu
Największa wspólna lista spośród wszystkich rodzajów innych niż HTTP. Sprawdzenie portu TCP niesie zasadniczo te same podmioty połączenia, DNS, TLS i certyfikatu co sprawdzenie HTTP, bo sprawdzenie portu też może negocjować TLS: bind, cert i jego sześć podpól, conn i jego cztery podpola, dns i jego dwa podpola, time/time.connect/time.dns/time.tls, oraz tls/tls.cipher/tls.protocol - wszystkie udokumentowane w sekcjach powyżej, z tymi samymi znaczeniami. Unikalne dla sprawdzeń portu:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
banner | Dane odczytane z gniazda po połączeniu. | string | - |
banner.hash (kandydat - wdrażane na agentów) | Skrót bannera - porównaj z previous.banner.hash, aby wykryć zmiany usługi. | string | - |
banner.regex | Dopasuj tekst wyrażeniem regularnym i weź to, co przechwyciło. | string | body.regex("order-(?<id>\\d+)") exists |
banner.size (kandydat - wdrażane na agentów) | Rozmiar bannera, w bajtach. | number | - |
banner.hash i banner.size mają status kandydata - zobacz sekcję Uczciwość. banner.regex działa już dziś i funkcjonuje dokładnie jak body.regex(...) w sprawdzeniu HTTP: nazwane przechwycenia zasilają tę samą przestrzeń nazw bind(...).
Sprawdzenia ping
Dzieli podmioty połączenia i DNS z sekcjami powyżej: conn, conn.failed, conn.failedIps, conn.ip, conn.ip.family, dns, dns.ips, dns.server, time (tutaj średni czas round-trip udanych odpowiedzi) oraz time.dns. Unikalne dla sprawdzeń ping:
| Nazwa | Co to jest | Typ/wartości | Przykład |
|---|---|---|---|
loss | Procent żądań echo, które nie doczekały się odpowiedzi. | number | loss eq 0 |
reply | Udane odpowiedzi echo. | collection | - |
sentCount (kandydat - wdrażane na agentów) | Ile żądań echo zostało wysłanych. | number | - |
time.max | Czas round-trip najwolniejszej odpowiedzi. | number | - |
time.min | Czas round-trip najszybszej odpowiedzi. | number | - |
ttl | TTL pierwszej udanej odpowiedzi - porównaj z previous.ttl, żeby wykryć zmiany trasy. | number | - |
sentCount ma status kandydata - zobacz sekcję Uczciwość. ttl warto znać nawet poza ścisłą regułą przejścia/niepowodzenia: sparowanie go z previous.ttl (zobacz Opakowania powyżej) sygnalizuje zmianę trasy między sprawdzeniami, bo TTL pakietu przy przybyciu odzwierciedla, ile przeskoków przebył.
Reguły, które ludzie naprawdę chcą pisać
Strona działa i faktycznie mówi to, co trzeba
Sam kod statusu nie potrafi powiedzieć, czy strona wyrenderowała się poprawnie - odpowiedź 200 z pustą powłoką to klasyczna cicha awaria, którą pomija sprawdzenie oparte tylko na statusie.
status isOk
body contains "Add to cart"
API odpowiada JSON-em i oczekiwanym polem
Sprawdź, że endpoint wciąż mówi JSON, a potem sięgnij w głąb. Pierwsza linia wyłapuje stronę błędu HTML serwowaną tam, gdzie powinien być JSON, częsty kształt awarii za proxy; druga sprawdza własny zgłaszany stan zdrowia API, nie tylko jego status transportu.
body isJson
body.json.path("$.status") eq "ok"
Odpowiedź zwolniła bardziej, niż powinna
Rozbij to na części, gdy musisz wiedzieć, co naprawić, a nie tylko, że coś jest wolne - time.connect, time.tls, time.dns i time.head rozdzielają czas sieci, handshake, resolvera i aplikacji.
time lt 2s
Przekierowanie wysłało odwiedzających poza Twoją własną domenę
Porównuje, gdzie wylądowało sprawdzenie, z URL, który skonfigurowałeś - zawodzi w chwili, gdy łańcuch przekierowań, przejęty, źle skonfigurowany albo po prostu zmieniony przez wdrożenie, wyląduje tam, gdzie nie zamierzałeś.
url.host eq url.original.host
Strona zmieniła się od ostatniego sprawdzenia
Przydatne na treści, które powinny być stabilne między sprawdzeniami - cennik, regulamin, opublikowana polityka - i podwaja się jako podstawowy sygnał defacementu.
previous.body.hash eq body.hash
Liczba w zakresie, zapisana krótszym sposobem
Wyłapuje jednocześnie okrojoną stronę i rozpędzoną, w jednej regule, bez wypisywania jawnego zakresu.
body.size between 50 and 500kb
Certyfikat, który zaraz wygaśnie
Najczęstsze ze wszystkich sprawdzeń TLS, i takie, którego zwykły monitor działa/nie działa w ogóle nie potrafi wyrazić - certyfikat, który dziś wciąż się waliduje, ale wygasa za tydzień, nie daje żadnego innego ostrzeżenia. Sparuj to z cert.issuer, jeśli chcesz też wyłapać certyfikat po cichu wystawiony przez niewłaściwy urząd.
cert.days.left gt 14
Zapytanie do bazy danych zwracające złą liczbę wierszy
W sprawdzeniu Database rows to kolekcja, na którą zapytanie wpłynęło lub którą zwróciło - liczenie jej wyłapuje zapytanie, które powinno zwracać dokładnie jeden rekord konta, cicho zaczynające zwracać zero (usunięty, albo zepsuty join) albo więcej niż jeden (duplikat, który nie powinien istnieć).
rows.count eq 1
Wartość SNMP dryfująca poza zakres
Urządzenie SNMP, które w ogóle odpowiada, to nie to samo co zdrowe - monitorowany OID (wykorzystanie dysku, głębokość kolejki, temperatura) może wspiąć się dobrze poza bezpieczny próg, podczas gdy samo urządzenie pozostaje w pełni osiągalne. Porównanie odpytanej value z zakresem wyłapuje to, czego zwykłe sprawdzenie osiągalności nie potrafi.
value lt 90
Usługa TCP odpowiadająca złym bannerem
Port, który przyjmuje połączenia, to nie to samo co właściwa usługa na nim nasłuchująca - zawieszony proces, źle skonfigurowane proxy albo obniżona/podmieniona usługa wciąż mogą dokończyć handshake TCP. Odczytanie tekstu powitalnego wysyłanego przez usługę zaraz po połączeniu (banner SMTP, FTP lub podobny) wyłapuje to, czego samo sprawdzenie otwartego portu nie potrafi.
banner contains "220"
Porównywanie z poprzednim sprawdzeniem
Garstka podmiotów patrzy wstecz zamiast tylko na bieżącą odpowiedź: umieść previous. przed podmiotem, żeby odczytać, jaki był przy ostatnim sprawdzeniu, albo opakuj go w delta(...), żeby uzyskać różnicę między wtedy a teraz, albo w delta2(...), żeby uzyskać zmianę tej zmiany - przydatne do wyłapania wartości przyspieszającej, a nie tylko dryfującej (czas odpowiedzi rosnący coraz szybciej z każdym sprawdzeniem). previous.body.hash eq body.hash powyżej to dokładnie to - "czy odcisk palca treści pasuje do tego, jaki był ostatnim razem." delta(body.size, h) odczytuje zmianę jako tempo na godzinę zamiast surowej różnicy, dla wartości, które oczekujesz, że będą rosły stopniowo, a nie skakały.
Za pierwszym razem, gdy taka reguła się uruchamia, nie ma niczego do porównania, więc jest pomijana zamiast zawodzić: sprawdzenie jest oznaczane jako "rozgrzewa się", nie jako zepsute, a dodanie reguły nie wywołuje fałszywego alertu. Rozgrzewanie stosuje się tylko wtedy, gdy bieżący odczyt jest poprawny, a brakuje punktu odniesienia. Jeśli sam bieżący odczyt zawodzi (powiedzmy, treść tym razem nie jest poprawnym JSON-em), reguła zawodzi dokładnie tak, jak zawiodłaby jej zwykła wersja bez previous.. Taka reguła wymaga też, żeby wartość zmieniała się między sprawdzeniami, co czyni ją bez znaczenia przy metodzie sprawdzenia, która nigdy nie przesuwa stanu, na przykład żądaniu HEAD.
Porównywanie z poprzednim sprawdzeniem wymaga planu wyższego poziomu; bez niego te podmioty pojawiają się w edytorze wyszarzone, z wyjaśnieniem.
Limity i to, czego celowo brakuje
Ile reguł możesz dodać, zależy od Twojego planu, pokazywane jako żywy licznik obok "Add rule." Silnik egzekwuje też bezwzględny sufit na każde sprawdzenie niezależnie od planu, zabezpieczenie przed nadużyciem, a nie limit dla zwykłego użycia: sprawdzenie z liczbą reguł zbliżoną do tego sufitu byłoby już niezwykle duże.
Nie ma sposobu, by napisać własny JavaScript dla reguły, i nigdy nie będzie. Każda reguła jest zbudowana ze stałego, nazwanego słownictwa podmiotów i predykatów, a nie z otwartej piaskownicy skryptowej, co utrzymuje regułę czytelną na pierwszy rzut oka i bezpieczną do uruchomienia na każdym agencie monitoringu na świecie.
Nie każda reguła działa wszędzie w chwili, gdy zostanie napisana: niektóre nowsze warunki potrzebują niedawnej wersji agenta monitoringu wykonującego Twoje sprawdzenie, więc nowa możliwość potrzebuje czasu, żeby dotrzeć do każdego sprawdzenia na Twoim koncie, w miarę jak agenci aktualizują się w tle. Reguły zbudowane na stabilnym rdzeniu języka nie są tym dotknięte.
Garstka wpisów w tym słowniku nie jest jeszcze w pełni aktywna, każdy oznaczony w tabeli powyżej:
- Zarezerwowane (zadeklarowane, jeszcze niewypełniane przez żadnego agenta):
ttfb,httpVersion,cert.subject. - Kandydat (już się wdraża, jeszcze nie na każdym agencie):
conn.ip.familyiconn.failedIpsw sprawdzeniach HTTP, Port i Ping,value.typew sprawdzeniach SNMP,banner.hashibanner.sizew sprawdzeniach Port,sentCountw sprawdzeniach Ping, oraz własnetimesprawdzenia Counter. - Jeszcze niedostępne:
steps, zarezerwowane dla przyszłego typu sprawdzenia wieloetapowego. - Wymaga planu z asercjami stanowymi: cała rodzina opakowań
previous/delta/delta2, w każdym rodzaju sprawdzenia.
Wszystko inne w tym słowniku działa już dziś na każdym planie z trybem asercji.
Gdzie tryb asercji działa już dziś
Przełącznik Weryfikacji odpowiedzi dla trybu asercji pojawia się w monitorach HTTP (strona) i API, które dzielą ten sam edytor reguł i składnię. Ten sam język i ewaluator już działają pod spodem sprawdzeń Database, Counter, Port, Ping i SNMP na poziomie protokołu: powyższy rejestr obsługuje wszystkie sześć rodzajów sprawdzeń, a reguła zapisana dla jednego czyta się tak samo, jeśli tryb dotrze później do edytora innego typu.
SNMP pokazuje najwyraźniejszy podgląd: jego edytor ma już panel reguł asercji nazywający value i value.type, oznaczony "Wkrótce", jeszcze bez działającej listy reguł za nim. Sprawdzenia Database, Counter i Ping w ogóle nie pokazują panelu trybu asercji, mimo że ich podmioty są równie aktywne w silniku pod spodem.
Konfigurowanie prawdziwego sprawdzenia
Jeśli walidujesz REST API, a nie zwykłą stronę internetową, zacznij od walidacji odpowiedzi API, która obejmuje razem uptime, czas odpowiedzi i treść Twojego własnego API. Dla strony lub serwisu, który musi działać i odpowiadać poprawnie wszędzie tam, gdzie są Twoi użytkownicy, globalne monitorowanie uptime z ponad 300 lokalizacji to szerszy obraz, w który wpina się tryb asercji. Żeby ustawiać reguły przez kod zamiast przez panel, własne API v2 HostTracker tworzy i aktualizuje reguły asercji monitora tak samo jak edytor. Dla powyższej reguły wygaśnięcia certyfikatu i wszystkiego innego związanego z TLS, monitorowanie domeny i certyfikatu TLS obejmuje rodzaj sprawdzenia, na którym żyje cert.days.left i inne podmioty TLS. Żeby zobaczyć, jak jedna reguła ocenia prawdziwy URL już teraz, bez konta, użyj darmowego narzędzia do sprawdzania HTTP. Dla kodów statusu, z którymi porównuje podmiot status, zacznij od 200 OK, a poradniki monitoringu obejmują konfigurowanie każdego rodzaju sprawdzenia, pod którym działa ten język.
Najczęściej zadawane pytania
Co się stanie z moimi starymi ustawieniami kodu statusu i słów kluczowych, jeśli włączę tryb asercji?
Są zastępowane listą reguł, dopóki tryb jest włączony. Ponowne wyłączenie go przed zapisaniem przywraca klasyczne pola dokładnie takimi, jakie były: nic nie jest usuwane, oba tryby po prostu nie mogą być aktywne jednocześnie.
Czy mogę połączyć wiele warunków w jednym monitorze?
Tak: każda reguła na liście musi przejść. Nie ma jeszcze "OR" między osobnymi regułami, więc żeby zaakceptować jedną z kilku wartości, użyj pojedynczej reguły z in [...] albo containsAny [...].
Czy tryb asercji kiedykolwiek pozwoli mi napisać własny skrypt?
Nie. Każda reguła jest złożona ze stałego zestawu podmiotów i predykatów języka. Nie ma własnego JavaScriptu, celowo.
Co się dzieje, gdy pierwszy raz dodaję regułę porównującą z poprzednim sprawdzeniem?
Nie ma jeszcze niczego do porównania, więc jest oznaczana jako rozgrzewająca się i pomijana zamiast zawodzić. Dodanie reguły "czy to się zmieniło" nigdy samo z siebie nie wywołuje fałszywego alertu.
Czy potrzebuję konkretnego planu, żeby używać trybu asercji?
Sam tryb i codzienne reguły (status, treść, nagłówki, czas, przekierowania) są szeroko dostępne; ile reguł możesz dodać naraz, zależy od Twojego planu i jest pokazywane na żywo w edytorze. Reguły porównujące z poprzednim sprawdzeniem (previous, delta, delta2) wymagają planu wyższego poziomu i są wyszarzone z wyjaśnieniem.
Czy tryb asercji działa w monitorach API tak samo jak w monitorach strony internetowej?
Tak. Monitory HTTP i API dzielą ten sam edytor reguł, podmioty i predykaty, a reguła napisana dla jednego czyta się identycznie w drugim.
Co właściwie robi where(...) i kiedy go potrzebuję?
Filtruje kolekcję do elementów pasujących do warunku, zanim odczytasz pole wyniku. Użyj go, gdy zwykła projekcja jak requests.status nie jest wystarczająco precyzyjna, a potrzebujesz jednego konkretnego przeskoku, linku czy elementu zamiast całej kolekcji (zobacz sekcję powyżej).
Czy mogę już dziś napisać regułę wobec zapytania do bazy danych, wartości SNMP, bannera portu czy wyniku ping?
Język i ewaluator obsługują je wszystkie, a powyższe tabele podmiotów obejmują każde z nich. Edytor reguł nie: tylko monitory HTTP i API pokazują dziś przełącznik Weryfikacji odpowiedzi. SNMP pokazuje podgląd "Wkrótce" swoich dwóch podmiotów, a Database, Counter i Ping w ogóle nie pokazują panelu trybu asercji.
Dlaczego niektóre podmioty w tym słowniku mówią "zarezerwowane" albo "kandydat" zamiast po prostu być wymienione normalnie?
"Zarezerwowane" oznacza, że pole jest zadeklarowane w rejestrze, ale żaden agent jeszcze go nie wypełnia; "kandydat" oznacza, że wdraża się na agentów, ale jeszcze nie dotarło do wszystkich. Oba są oznaczone wszędzie tam, gdzie się pojawiają w tym słowniku, oraz na liście podsumowującej w sekcji Limity powyżej.