Vai al contenuto principale

Guide / Guide al monitoraggio: ogni tipo di controllo, passo per passo

Modalità assert: referenza completa alla validazione della risposta

La modalità assert sostituisce i campi fissi di successo/fallimento di un monitor con un elenco di regole che scrivi tu stesso, ciascuna delle quali nomina esattamente cosa deve essere vero della risposta. La maggior parte dei monitor di uptime giudica un controllo con una manciata di campi fissi: un codice di stato che conta come "down", un elenco di stati da ignorare, forse una parola chiave che deve comparire da qualche parte nel corpo. Questi campi non possono esprimere un'API che risponde legittimamente 404 per una risorsa mancante, una pagina che restituisce 200 con un guscio vuoto perché il database è andato in timeout, o una catena di redirect che inizia a instradare verso il dominio di qualcun altro.

La modalità assert di HostTracker sostituisce quei campi fissi con un piccolo linguaggio di regole che scrivi tu stesso, regola per regola, dentro l'editor del monitor. Ogni regola dice esattamente cosa deve essere vero della risposta: lo stato, un pezzo del corpo, un'intestazione, quanto tempo ci ha messo, dove è finito un redirect. Un controllo fallisce solo quando una delle tue regole fallisce. È lo stesso linguaggio per un sito web, un'API REST, una query di database, una porta TCP, un target Ping, un contatore SNMP o un controllo Counter generico: un unico insieme di soggetti, un unico insieme di predicati, riusati ovunque compaia la modalità. Questa guida copre ogni soggetto, operatore, riduttore, scorciatoia di zucchero sintattico e forma di sintassi che il motore implementa.

Cosa sostituisce la modalità assert

I classici campi di Response Validation sono ancora lì quando la modalità assert è spenta: un intervallo di stato atteso, un elenco di stati da ignorare, una parola chiave che deve (o non deve) comparire. La modalità è un interruttore che scambia quell'insieme fisso con un elenco di regole che costruisci tu, e disattivarlo di nuovo prima di salvare riporta esattamente i campi classici. Nessun monitor resta bloccato in una modalità in modo permanente.

Un unico linguaggio invece di un mucchio di aggeggi specifici per tipo si compone. Un controllo "deve essere JSON e contenere un campo", un controllo "deve ancora dire Add to cart" e un controllo "non deve essere diventato più lento" sono tre regole nella stessa sintassi, nello stesso elenco, ciascuna passa o fallisce per conto proprio.

Attivarla

La modalità assert vive dentro la sezione Response Validation dell'editor del monitor, per i monitor HTTP (sito web) e API. Attiva l'interruttore, e i campi classici vengono sostituiti da un elenco numerato di regole con un pulsante "Add rule" e un contatore in tempo reale che mostra quante regole hai usato rispetto al limite del tuo piano.

Modalità assert attivata, con la prima regola costruita e convalidata

Ogni regola viene convalidata mentre la costruisci: una regola non ancora finita porta uno stato distinto di "non finita", e una regola che l'editor riesce a valutare viene contrassegnata come completa. Ogni regola ha anche un piccolo pulsante </> che apre la sua forma sorgente in testo semplice, così puoi leggere o copiare l'espressione esatta invece della sola vista a caselle.

Il modello mentale: soggetto, predicato, valore

Ogni regola ha la stessa forma: un soggetto (il codice di stato, il corpo, un'intestazione, il tempo di risposta), un predicato (uguale a, contiene, esiste, è minore di) e, per la maggior parte dei predicati, un valore con cui confrontare. status eq 200 è soggetto, predicato e valore; body.json exists è un soggetto e un predicato senza valore, perché "exists" non ha bisogno di altro.

Costruire una regola nell'editor inizia scegliendo cosa controllare, poi la condizione, poi il valore:

Costruzione di una seconda regola: il selettore di campo elenca ogni soggetto con il suo tipo e un esempio

Le regole nell'elenco sono combinate con AND: un controllo fallisce quando una singola regola fallisce e passa solo quando ogni regola passa. Non c'è ancora un OR, quindi per accettare uno tra diversi stati o stringhe, esprimilo dentro un'unica regola (status in [200, 301, 302], body containsAny ["In stock", "Pre-order"]). Una regola che fallisce si nomina da sola nell'avviso, quindi dai a ciascuna un'etichetta breve dove puoi e l'avviso dirà quale aspettativa si è rotta.

Cosa puoi controllare

Il selettore raggruppa i soggetti nel documento proprio della risposta (il corpo, le intestazioni) e nel suo trasporto (stato, timing, redirect, TLS). Alcuni dei soggetti più importanti, con l'elenco completo nella referenza che segue:

SoggettoCos'èEsempio
statusIl codice di stato HTTP della risposta finale, dopo aver seguito i redirectstatus isOk
bodyIl corpo della risposta come testo semplicebody contains "Add to cart"
body.json / body.xml / body.html / body.yamlIl corpo, ma solo quando viene effettivamente interpretato come quel formato, altrimenti il soggetto è semplicemente assentebody.json exists
body.json.path("$.a")Una query JSONPath dentro un corpo JSON (lo stesso linguaggio di query funziona anche su YAML, dato che YAML viene interpretato nello stesso modello a oggetti)body.json.path("$.status") eq "ok"
body.size / body.hashLa dimensione della risposta in byte, e un'impronta del contenuto del corpobody.size gt 1kb
header("Name")Un'intestazione della risposta, cercata per nomeheader("Content-Type") isJson
time e time.connect / time.tls / time.dns / time.headTempo di risposta totale, e le sue fasi di rete, handshake TLS, DNS e tempo di elaborazione del servertime lt 2s
redirects / requestsI salti che un controllo ha seguito, e la catena completa (inclusa la risposta finale)redirects.count eq 0
url e le sue parti (.host, .scheme, .path...)L'URL finale su cui è atterrato il controllourl.scheme eq "https"
cert.days.leftGiorni rimanenti prima che il certificato TLS scadacert.days.left gt 14

I numeri accettano suffissi di unità così non devi mai convertire a mano: 2s significa 2000 millisecondi, 1kb significa 1024 byte. I confronti di testo distinguono maiuscole e minuscole a meno che tu non aggiunga nocase alla regola.

La referenza completa

Quello che segue è ogni soggetto, operatore, riduttore, scorciatoia di zucchero sintattico, filtro e forma di sintassi che il motore di assert registra per i controlli HTTP e API, preso direttamente dal registro del motore stesso (gli stessi dati che alimentano i selettori dell'editor delle regole e la sua documentazione). Le voci non ancora generalmente disponibili portano una nota tra parentesi: campi riservati che nessun agente ha ancora iniziato a popolare, candidati ancora in fase di distribuzione agli agenti, e la famiglia con stato che richiede un piano specifico. Tutto ciò che non ha una tale nota è live oggi su ogni piano che ha la modalità assert.

La referenza segue il raggruppamento proprio del motore: campi della risposta, poi i modi per accedere a un corpo, poi timing, rete e TLS, poi gli operatori, i riduttori e le scorciatoie che funzionano su tutti loro, poi i tipi di controllo oltre HTTP che parlano lo stesso linguaggio.

Risposta

I soggetti che descrivono la risposta stessa: il suo stato, il suo corpo grezzo, le sue intestazioni, l'URL da cui ha effettivamente risposto, e la catena di richieste che ce l'ha portata.

NomeCos'èTipo/valoriEsempio
bodyIl corpo della risposta come testo decodificato.stringbody contains "Welcome"
headerUn'intestazione della risposta finale, per nome.stringheader("Content-Type") isJson
redirectsI salti di redirect che sono stati seguiti, la catena di richieste senza il suo elemento finale.collectionredirects.count eq 0
statusIl codice di stato HTTP della risposta finale, dopo aver seguito i redirect.numberstatus isOk
body.sizeLa dimensione del corpo scaricato, in byte.numberbody.size lt 500000
urlL'URL che ha effettivamente risposto, dopo tutti i redirect. Un url: confrontalo come testo, o leggi le sue parti (url.host, .port, .path, .query, .scheme).urlurl.host eq "www.example.com"
requestsOgni richiesta fatta da questo controllo, in ordine: i salti di redirect e poi la richiesta finale.collectionrequests.count le 2
url.hostLa parte host dell'URL.stringurl.host eq "example.com"
url.pathLa parte percorso dell'URL.stringurl.path startsWith "/api"
url.portLa parte porta dell'URL.numberurl.port eq 443
url.queryLa stringa di query dell'URL.stringurl.query contains "token"
url.schemeLo schema dell'URL (http o https).stringurl.scheme eq "https"
body.hashUn digest del corpo della risposta, confrontalo con previous.body.hash per rilevare cambi di contenuto.stringbody.hash eq previous.body.hash
httpVersion (riservato, non ancora popolato)La versione HTTP negoziata.stringhttpVersion eq "HTTP/2"
setCookieI valori Set-Cookie della risposta finale, un elemento per cookie, confrontane uno con contains o matches, contali con .count.collectionsetCookie exists
steps (non ancora disponibile)I passi di un controllo multi-step. Non ancora disponibile.collectionsteps.count le 1
url.originalL'URL con cui il controllo era configurato, prima di ogni redirect. Un url come url stesso: ha le stesse parti (url.original.host, .port, .path, .query, .scheme).urlurl.original.scheme eq "http"
url.original.hostLa parte host dell'URL.stringurl.original.host eq "example.com"
url.original.pathLa parte percorso dell'URL.stringurl.original.path startsWith "/start"
url.original.portLa parte porta dell'URL.numberurl.original.port eq 80
url.original.queryLa stringa di query dell'URL.stringurl.original.query contains "utm_"
url.original.schemeLo schema dell'URL (http o https).stringurl.original.scheme eq "http"

Due alias: redirectCount è la forma breve di redirects.count, redirectCount eq 0 si legge in modo leggermente più naturale della forma lunga equivalente quando intendi "il controllo ha risposto direttamente, senza redirect." E setCookie al livello superiore è l'elenco cookie della risposta finale; lo stesso nome ricompare per ogni salto dentro requests/redirects (vedi Soggetti dei salti sotto), contenendo solo i cookie di quella singola richiesta.

Estrarre valori dal corpo

Questi soggetti si risolvono solo quando il corpo è nel formato che nominano: uno spazio dei nomi JSON su una pagina HTML è semplicemente assente, non un errore tipizzato. Questo rende exists il modo standard per sondare il formato, e body.json exists chiede se il corpo è stato interpretato come JSON. I quattro spazi dei nomi di formato portano ciascuno una funzione di query .path(...) corrispondente (JSONPath per json/yaml, XPath per xml, selettori CSS per html) e un .regex(...) corrispondente, più un body.regex(...) indipendente dal formato che legge il testo grezzo indipendentemente dal formato. body.html.a, body.html.script e body.html.link sono collezioni già pronte di ogni link, script ed elemento <link> nella pagina; vedi Ambiti di elemento sotto per i campi disponibili su ciascuno.

NomeCos'èTipo/valoriEsempio
body.jsonIl corpo della risposta, ma solo quando è davvero JSON.stringbody.json exists
body.json.pathInterroga il corpo JSON con un'espressione JSONPath.jsonbody.json.path("$.status") eq "ok"
body.htmlIl corpo della risposta, ma solo quando è davvero HTML.stringbody.html exists
body.html.pathSeleziona elementi della pagina con un selettore CSS.collectionbody.html.path("h1").first contains "Welcome"
body.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists
body.xmlIl corpo della risposta, ma solo quando è davvero XML.stringbody.xml exists
body.xml.pathInterroga il corpo XML con un'espressione XPath.stringbody.xml.path("//item/@id") exists
body.html.aOgni link nella pagina.collectionbody.html.a.count gt 0
body.html.linkOgni <link> dichiarato dalla pagina. Una menzione nuda significa i target del link.collectionbody.html.link.count gt 0
body.html.scriptOgni script caricato dalla pagina. Una menzione nuda significa le sorgenti dello script.collectionbody.html.script.count gt 0
body.yamlIl corpo della risposta, ma solo quando è davvero YAML.stringbody.yaml exists
body.yaml.pathInterroga il corpo YAML con un'espressione JSONPath.jsonbody.yaml.path("$.services.web.image") contains ":1."
body.html.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists
body.json.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists
body.xml.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists
body.yaml.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists

Un dettaglio della famiglia regex che vale la pena segnalare: i gruppi di cattura con nome ((?<id>...)) dentro una regola .regex(...) scrivono in uno spazio dei nomi di binding limitato al controllo che una regola successiva può rileggere con bind("id") o bind[0] per posizione, vedi Valori catturati sotto.

Valori catturati

Un soggetto vive nel proprio gruppo del registro perché non legge direttamente la risposta, legge ciò che una regola precedente ha catturato da essa.

NomeCos'èTipo/valoriEsempio
bindUn valore catturato da una regola regex precedente, per nome di cattura o per posizione.stringbind("id") gt 1000

Abbinalo a una regola regex precedente nell'elenco: una regola come body.regex("order-(?<id>\d+)") exists cattura l'id dell'ordine nel nome id, e una regola successiva può testarlo con bind("id") gt 1000 oppure, per una cattura posizionale (senza nome), bind[0].

Timing

Un totale più una scomposizione per fase, così un avviso "è diventato più lento" può anche dire quale parte è diventata più lenta.

NomeCos'èTipo/valoriEsempio
timeTempo di risposta totale: connessione + TLS + attesa + download. La risoluzione DNS non è inclusa.numbertime lt 2000
ttfb (riservato, non ancora popolato)Tempo al primo byte.numberttfb lt 200
time.connectTempo impiegato per stabilire la connessione TCP.numbertime.connect lt 500
time.dataTempo impiegato per scaricare il corpo della risposta.numbertime.data lt 1000
time.dnsTempo impiegato per risolvere il nome di dominio. Non incluso nel soggetto time nudo.numbertime.dns lt 200
time.headTempo di attesa per le intestazioni della risposta.numbertime.head lt 500
time.tlsTempo impiegato per l'handshake TLS.numbertime.tls lt 300

Il soggetto time nudo è connessione + TLS + attesa delle intestazioni + download del corpo. La risoluzione DNS è esclusa e vive solo nel soggetto fratello time.dns, perché il DNS è spesso in cache e altrimenti farebbe apparire lo stesso endpoint incoerentemente veloce o lento tra un controllo e l'altro.

Rete: DNS e connessione

dns e conn sono puri spazi dei nomi nel registro, un gruppo senza un proprio valore, quindi una regola non può mai fermarsi sul nome nudo (sia l'editor sia il motore rifiutano una catena che finisce solo su dns o conn, indirizzandoti ai campi reali sotto).

NomeCos'èTipo/valoriEsempio
connLa connessione di rete fatta dal controllo, l'indirizzo che ha servito la risposta e gli eventuali fallimenti di connessione.string-
conn.failedQuanti degli indirizzi risolti non sono riusciti a connettersi.numberconn.failed eq 0
conn.failedIps (candidato, in fase di distribuzione agli agenti)Gli indirizzi risolti che non sono riusciti a connettersi.collectionconn.failedIps.count eq 0
conn.ipL'indirizzo IP che ha effettivamente servito la risposta.stringconn.ip eq "203.0.113.10"
conn.ip.family (candidato, in fase di distribuzione agli agenti)Se la risposta è stata servita su IPv4 o IPv6.stringconn.ip.family eq "IPv4"
dnsLa risoluzione DNS del nome monitorato, a quali indirizzi si è risolto e quale server ha risposto.string-
dns.ipsTutti gli indirizzi IP a cui si è risolto il nome di dominio durante questo controllo.collectiondns.ips contains "1.2.3.4"
dns.serverIl server DNS che ha risposto alla risoluzione.stringdns.server eq "8.8.8.8"

TLS e certificato

Come dns e conn, tls e cert sono puri spazi dei nomi, i fatti su certificato/handshake vivono un livello sotto.

NomeCos'èTipo/valoriEsempio
cert.days.leftGiorni rimanenti prima che il certificato del sito scada.numbercert.days.left gt 14
certIl certificato presentato dal server, giorni alla scadenza, emittente e campi di identità.string-
cert.daysGiorni trascorsi dall'emissione del certificato.numbercert.days gt 0
cert.issuerL'autorità di certificazione che ha emesso il certificato del sito.stringcert.issuer contains "Let's Encrypt"
cert.sanI nomi di dominio per cui il certificato è valido.collectioncert.san contains "www.example.com"
cert.serialIl numero di serie del certificato.stringcert.serial exists
cert.subject (riservato, non ancora popolato)Il soggetto del certificato. Non ancora catturato, in arrivo con una futura versione dell'agente.stringcert.subject contains "example.com"
tlsL'handshake TLS della connessione protetta, versione del protocollo e cifrario negoziati.string-
tls.cipherLa suite di cifratura negoziata.stringtls.cipher contains "AES"
tls.protocolLa versione TLS negoziata.stringtls.protocol eq "Tls13"

cert.subject è elencato qui per completezza ma non è ancora popolato, vedi la sezione Trasparenza sotto per cosa significa "riservato" in pratica. La regola quotidiana sul certificato è cert.days.left gt 14, trattata nella sezione delle regole pratiche.

Soggetti dei salti: campi dentro requests e redirects

requests e redirects sono collezioni, e ogni elemento è un record completo di richiesta/risposta con il proprio insieme ridotto di campi. Non ogni soggetto di primo livello ha senso per singolo salto (un salto non ha un proprio certificato), e un campo esiste solo per salto: hstsHeader, l'intestazione Strict-Transport-Security di quella richiesta nella catena.

NomeCos'èTipo/valoriEsempio
statusIl codice di stato di questa richiesta nella catena.numberstatus eq 200
urlL'URL a cui è stata fatta questa richiesta.urlurl startsWith "https://"
headerUn'intestazione della risposta di questa richiesta. Un salto mantiene un record di intestazione ridotto a un solo valore, i predicati per liste (containsAny, containsAll, unique) si applicano solo sull'intestazione della risposta finale.stringheader("Content-Type") contains "json"
hstsHeaderL'intestazione Strict-Transport-Security di questa richiesta.stringrequests[0].hstsHeader exists
setCookieI valori dell'intestazione Set-Cookie di questa richiesta.collectionsetCookie exists
url.originalL'URL con cui il controllo era configurato, prima di ogni redirect. Un url come url stesso: ha le stesse parti (url.original.host, .port, .path, .query, .scheme).urlurl.original.scheme eq "http"
url.hostLa parte host dell'URL.stringurl.host eq "example.com"
url.portLa parte porta dell'URL.numberurl.port eq 443
url.pathLa parte percorso dell'URL.stringurl.path startsWith "/api"
url.queryLa stringa di query dell'URL.stringurl.query contains "token"
url.schemeLo schema dell'URL (http o https).stringurl.scheme eq "https"
url.original.hostLa parte host dell'URL.stringurl.original.host eq "example.com"
url.original.portLa parte porta dell'URL.numberurl.original.port eq 80
url.original.pathLa parte percorso dell'URL.stringurl.original.path startsWith "/start"
url.original.queryLa stringa di query dell'URL.stringurl.original.query contains "utm_"
url.original.schemeLo schema dell'URL (http o https).stringurl.original.scheme eq "http"

Il header(...) per singolo salto mantiene un record ridotto a un solo valore: predicati a forma di lista come containsAny o unique hanno senso solo sulla mappa completa delle intestazioni della risposta finale, quindi si applicano lì e non per salto. Le due collezioni significano cose diverse. requests è l'intera catena inclusa la risposta finale che ha risposto, quindi non è mai vuota nemmeno per un 200 diretto, mentre redirects sono solo i salti seguiti lungo il percorso, vuota quando nulla ha effettuato redirect.

Ambiti di elemento: campi dentro un elemento della collezione

Un ambito di elemento è l'insieme di campi disponibile su UN elemento di una collezione, dopo aver indicizzato al suo interno (requests[0]) o mentre la filtri con where(current. ...) (vedi la sezione successiva). Sei collezioni portano un proprio ambito di elemento: le quattro collezioni di elementi HTML condividono una forma, e requests/redirects condividono la forma dei soggetti dei salti documentata subito sopra.

Ambito di elementoCome appare un elemento
body.html.pathUn elemento trovato da una query CSS body.html.path("selector").
body.html.aUn elemento link <a> da body.html.a.
body.html.scriptUn elemento <script> da body.html.script.
body.html.linkUn elemento <link> da body.html.link.
requestsUna richiesta nella catena completa (vedi la tabella dei soggetti dei salti sopra).
redirectsUn salto di redirect seguito (gli stessi campi di requests, vedi sopra).

La forma condivisa per body.html.path(...), body.html.a, body.html.script e body.html.link, una riga per link, tag script o elemento <link>:

NomeCos'èTipo/valoriEsempio
urlIl target del link esattamente come lo scrive il markup.stringbody.html.a.url contains "/checkout"
textIl testo visibile dell'elemento.stringbody.html.a.text contains "Sign in"
absoluteIl target del link risolto rispetto all'URL della pagina in un indirizzo assoluto, un elenco di url, con le parti dell'url disponibili per elemento (.host, .path, .port, .query, .scheme).urlbody.html.a.absolute.scheme in ["https"]
relL'attributo rel dell'elemento.stringbody.html.a.where(current.rel eq "nofollow").count eq 0
absolute.hostLa parte host dell'URL.stringbody.html.a.absolute.host.unique.count le 3
absolute.portLa parte porta dell'URL.numberbody.html.a.absolute.port in [443]
absolute.pathLa parte percorso dell'URL.stringbody.html.a.absolute.path startsWith "/"
absolute.queryLa stringa di query dell'URL.stringbody.html.a.absolute.query not contains "session"
absolute.schemeLo schema dell'URL (http o https).stringbody.html.a.absolute.scheme in ["https"]

Due valori predefiniti si applicano prima di scrivere una regola su queste collezioni. Una menzione nuda di body.html.a (o .script/.link) significa la sua proiezione .url, quindi body.html.a.count gt 0 conta gli href, e una regola salvata si rilegge con .url scritto per esteso, perché una regola memorizzata dice sempre esattamente cosa valuta. E .url è l'attributo href grezzo esattamente come lo ha scritto il markup, quindi un link relativo resta relativo; .absolute è lo stesso link risolto rispetto all'URL proprio della pagina, che è ciò che vuoi quando controlli lo schema o l'host dei link in uscita (body.html.a.absolute.scheme in ["https"]).

Operatori

La metà predicato di ogni regola: quale test eseguire sul soggetto. Tutti e 15 sono condivisi tra ogni tipo di controllo, e quali si adattano a un dato soggetto dipende dal suo tipo (un codice di stato accetta lt/gt, un corpo accetta contains, una collezione accetta exists/unique/in).

NomeCos'èSi applica aEsempio
eqUguale a. Contro un letterale json("…") / xml("…") / yaml("…") è una corrispondenza strutturale ESATTA: stesse chiavi (in qualsiasi ordine), array nello stesso ordine, stessi valori.qualsiasi tipobody.json eq json("{\"ok\": true}")
ltMinore di.numberstime lt 2000
leMinore o uguale a.numberscert.days.left le 30
gtMaggiore di.numbersbody.size gt 0
geMaggiore o uguale a.numbersstatus ge 500
containsContiene il testo, su una lista, passa quando il valore È uno degli elementi (corrispondenza esatta; usa matches per cercare dentro gli elementi). Contro un letterale json("…") / xml("…") / yaml("…") è contenimento STRUTTURALE: tutto ciò che il letterale dichiara deve essere presente e corrispondere; la risposta può averne di più.text or listbody.json contains json("{\"status\": \"ok\"}")
startsWithInizia con il testo, su una lista, quando un QUALSIASI elemento lo fa.texturl.path startsWith "/api"
endsWithFinisce con il testo, su una lista, quando un QUALSIASI elemento lo fa.texturl.path endsWith ".json"
matchesCorrisponde all'espressione regolare in qualsiasi punto del testo, su una lista, quando un QUALSIASI elemento lo fa.textbody matches "order-\\d+"
containsAnyContiene almeno uno dei valori elencati (su una lista: qualche elemento È UGUALE a uno di essi).listbody containsAny ["In stock", "Pre-order"]
containsAllContiene ognuno dei valori elencati (su una lista: ogni valore è uguale a qualche elemento, i testimoni possono differire).listbody.html.a.text containsAll ["Home", "Contact"]
inÈ uno dei valori o intervalli elencati, su una lista, ogni elemento lo è.value(s) or rangestatus in [200, 301, 302]
existsIl soggetto è presente.any subjectheader("ETag") exists
isNumberIl valore si legge come un numero.text or anybind("id") isNumber
uniqueLa lista non ha duplicati.listdns.ips unique

Due operatori significano qualcosa di più stretto di quanto sembri. contains su una lista è appartenenza esatta: il valore deve essere uguale a un intero elemento, non comparire come sottostringa dentro uno di essi, quindi usa matches quando vuoi un comportamento a sottostringa tra gli elementi di una collezione. E eq contro un letterale json(...)/xml(...)/yaml(...) è una corrispondenza strutturale completa (stesse chiavi, array nello stesso ordine, stessi valori), mentre contains contro lo stesso tipo di letterale è contenimento strutturale: tutto ciò che il letterale dichiara deve essere presente, ma la risposta reale può portarne di più.

Riduttori

Un riduttore riduce una collezione a un unico valore e può comparire solo alla fine di una catena. Gli esempi sotto usano requests.status, la collezione naturalmente numerica che i soggetti HTTP formano, come illustrazione; gli stessi otto riduttori funzionano su qualsiasi collezione numerica in qualsiasi tipo di controllo (i tempi di andata e ritorno di un controllo Ping, un insieme filtrato di righe di database).

NomeCosa riduceSi applica aEsempio
countQuanti elementi ha la lista.any collectionrequests.count le 2
minIl numero più piccolo nella lista.numeric collectionrequests.status.min ge 200
maxIl numero più grande nella lista.numeric collectionrequests.status.max lt 500
sumLa somma dei numeri nella lista.numeric collectionrequests.status.sum gt 0
avgLa media dei numeri nella lista.numeric collectionrequests.status.avg lt 300
firstIl primo elemento della lista.any collectionredirects.status.first eq 301
lastL'ultimo elemento della lista.any collectionrequests.status.last eq status
uniqueLa lista con i duplicati rimossi.any collectiondns.ips.unique.count le 3

unique è sovraccaricato, e la grafia distingue i due significati. Scritto come operatore senza punto (x unique) è un predicato, "questa collezione non ha duplicati," e fallisce nominando la ripetizione. Scritto come riduttore con un punto (x.unique) è una trasformazione, la collezione deduplicata stessa, che ha ancora bisogno di qualcosa dopo (x.unique.count eq 1). Un x.unique penzolante senza nulla dopo è un errore di sintassi, perché il motore non può indovinare quale dei due intendevi.

Zucchero sintattico

I predicati di zucchero sono forme brevi che il motore espande in predicati core ordinari prima ancora che la regola venga inviata a un agente, un predicato di zucchero non costa nulla in più da aggiungere (nessun bundle dell'agente, nessuna soglia di versione) perché nel momento in cui arriva sulla linea appare già come una regola ordinaria. Preferisci lo zucchero ogni volta che esiste: si legge meglio, ed è esattamente equivalente a scrivere la forma lunga a mano.

NomeCosa significaSi applica aEsempio
isOkLo stato è un codice di successo (200-299).status-
isRedirectLo stato è un codice di redirect (300-399).statusstatus isRedirect
isClientErrorLo stato è un errore client (400-499).statusstatus isClientError
isServerErrorLo stato è un errore server (500-599).statusstatus isServerError
isJsonIl contenuto è davvero JSON.document or media-type textheader("Content-Type") isJson
isXmlIl contenuto è davvero XML, il corpo viene interpretato come XML, oppure un'intestazione nomina un media type XML.document or media-type textbody isXml
isHtmlIl contenuto è davvero HTML, il corpo viene interpretato come HTML, oppure un'intestazione nomina un media type HTML.document or media-type textbody isHtml
isFormUn media type nomina una codifica di modulo: application/x-www-form-urlencoded o multipart/form-data. A differenza di isJson/isXml/isHtml non esiste uno spazio dei nomi del corpo corrispondente, quindi questo si applica solo a un valore di media type come un'intestazione Content-Type.media-type text onlyheader("Content-Type") isForm
isEmptyNon c'è nulla: un testo vuoto, una dimensione zero o una lista vuota.text, size or listbody isEmpty
isNullIl valore è null.any valuebody.json.path("$.deletedAt") isNull
absentIl soggetto non è presente affatto.any subjectheader("X-Debug") absent
betweenUn numero dentro un intervallo inclusivo.numbers (2-operand)body.size between 50 and 500kb

isJson/isXml/isHtml sono sensibili al contesto di proposito, e ciò su cui li scrivi decide quale significato si applica. Scritti sul documento stesso (body isJson) significano "questo viene interpretato come quel formato," lo stesso di body.json exists. Scritti su un valore testuale che nomina un media type, come un'intestazione (header("Content-Type") isJson), significano "questo nomina la famiglia MIME di quel formato"; vedi Famiglie MIME sotto per quali media type qualificano. isForm ha solo il secondo significato, dato che non esiste uno spazio dei nomi body.form in cui interpretare, quindi body isForm è un errore statico invece che una regola che non potrebbe mai essere vera.

Il filtro where(...)

Mantieni solo gli elementi che corrispondono, poi prosegui da lì. È l'unico costrutto di filtraggio nel linguaggio, e ha esattamente una forma: where(current.<field> <condition> <value>).

Filtrare è diverso dal proiettare: requests.url contains "cart" chiede se un tale salto esiste da qualche parte nella catena, mentre requests.where(current.url contains "cart").status chiede cosa ha restituito quel salto. Il filtraggio non riduce la lista, quindi concludi con .first, un controllo in [...], o .count. Va un solo livello, e prende esattamente una condizione.

ParteCosa nominaNote
current.<field>Un campo di ciascun elemento in fase di filtraggio, scritto dopo current.Questa è la metà su cui le persone sbagliano: current.url è l'URL del singolo salto, non quello della risposta finale. Solo i campi propri dell'elemento possono seguire current.
la condizioneQualsiasi predicato ordinario, incluso not e nocaseQualsiasi condizione che funziona al livello superiore di una regola funziona anche qui.
il valoreCon cosa viene confrontato il campo di ciascun elementoDi solito un valore semplice. Un soggetto scritto qui viene letto dalla risposta ESTERNA, non dall'elemento, where(current.url eq url.original) confronta ogni salto con l'URL con cui il controllo era configurato, motivo per cui il lato elemento deve dire current. esplicitamente.

Esempio: requests.where(current.url contains "cart").status.first eq 301, mantieni solo i salti il cui URL contiene "cart", poi guarda lo stato del primo che corrisponde.

Altri due limiti, entrambi imposti dal parser con un proprio messaggio: where non può essere annidato dentro un altro where, e il suo argomento è esattamente una condizione, senza and/or all'interno. Si applica solo a una collezione i cui elementi portano campi con nome (requests, body.html.a), non a una semplice lista proiettata come dns.ips, dove non c'è nulla che current. possa nominare.

Referenza di sintassi

Tutto il resto che la grammatica definisce: come nominare una regola, come scrivere intervalli e liste, cosa significa un soggetto nudo, e le piccole forme di punteggiatura che compaiono in molte regole.

FormaCosa faTipoEsempio
whereMantieni solo gli elementi che corrispondono, poi prosegui da lì.collection filterrequests.where(current.url contains "cart").status.first eq 301
notInverte la condizione che segue.flagbody not contains "error"
nocaseConfronta il testo senza distinguere maiuscole e minuscole.flagbody contains "welcome" nocase
currentDentro where(…), nomina l'unico elemento in fase di filtraggio.element reference (inside where)requests.where(current.status eq 301)
rangeUn intervallo di numeri, entrambi gli estremi INCLUSI.number rangestatus in [200..299]
listUna lista di valori con cui confrontare.value liststatus in [200, 301, 302]
docLiteralUn valore documento tipizzato per confronto strutturale: il testo tra virgolette viene interpretato come JSON, XML o YAML quando la regola viene salvata.json/xml/yaml textbody.json contains json("{\"user\": {\"active\": true}}")
implicitExistsUna regola che nomina solo un soggetto controlla che sia presente: scrivere solo body.json si salva come body.json exists.bare subject linebody.json
indexSceglie UN elemento di una lista per posizione, contando da 0.0-based integerrequests[0].status
labelUn nome facoltativo per la regola, scritto prima di due punti.name before a colon"json ok": body.json exists
commentTutto ciò che segue # è una nota per te stesso; non influisce sul controllo.trailing # textstatus isOk # the happy path

Alcuni meritano un passaggio in prosa semplice. label dà a una regola un nome che compare nell'avviso invece dell'espressione resa; scrivilo prima di due punti, come in "json ok": body.json exists. implicitExists significa che una riga che nomina solo un soggetto e nessun predicato è la forma breve di exists: scrivere body.json si salva come body.json exists, e riaprire la regola mostra la forma scritta per esteso. range e list sono le due forme che un valore può assumere dopo in: un intervallo ([200..299], entrambi gli estremi inclusi) o una lista esplicita ([200, 301, 302]), e un valore può essere aperto su entrambi i lati ([400..]). docLiteral è il wrapper json(...)/xml(...)/yaml(...) usato per il confronto strutturale contro il corpo (trattato sotto Operatori sopra e nelle regole pratiche sotto). index sceglie un elemento da una collezione per posizione, a partire da 0, allo stesso modo in cui bind[0] legge una cattura posizionale. current ha significato solo dentro un filtro where(...), trattato nella propria sezione sopra.

Wrapper: previous, delta e delta2

Tre forme che guardano indietro invece di guardare solo la risposta attuale, ciascuna limitata ai piani con asserzioni con stato, e ciascuna spiegata per intero in "Confrontare con il controllo precedente" sotto.

NomeCos'èTipo/valoriEsempio
delta (richiede un piano con asserzioni con stato)Di quanto è cambiato un valore numerico dal controllo precedente, facoltativamente come tasso per ms/s/m/h.numberdelta(body.size, h) lt 1mb
delta2 (richiede un piano con asserzioni con stato)Il cambiamento del cambiamento: un valore sta accelerando?numberdelta2(time) gt 0
previous (richiede un piano con asserzioni con stato)Il valore che questo soggetto aveva al controllo precedente.anystatus eq previous.status

Flag: not e nocase

Due modificatori che si attaccano a una regola invece di essere soggetti o predicati a sé.

FlagCosa faTipoEsempio
notInverte la condizione che segue.flag (attaches to a rule)body not contains "error"
nocaseConfronta il testo senza distinguere maiuscole e minuscole.flag (attaches to a rule)body contains "welcome" nocase

not si compone con il predicato che segue invece di negare l'intera regola come unità, x not != y si legge come x eq y, non come una doppia negazione. Quando un soggetto potrebbe essere del tutto assente, preferisci lo zucchero absent a not exists: i due significano esattamente la stessa cosa, ma absent lo dice direttamente. nocase cambia qualcosa solo su un confronto genuinamente testuale; l'editor (e questa referenza) ti lasciano comunque scriverlo ovunque, ma è silenziosamente privo di significato su un test numerico come status eq 200 nocase.

Famiglie MIME

Le tabelle di lookup dietro isJson, isXml, isHtml e isForm quando vengono applicati a un valore di media type come un'intestazione. Ogni famiglia corrisponde al media type di primo livello ovvio più, per JSON e XML, qualsiasi tipo che termina nel suffisso di sintassi strutturata corrispondente, il che è ciò che fa passare correttamente header("Content-Type") isJson su application/problem+json o application/vnd.api+json e non solo sul semplice application/json.

FamigliaCorrisponde aZucchero abbinatoEsempio
jsonapplication/json, text/json, o qualsiasi media type che termina in +json (application/problem+json, application/vnd.api+json, application/ld+json, ...).sugar: isJsonheader("Content-Type") isJson
xmlapplication/xml, text/xml, o qualsiasi media type che termina in +xml (image/svg+xml, application/atom+xml, ...).sugar: isXmlheader("Content-Type") isXml
htmltext/html o application/xhtml+xml.sugar: isHtmlheader("Content-Type") isHtml
formapplication/x-www-form-urlencoded o multipart/form-data.sugar: isFormheader("Content-Type") isForm

La corrispondenza ignora tutto a partire dal primo ; in poi (così application/json; charset=utf-8 corrisponde comunque) e non distingue maiuscole e minuscole.

Soggetti per controlli database, counter, SNMP, porta e ping

Ogni operatore, riduttore, scorciatoia di zucchero sintattico e forma di sintassi sopra è identico per questi cinque tipi di controllo: il motore registra gli stessi 15 operatori, 8 riduttori, 12 predicati di zucchero e 11 forme di sintassi per tutti e sei i tipi senza eccezioni. Ciò che cambia per tipo è l'elenco dei soggetti. Ogni tipo espone un piccolo insieme di soggetti propri di ciò che misura, più un sottoinsieme dei soggetti di rete/timing/TLS già documentati sopra, con il significato che si adatta al tipo (il time di un controllo Database è connessione-più-query invece di connessione-più-TLS-più-download, dato che non c'è una risposta HTTP da scaricare).

Controlli database

Condivide time, time.connect e time.dns con i soggetti documentati sopra (ridefiniti su una connessione database: connessione-più-query, risoluzione DNS dell'host del database). Propri dei controlli database:

NomeCos'èTipo/valoriEsempio
scalarIl singolo valore restituito dalla query (modalità Scalar).any-
rowsLe righe che la query ha interessato o restituito (modalità NonQuery).collection-
time.queryIl tempo impiegato dalla query stessa.number-

Un esempio pratico è nella sezione successiva: usa rows.count per verificare quante righe una query ha interessato o restituito, e scalar per controllare direttamente un singolo valore restituito.

Controlli counter

Condivide time con i soggetti documentati sopra, come campo in stato candidato specificamente per i controlli Counter (tempo di andata e ritorno della richiesta del counter; vedi la sezione Trasparenza per cosa significa "candidato"). Propri dei controlli counter:

NomeCos'èTipo/valoriEsempio
valueIl valore misurato del counter.number-

Controlli SNMP

Condivide time e time.dns con i soggetti documentati sopra (risoluzione del nome host più la richiesta SNMP stessa). Propri dei controlli SNMP:

NomeCos'èTipo/valoriEsempio
time.requestIl tempo impiegato dalla richiesta SNMP.number-
valueIl valore restituito dall'OID.any-
value.type (candidato, in fase di distribuzione agli agenti)Il nome del tipo di dato SNMP del valore restituito.string-

value.type è in stato candidato; vedi la sezione Trasparenza. Nota sulla disponibilità: l'interruttore di Response Validation della modalità assert non è ancora arrivato all'editor del monitor SNMP. Mostra un pannello "Coming soon" che nomina questi due soggetti invece di un elenco di regole funzionante. I soggetti e il motore di valutazione sottostante sono già registrati; è in sospeso solo l'interfaccia dell'editor SNMP.

Controlli porta

L'elenco condiviso più ampio di qualsiasi tipo non-HTTP. Un controllo di porta TCP porta essenzialmente gli stessi soggetti di connessione, DNS, TLS e certificato di un controllo HTTP, dato che un controllo di porta può negoziare TLS a sua volta: bind, cert e i suoi sei sottocampi, conn e i suoi quattro sottocampi, dns e i suoi due sottocampi, time/time.connect/time.dns/time.tls, e tls/tls.cipher/tls.protocol, tutti documentati nelle sezioni sopra, con gli stessi significati. Propri dei controlli porta:

NomeCos'èTipo/valoriEsempio
bannerI dati letti dal socket dopo la connessione.string-
banner.hash (candidato, in fase di distribuzione agli agenti)Un digest del banner, confrontalo con previous.banner.hash per rilevare cambi del servizio.string-
banner.regexFai corrispondere il testo con un'espressione regolare e prendi ciò che ha catturato.stringbody.regex("order-(?<id>\\d+)") exists
banner.size (candidato, in fase di distribuzione agli agenti)La dimensione del banner, in byte.number-

banner.hash e banner.size sono in stato candidato, vedi la sezione Trasparenza. banner.regex è live oggi e funziona esattamente come body.regex(...) su un controllo HTTP: le catture con nome alimentano lo stesso spazio dei nomi bind(...).

Controlli ping

Condivide i soggetti di connessione e DNS con le sezioni sopra: conn, conn.failed, conn.failedIps, conn.ip, conn.ip.family, dns, dns.ips, dns.server, time (qui, il tempo medio di andata e ritorno delle risposte riuscite) e time.dns. Propri dei controlli ping:

NomeCos'èTipo/valoriEsempio
lossLa percentuale di richieste echo che non hanno ricevuto risposta.numberloss eq 0
replyLe risposte echo riuscite.collection-
sentCount (candidato, in fase di distribuzione agli agenti)Quante richieste echo sono state inviate.number-
time.maxIl tempo di andata e ritorno della risposta più lenta.number-
time.minIl tempo di andata e ritorno della risposta più veloce.number-
ttlIl TTL della prima risposta riuscita, confrontalo con previous.ttl per individuare cambi di rotta.number-

sentCount è in stato candidato, vedi la sezione Trasparenza. ttl vale la pena conoscerlo anche fuori da una rigida regola di successo/fallimento: abbinarlo a previous.ttl (vedi Wrapper sopra) segnala un cambio di rotta tra un controllo e l'altro, dato che il time-to-live di un pacchetto all'arrivo riflette quanti salti ha attraversato.

Le regole che le persone vogliono davvero scrivere

La pagina è raggiungibile e dice davvero la cosa giusta

Un codice di stato da solo non può dirti che una pagina si è renderizzata correttamente, una risposta 200-con-guscio-vuoto è il classico fallimento silenzioso che un controllo basato solo sullo stato non vede.

status isOk
body contains "Add to cart"

Un'API risponde con JSON e il campo che ti aspetti

Controlla che l'endpoint stia ancora parlando JSON, poi accedi al suo interno. La prima riga intercetta una pagina di errore HTML servita dove dovrebbe esserci JSON, una forma comune di interruzione dietro un proxy; la seconda controlla lo stato di salute dichiarato dall'API stessa, non solo il suo stato di trasporto.

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

La risposta è diventata più lenta di quanto dovrebbe

Scomponila quando hai bisogno di sapere cosa correggere invece di sapere solo che qualcosa è lento, time.connect, time.tls, time.dns e time.head separano tempo di rete, handshake, resolver e tempo dell'applicazione.

time lt 2s

Un redirect ha mandato i visitatori fuori dal tuo stesso dominio

Confronta dove è finito il controllo con l'URL che hai configurato, fallisce nel momento in cui una catena di redirect, dirottata, mal configurata, o semplicemente cambiata da un deploy, atterra da qualche parte che non intendevi.

url.host eq url.original.host

La pagina è cambiata dall'ultimo controllo

Utile su contenuti che dovrebbero restare stabili tra un controllo e l'altro, come prezzi, termini, una policy pubblicata, e funge anche da segnale base di defacement.

previous.body.hash eq body.hash

Un numero dentro un intervallo, scritto in modo breve

Intercetta sia una pagina ridotta all'osso sia una fuori controllo in un'unica regola, senza scrivere per esteso un intervallo esplicito.

body.size between 50 and 500kb

Un certificato in scadenza

Il singolo controllo TLS più comune, e uno che un monitor semplice su/giù non può esprimere affatto, un certificato ancora valido oggi ma che scade la prossima settimana non dà nessun altro segno di avvertimento. Abbinalo a cert.issuer se vuoi intercettare anche un certificato emesso silenziosamente dall'autorità sbagliata.

cert.days.left gt 14

Una query di database che restituisce il numero sbagliato di righe

Su un controllo Database, rows è la collezione che una query ha interessato o restituito, contarla intercetta una query che dovrebbe restituire esattamente un record account e inizia silenziosamente a restituirne zero (eliminato, o un join rotto) oppure più di uno (un duplicato che non dovrebbe esistere).

rows.count eq 1

Un valore SNMP che esce dall'intervallo

Un dispositivo SNMP che risponde comunque non è lo stesso di uno sano, un OID monitorato (uso disco, profondità di coda, temperatura) può salire ben oltre una soglia sicura mentre il dispositivo stesso resta perfettamente raggiungibile. Confrontare il value interrogato con un intervallo intercetta ciò che un semplice controllo di raggiungibilità non può.

value lt 90

Un servizio TCP che risponde con il banner sbagliato

Una porta che accetta connessioni non è lo stesso di avere il servizio giusto in ascolto su di essa, un processo bloccato, un proxy mal configurato, o un servizio declassato/sostituito possono comunque completare un handshake TCP. Leggere il testo di saluto che un servizio invia subito dopo la connessione (un banner SMTP, FTP o simile) intercetta ciò che un semplice controllo porta-aperta non può.

banner contains "220"

Confrontare con il controllo precedente

Una manciata di soggetti guarda indietro invece di guardare solo la risposta attuale: metti previous. davanti a un soggetto per leggere qual era all'ultimo controllo, oppure avvolgilo in delta(...) per ottenere la differenza tra allora e ora, o in delta2(...) per ottenere il cambiamento di quel cambiamento, utile per individuare un valore che sta accelerando invece di semplicemente derivare (un tempo di risposta che sale sempre più rapidamente a ogni controllo). previous.body.hash eq body.hash sopra è esattamente questo, "l'impronta del corpo corrisponde a quella dell'ultima volta." delta(body.size, h) legge il cambiamento come un tasso all'ora invece che come una differenza grezza, per valori che ti aspetti crescano costantemente invece di saltare.

La prima volta che una regola come questa gira non ha nulla con cui confrontare, quindi viene saltata invece di fallire: il controllo viene segnato come "in fase di riscaldamento," non rotto, e aggiungere la regola non solleva alcun falso allarme. Il riscaldamento si applica solo quando la lettura attuale è valida e manca solo il riferimento. Se la lettura attuale stessa fallisce (per esempio, il corpo non è JSON valido questa volta), la regola fallisce esattamente come farebbe la sua versione semplice, senza previous.. Una regola simile ha anche bisogno che il valore cambi tra un controllo e l'altro, il che la rende priva di senso su un metodo di controllo che non fa mai avanzare lo stato, una richiesta HEAD per esempio.

Confrontare con il controllo precedente richiede un piano di livello superiore; senza di esso, quei soggetti appaiono disattivati nell'editor con una spiegazione.

Limiti, e cosa manca deliberatamente

Quante regole puoi aggiungere dipende dal tuo piano, mostrato come un contatore in tempo reale accanto a "Add rule." Il motore applica anche un tetto assoluto su ogni controllo indipendentemente dal piano, una protezione contro l'abuso più che un limite all'uso ordinario: un controllo con un numero di regole anche solo vicino a quel tetto sarebbe già insolitamente grande.

Non c'è modo di scrivere JavaScript personalizzato per una regola, e non ci sarà mai. Ogni regola è costruita da un vocabolario fisso e nominato di soggetti e predicati invece che da una sandbox di scripting aperta, il che mantiene una regola leggibile a colpo d'occhio e sicura da eseguire su ogni agente di monitoraggio nel mondo.

Non ogni regola funziona ovunque nel momento in cui viene scritta: alcune condizioni più recenti richiedono una versione recente dell'agente di monitoraggio che esegue il tuo controllo, quindi una nuova capacità impiega del tempo a raggiungere ogni controllo del tuo account man mano che gli agenti si aggiornano in background. Le regole costruite sul nucleo stabile del linguaggio non ne sono influenzate.

Una manciata di voci in questa referenza non è ancora pienamente live, e ciascuna è etichettata nella sua tabella sopra:

  • Riservato (dichiarato, non ancora popolato da alcun agente): ttfb, httpVersion, cert.subject.
  • Candidato (già in fase di distribuzione, non ancora su ogni agente): conn.ip.family e conn.failedIps sui controlli HTTP, Port e Ping, value.type sui controlli SNMP, banner.hash e banner.size sui controlli Port, sentCount sui controlli Ping, e il time proprio del controllo Counter.
  • Non ancora disponibile: steps, riservato per un futuro tipo di controllo multi-step.
  • Richiede un piano con asserzioni con stato: l'intera famiglia di wrapper previous / delta / delta2, su ogni tipo di controllo.

Tutto il resto in questa referenza è live oggi su ogni piano che ha la modalità assert.

Dove funziona oggi la modalità assert

L'interruttore di Response Validation per la modalità assert compare sui monitor HTTP (sito web) e API, che condividono lo stesso editor di regole e la stessa sintassi. Lo stesso linguaggio e lo stesso motore di valutazione già girano sotto i controlli Database, Counter, Port, Ping e SNMP a livello di protocollo: il registro sopra serve tutti e sei i tipi di controllo, e una regola salvata per uno si legge allo stesso modo se la modalità raggiunge l'editor di un altro tipo più avanti.

SNMP mostra l'anteprima più chiara: il suo editor ha già un pannello Regole di asserzione che nomina value e value.type, etichettato "Coming soon", senza ancora un elenco di regole funzionante dietro. I controlli Database, Counter e Ping non mostrano affatto un pannello della modalità assert, anche se i loro soggetti sono ugualmente live nel motore sottostante.

Configurare un controllo reale

Se stai convalidando un'API REST invece di una semplice pagina web, parti da convalida della risposta API, che copre insieme l'uptime, il tempo di risposta e il corpo della tua API. Per una pagina o un sito che deve restare raggiungibile e rispondere correttamente da ovunque si trovino i tuoi utenti, il monitoraggio globale dell'uptime da oltre 300 ubicazioni è il quadro più ampio in cui si inserisce la modalità assert. Per impostare le regole tramite codice invece che tramite il pannello, la API v2 propria di HostTracker crea e aggiorna le regole di assert di un monitor allo stesso modo dell'editor. Per la regola sulla scadenza del certificato sopra e tutto il resto su TLS, il monitoraggio di dominio e certificato TLS copre il tipo di controllo su cui vivono cert.days.left e gli altri soggetti TLS. Per osservare una regola valutata contro un URL reale proprio ora, senza account, usa lo strumento gratuito di controllo HTTP. Per i codici di stato con cui il soggetto status confronta, inizia con 200 OK, e le guide al monitoraggio coprono la configurazione di ogni tipo di controllo su cui gira questo linguaggio.

Domande frequenti

Cosa succede alle mie vecchie impostazioni di codice di stato e parola chiave se attivo la modalità assert?

Vengono sostituite dall'elenco di regole mentre la modalità è attiva. Disattivarla di nuovo prima di salvare ripristina i campi classici esattamente come erano: nulla viene eliminato, le due modalità semplicemente non possono essere entrambe attive.

Posso combinare più condizioni in un unico monitor?

Sì: ogni regola nell'elenco deve passare. Non c'è ancora un "OR" tra regole separate, quindi per accettare uno tra diversi valori usa un'unica regola con in [...] o containsAny [...].

La modalità assert mi permetterà mai di scrivere un mio script?

No. Ogni regola è composta dall'insieme fisso di soggetti e predicati del linguaggio. Non c'è JavaScript personalizzato, di proposito.

Cosa succede la prima volta che aggiungo una regola che confronta con il controllo precedente?

Non ha ancora nulla con cui confrontare, quindi viene segnata come in fase di riscaldamento e saltata invece che fallita. Aggiungere una regola "questo è cambiato" non solleva mai da sola un falso allarme.

Mi serve un piano specifico per usare la modalità assert?

La modalità stessa e le regole quotidiane (stato, corpo, intestazioni, timing, redirect) sono ampiamente disponibili; quante regole puoi aggiungere in una volta dipende dal tuo piano ed è mostrato in tempo reale nell'editor. Le regole che confrontano con un controllo precedente (previous, delta, delta2) richiedono un piano di livello superiore e appaiono disattivate con una spiegazione.

La modalità assert funziona sui monitor API allo stesso modo dei monitor sito web?

Sì. I monitor HTTP e API condividono lo stesso editor di regole, gli stessi soggetti e predicati, e una regola scritta per uno si legge in modo identico sull'altro.

Cosa fa esattamente where(...), e quando mi serve?

Filtra una collezione fino agli elementi che corrispondono a una condizione prima che tu legga un campo del risultato. Usalo quando una semplice proiezione come requests.status non è abbastanza specifica e hai bisogno di un particolare salto, link o elemento invece dell'intera collezione (vedi la sezione sopra).

Posso scrivere oggi una regola contro una query di database, un valore SNMP, un banner di porta o un risultato ping?

Il linguaggio e il motore di valutazione li supportano tutti, e le tabelle dei soggetti sopra coprono ciascuno di essi. L'editor delle regole no: solo i monitor HTTP e API mostrano oggi l'interruttore Response Validation. SNMP mostra un'anteprima "Coming soon" dei suoi due soggetti, e Database, Counter e Ping non mostrano affatto un pannello della modalità assert.

Perché alcuni soggetti in questa referenza dicono "riservato" o "candidato" invece di essere semplicemente elencati normalmente?

"Riservato" significa che il campo è dichiarato nel registro ma nessun agente lo popola ancora; "candidato" significa che è in fase di distribuzione agli agenti ma non li ha ancora raggiunti tutti. Entrambi sono segnalati ovunque compaiano in questa referenza e nell'elenco riassuntivo nella sezione Limiti sopra.

Controlla ora

Esegui il controllo gratuito sul tuo sito, senza bisogno di un account.

Web api validation

Monitora in modo permanente

Ricevi un avviso appena qualcosa si rompe: HostTracker controlla da oltre 300 località e ti avvisa via e-mail, SMS, Slack, Telegram e altro.

Funzionalità di HostTracker

Altro in questa sezione: Guide al monitoraggio: ogni tipo di controllo, passo per passo