Mode assertion : la référence complète de validation de réponse
Le mode assertion remplace les champs fixes de réussite/échec d'un moniteur par une liste de règles que vous écrivez vous-même, chaque règle nommant exactement ce qui doit être vrai à propos de la réponse. La plupart des moniteurs d'uptime jugent une vérification avec une poignée de champs fixes : un code de statut qui compte comme « en panne », une liste de statuts à ignorer, peut-être un mot-clé qui doit apparaître quelque part dans le corps. Ces champs ne peuvent pas exprimer une API qui répond légitimement 404 pour une ressource manquante, une page qui renvoie 200 avec une coquille vide parce que la base de données a expiré, ou une chaîne de redirection qui se met à passer par le domaine de quelqu'un d'autre.
Le mode assertion de HostTracker remplace ces champs fixes par un petit langage de règles que vous écrivez vous-même, règle par règle, dans l'éditeur de moniteur. Chaque règle dit exactement ce qui doit être vrai à propos de la réponse : le statut, un morceau du corps, un en-tête, le temps qu'elle a pris, où a atterri une redirection. Une vérification échoue seulement quand l'une de vos règles échoue. C'est le même langage pour un site web, une API REST, une requête de base de données, un port TCP, une cible Ping, un compteur SNMP ou une vérification Counter générique : un seul ensemble de sujets, un seul ensemble de prédicats, réutilisés partout où le mode apparaît. Ce guide couvre chaque sujet, opérateur, réducteur, raccourci sucré et forme de syntaxe que le moteur implémente.
Ce que le mode assertion remplace
Les champs classiques de Validation de la réponse sont toujours là quand le mode assertion est désactivé : une plage de statut attendue, une liste de statuts à ignorer, un mot-clé qui doit (ou ne doit pas) apparaître. Le mode est un interrupteur qui échange cet ensemble fixe contre une liste de règles que vous construisez vous-même, et le désactiver de nouveau avant d'enregistrer remet directement les champs classiques en place. Aucun moniteur n'est enfermé de façon permanente dans un seul mode.
Un seul langage se compose au lieu d'un tas de gadgets propres à chaque type. Une vérification « doit être du JSON et contenir un champ », une vérification « doit toujours dire Ajouter au panier » et une vérification « ne doit pas avoir ralenti » sont trois règles dans la même syntaxe, dans la même liste, chacune réussissant ou échouant de son côté.
L'activer
Le mode assertion vit dans la section Validation de la réponse de l'éditeur de moniteur, pour les moniteurs HTTP (site web) et API. Basculez l'interrupteur, et les champs classiques sont remplacés par une liste de règles numérotées avec un bouton « Ajouter une règle » et un compteur en direct montrant combien de règles vous avez utilisées par rapport à la limite de votre forfait.

Chaque règle est validée au fur et à mesure que vous la construisez : une règle pas encore terminée porte un
état « inachevé » distinct, et une règle que l'éditeur peut évaluer est marquée complète. Chaque règle a aussi un
petit bouton </> qui ouvre sa forme source en texte brut, pour que vous puissiez lire ou
copier l'expression exacte plutôt que seulement la vue case par case.
Le modèle mental : sujet, prédicat, valeur
Chaque règle a la même forme : un sujet (le code de statut, le corps, un en-tête, le temps de
réponse), un prédicat (égal à, contient, existe, est inférieur à) et, pour la plupart des prédicats, une
valeur à laquelle comparer. status eq 200 est un sujet, un prédicat et une valeur ;
body.json exists est un sujet et un prédicat sans valeur, car « exists » n'a besoin de rien
d'autre.
Construire une règle dans l'éditeur commence par choisir quoi vérifier, puis la condition, puis la valeur :

Les règles de la liste sont combinées avec AND : une vérification échoue quand une seule règle échoue et ne
réussit que quand chaque règle réussit. Il n'y a pas encore de OR, donc pour accepter l'un de plusieurs statuts
ou chaînes, exprimez cela à l'intérieur d'une seule règle (status in [200, 301, 302],
body containsAny ["In stock", "Pre-order"]). Une règle qui échoue se nomme elle-même dans l'alerte,
donnez donc à chacune un court libellé quand vous le pouvez et l'alerte dira quelle attente a été rompue.
Ce que vous pouvez vérifier
Le sélecteur regroupe les sujets entre le document propre de la réponse (le corps, les en-têtes) et son transport (statut, timing, redirections, TLS). Quelques-uns des sujets les plus importants, avec la liste complète dans la référence qui suit :
| Sujet | Ce que c'est | Exemple |
|---|---|---|
status | Le code de statut HTTP de la réponse finale, après suivi des redirections | status isOk |
body | Le corps de la réponse en texte brut | body contains "Add to cart" |
body.json / body.xml / body.html / body.yaml | Le corps, mais seulement quand il s'analyse vraiment comme ce format - sinon le sujet est simplement absent | body.json exists |
body.json.path("$.a") | Une requête JSONPath dans un corps JSON (le même langage de requête fonctionne aussi sur YAML, puisque YAML s'analyse dans le même modèle d'objet) | body.json.path("$.status") eq "ok" |
body.size / body.hash | La taille de la réponse en octets, et une empreinte du contenu du corps | body.size gt 1kb |
header("Name") | Un en-tête de réponse, recherché par nom | header("Content-Type") isJson |
time et time.connect / time.tls / time.dns / time.head | Le temps de réponse total, et ses phases réseau, poignée de main TLS, DNS et temps de réflexion du serveur | time lt 2s |
redirects / requests | Les sauts qu'une vérification a suivis, et la chaîne complète (y compris la réponse finale) | redirects.count eq 0 |
url et ses parties (.host, .scheme, .path...) | L'URL finale sur laquelle la vérification a atterri | url.scheme eq "https" |
cert.days.left | Jours restants avant l'expiration du certificat TLS | cert.days.left gt 14 |
Les nombres acceptent des suffixes d'unité pour que vous n'ayez jamais à convertir à la main :
2s signifie 2000 millisecondes, 1kb signifie 1024 octets. Les comparaisons de texte
sont sensibles à la casse sauf si vous ajoutez nocase à la règle.
La référence complète
Ce qui suit est chaque sujet, opérateur, réducteur, raccourci sucré, filtre et forme de syntaxe que le moteur d'assertion enregistre pour les vérifications HTTP et API, tiré du propre registre du moteur (les mêmes données qui alimentent les sélecteurs de l'éditeur de règles et sa documentation). Les entrées pas encore généralement disponibles portent une note entre parenthèses : des champs réservés que le moteur n'a pas encore commencé à peupler, des candidats encore en cours de déploiement vers les agents, et la famille à état qui nécessite un forfait précis. Tout ce qui n'a pas une telle note est vivant aujourd'hui sur tout forfait ayant le mode assertion.
La référence suit le propre regroupement du moteur : les champs de la réponse, puis les façons d'atteindre l'intérieur d'un corps, puis le timing, le réseau et le TLS, puis les opérateurs, réducteurs et raccourcis qui fonctionnent sur tous, puis les types de vérification au-delà de HTTP qui parlent le même langage.
Réponse
Les sujets qui décrivent la réponse elle-même : son statut, son corps brut, ses en-têtes, l'URL depuis laquelle elle a réellement répondu, et la chaîne de requêtes qui y a mené.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
body | Le corps de la réponse en texte décodé. | string | body contains "Welcome" |
header | Un en-tête de la réponse finale, par nom. | string | header("Content-Type") isJson |
redirects | Les sauts de redirection qui ont été suivis - la chaîne de requêtes sans son dernier élément. | collection | redirects.count eq 0 |
status | Le code de statut HTTP de la réponse finale, après suivi des redirections. | number | status isOk |
body.size | La taille du corps téléchargé, en octets. | number | body.size lt 500000 |
url | L'URL qui a réellement répondu, après toutes les redirections. Une url : comparez-la comme du texte, ou lisez ses parties (url.host, .port, .path, .query, .scheme). | url | url.host eq "www.example.com" |
requests | Chaque requête faite par cette vérification, dans l'ordre - les sauts de redirection puis la requête finale. | collection | requests.count le 2 |
url.host | La partie hôte de l'URL. | string | url.host eq "example.com" |
url.path | La partie chemin de l'URL. | string | url.path startsWith "/api" |
url.port | La partie port de l'URL. | number | url.port eq 443 |
url.query | La chaîne de requête de l'URL. | string | url.query contains "token" |
url.scheme | Le schéma de l'URL (http ou https). | string | url.scheme eq "https" |
body.hash | Un condensé du corps de la réponse - comparez-le avec previous.body.hash pour détecter des changements de contenu. | string | body.hash eq previous.body.hash |
httpVersion (réservé - pas encore peuplé) | La version HTTP négociée. | string | httpVersion eq "HTTP/2" |
setCookie | Les valeurs Set-Cookie de la réponse finale, un élément par cookie - repérez-en un avec contains ou matches, comptez-les avec .count. | collection | setCookie exists |
steps (pas encore disponible) | Les étapes d'une vérification multi-étapes. Pas encore disponible. | collection | steps.count le 1 |
url.original | L'URL avec laquelle la vérification a été configurée, avant toute redirection. Une url comme url elle-même : elle a les mêmes parties (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.original.host | La partie hôte de l'URL. | string | url.original.host eq "example.com" |
url.original.path | La partie chemin de l'URL. | string | url.original.path startsWith "/start" |
url.original.port | La partie port de l'URL. | number | url.original.port eq 80 |
url.original.query | La chaîne de requête de l'URL. | string | url.original.query contains "utm_" |
url.original.scheme | Le schéma de l'URL (http ou https). | string | url.original.scheme eq "http" |
Deux alias : redirectCount est un raccourci pour redirects.count -
redirectCount eq 0 se lit un peu plus naturellement que la forme longue équivalente quand vous
voulez dire « la vérification a répondu directement, sans redirection ». Et setCookie au niveau
supérieur est la liste de cookies de la réponse finale ; le même nom réapparaît par saut à l'intérieur de
requests/redirects (voir les sujets de saut ci-dessous), ne portant que les cookies de
cette seule requête.
Extraire des valeurs du corps
Ces sujets ne se résolvent que quand le corps est le format qu'ils nomment : un espace de noms JSON sur une
page HTML est simplement absent, pas une erreur typée. Cela fait de exists le moyen standard de
sonder le format, et body.json exists demande si le corps s'est analysé comme du JSON. Les quatre
espaces de noms de format portent chacun une fonction de requête .path(...) correspondante
(JSONPath pour json/yaml, XPath pour xml, des sélecteurs CSS pour html) et un .regex(...)
correspondant, plus un body.regex(...) agnostique du format qui lit le texte brut quel que soit le
format. body.html.a, body.html.script et body.html.link sont des
collections toutes prêtes de chaque lien, script et élément <link> de la page ; voir les
portées d'élément ci-dessous pour les champs disponibles sur chacun.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
body.json | Le corps de la réponse, mais seulement quand c'est vraiment du JSON. | string | body.json exists |
body.json.path | Interroger le corps JSON avec une expression JSONPath. | json | body.json.path("$.status") eq "ok" |
body.html | Le corps de la réponse, mais seulement quand c'est vraiment du HTML. | string | body.html exists |
body.html.path | Sélectionner des éléments de page avec un sélecteur CSS. | collection | body.html.path("h1").first contains "Welcome" |
body.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml | Le corps de la réponse, mais seulement quand c'est vraiment du XML. | string | body.xml exists |
body.xml.path | Interroger le corps XML avec une expression XPath. | string | body.xml.path("//item/@id") exists |
body.html.a | Chaque lien de la page. | collection | body.html.a.count gt 0 |
body.html.link | Chaque <link> que la page déclare. Une simple mention signifie les cibles des liens. | collection | body.html.link.count gt 0 |
body.html.script | Chaque script que la page charge. Une simple mention signifie les sources des scripts. | collection | body.html.script.count gt 0 |
body.yaml | Le corps de la réponse, mais seulement quand c'est vraiment du YAML. | string | body.yaml exists |
body.yaml.path | Interroger le corps YAML avec une expression JSONPath. | json | body.yaml.path("$.services.web.image") contains ":1." |
body.html.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
body.json.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
body.yaml.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
Un détail de la famille regex qui mérite d'être signalé : les groupes de capture nommés
((?<id>...)) à l'intérieur d'une règle .regex(...) écrivent dans un espace de
noms de liaison propre à la vérification, qu'une règle ultérieure peut relire avec bind("id") ou
bind[0] par position - voir Valeurs capturées ci-dessous.
Valeurs capturées
Un sujet vit dans son propre groupe du registre car il ne lit pas la réponse directement - il lit ce qu'une règle antérieure en a capturé.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
bind | Une valeur capturée par une règle regex antérieure, par nom de capture ou par position. | string | bind("id") gt 1000 |
Associez-le à une règle regex plus tôt dans la liste : une règle comme
body.regex("order-(?<id>\d+)") exists capture l'identifiant de commande dans le nom
id, et une règle ultérieure peut le tester avec bind("id") gt 1000 ou, pour une
capture positionnelle (sans nom), bind[0].
Timing
Un total plus une répartition par phase, pour qu'une alerte « ça a ralenti » puisse aussi dire quelle partie a ralenti.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
time | Temps de réponse total : connexion + TLS + attente + téléchargement. La résolution DNS n'est pas incluse. | number | time lt 2000 |
ttfb (réservé - pas encore peuplé) | Délai jusqu'au premier octet. | number | ttfb lt 200 |
time.connect | Temps pris pour établir la connexion TCP. | number | time.connect lt 500 |
time.data | Temps pris pour télécharger le corps de la réponse. | number | time.data lt 1000 |
time.dns | Temps pris pour résoudre le nom de domaine. Non inclus dans le sujet time nu. | number | time.dns lt 200 |
time.head | Temps attendu pour les en-têtes de la réponse. | number | time.head lt 500 |
time.tls | Temps pris pour la poignée de main TLS. | number | time.tls lt 300 |
Le sujet time nu est connexion + TLS + attente-des-en-têtes + téléchargement du corps. La
résolution DNS est exclue et ne vit que dans le sujet frère time.dns, car le DNS est souvent mis en
cache et ferait sinon paraître le même point de terminaison tantôt rapide tantôt lent de façon incohérente entre
les vérifications.
Réseau : DNS et connexion
dns et conn sont des espaces de noms purs dans le registre - un groupe sans valeur
propre, donc une règle ne peut jamais s'arrêter sur le nom nu (l'éditeur et le moteur refusent tous deux une
chaîne qui se termine sur dns ou conn seul, et vous orientent vers les vrais champs
ci-dessous).
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
conn | La connexion réseau que la vérification a établie - l'adresse qui a servi la réponse et tout échec de connexion. | string | - |
conn.failed | Combien des adresses résolues ont échoué à se connecter. | number | conn.failed eq 0 |
conn.failedIps (candidat - en cours de déploiement vers les agents) | Les adresses résolues qui ont échoué à se connecter. | collection | conn.failedIps.count eq 0 |
conn.ip | L'adresse IP qui a réellement servi la réponse. | string | conn.ip eq "203.0.113.10" |
conn.ip.family (candidat - en cours de déploiement vers les agents) | Si la réponse a été servie en IPv4 ou en IPv6. | string | conn.ip.family eq "IPv4" |
dns | Résolution DNS du nom surveillé - vers quelles adresses il a résolu et quel serveur a répondu. | string | - |
dns.ips | Toutes les adresses IP vers lesquelles le nom de domaine a résolu pendant cette vérification. | collection | dns.ips contains "1.2.3.4" |
dns.server | Le serveur DNS qui a répondu à la résolution. | string | dns.server eq "8.8.8.8" |
TLS et certificat
Comme dns et conn, tls et cert sont des espaces de noms
purs - les informations de certificat/poignée de main vivent un niveau plus bas.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
cert.days.left | Jours restants avant l'expiration du certificat du site. | number | cert.days.left gt 14 |
cert | Le certificat présenté par le serveur - jours avant expiration, émetteur et champs d'identité. | string | - |
cert.days | Jours depuis l'émission du certificat. | number | cert.days gt 0 |
cert.issuer | L'autorité de certification qui a émis le certificat du site. | string | cert.issuer contains "Let's Encrypt" |
cert.san | Les noms de domaine pour lesquels le certificat est valide. | collection | cert.san contains "www.example.com" |
cert.serial | Le numéro de série du certificat. | string | cert.serial exists |
cert.subject (réservé - pas encore peuplé) | Le sujet du certificat. Pas encore capturé - à venir avec une future version d'agent. | string | cert.subject contains "example.com" |
tls | La poignée de main TLS de la connexion sécurisée - version de protocole et chiffrement négociés. | string | - |
tls.cipher | La suite de chiffrement négociée. | string | tls.cipher contains "AES" |
tls.protocol | La version TLS négociée. | string | tls.protocol eq "Tls13" |
cert.subject est listé ici par souci d'exhaustivité mais n'est pas encore peuplé - voir la
section Honnêteté ci-dessous pour ce que « réservé » signifie en pratique. La règle de certificat du quotidien
est cert.days.left gt 14, couverte dans la section des règles concrètes.
Sujets de saut : champs à l'intérieur de requests et redirects
requests et redirects sont des collections, et chaque élément est un enregistrement
complet de requête/réponse avec son propre ensemble de champs réduit. Tous les sujets de premier niveau n'ont
pas de sens par saut (un saut n'a pas son propre certificat), et un champ n'existe que par saut :
hstsHeader, l'en-tête Strict-Transport-Security de cette requête dans la chaîne.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
status | Le code de statut de cette requête dans la chaîne. | number | status eq 200 |
url | L'URL vers laquelle cette requête a été faite. | url | url startsWith "https://" |
header | Un en-tête de réponse de cette requête. Un saut garde un enregistrement d'en-tête réduit, à valeur unique - les prédicats de type liste (containsAny, containsAll, unique) ne s'appliquent qu'à l'en-tête de la réponse finale. | string | header("Content-Type") contains "json" |
hstsHeader | L'en-tête Strict-Transport-Security de cette requête. | string | requests[0].hstsHeader exists |
setCookie | Les valeurs d'en-tête Set-Cookie de cette requête. | collection | setCookie exists |
url.original | L'URL avec laquelle la vérification a été configurée, avant toute redirection. Une url comme url elle-même : elle a les mêmes parties (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.host | La partie hôte de l'URL. | string | url.host eq "example.com" |
url.port | La partie port de l'URL. | number | url.port eq 443 |
url.path | La partie chemin de l'URL. | string | url.path startsWith "/api" |
url.query | La chaîne de requête de l'URL. | string | url.query contains "token" |
url.scheme | Le schéma de l'URL (http ou https). | string | url.scheme eq "https" |
url.original.host | La partie hôte de l'URL. | string | url.original.host eq "example.com" |
url.original.port | La partie port de l'URL. | number | url.original.port eq 80 |
url.original.path | La partie chemin de l'URL. | string | url.original.path startsWith "/start" |
url.original.query | La chaîne de requête de l'URL. | string | url.original.query contains "utm_" |
url.original.scheme | Le schéma de l'URL (http ou https). | string | url.original.scheme eq "http" |
Le header(...) par saut garde un enregistrement réduit, à valeur unique : des prédicats de forme
liste comme containsAny ou unique n'ont de sens que sur la carte d'en-têtes complète de
la réponse finale, donc ils s'y appliquent et pas par saut. Les deux collections signifient des choses
différentes. requests est la chaîne entière incluant la réponse finale qui a répondu, elle n'est
donc jamais vide même pour un 200 direct, tandis que redirects ne comprend que les sauts suivis en
chemin, vide quand rien n'a redirigé.
Portées d'élément : champs à l'intérieur d'un élément de collection
Une portée d'élément est l'ensemble de champs disponible sur UN élément d'une collection - après indexation
dedans (requests[0]) ou lors du filtrage avec where(current. ...) (voir la section
suivante). Six collections portent leur propre portée d'élément : les quatre collections d'éléments HTML
partagent une forme, et requests/redirects partagent la forme des sujets de saut
documentée juste au-dessus.
| Portée d'élément | À quoi ressemble un élément |
|---|---|
body.html.path | Un élément trouvé par une requête CSS body.html.path("selector"). |
body.html.a | Un élément lien <a> de body.html.a. |
body.html.script | Un élément <script> de body.html.script. |
body.html.link | Un élément <link> de body.html.link. |
requests | Une requête dans la chaîne complète (voir le tableau des sujets de saut ci-dessus). |
redirects | Un saut de redirection suivi (les mêmes champs que requests, voir ci-dessus). |
La forme partagée pour body.html.path(...), body.html.a, body.html.script
et body.html.link - une ligne par lien, balise script ou élément <link> :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
url | La cible du lien exactement telle que le balisage l'écrit. | string | body.html.a.url contains "/checkout" |
text | Le texte visible de l'élément. | string | body.html.a.text contains "Sign in" |
absolute | La cible du lien résolue contre l'URL de la page en une adresse absolue - une liste d'urls, avec les parties de l'url disponibles par élément (.host, .path, .port, .query, .scheme). | url | body.html.a.absolute.scheme in ["https"] |
rel | L'attribut rel de l'élément. | string | body.html.a.where(current.rel eq "nofollow").count eq 0 |
absolute.host | La partie hôte de l'URL. | string | body.html.a.absolute.host.unique.count le 3 |
absolute.port | La partie port de l'URL. | number | body.html.a.absolute.port in [443] |
absolute.path | La partie chemin de l'URL. | string | body.html.a.absolute.path startsWith "/" |
absolute.query | La chaîne de requête de l'URL. | string | body.html.a.absolute.query not contains "session" |
absolute.scheme | Le schéma de l'URL (http ou https). | string | body.html.a.absolute.scheme in ["https"] |
Deux valeurs par défaut s'appliquent avant que vous n'écriviez une règle contre ces collections. Une simple
mention de body.html.a (ou .script/.link) signifie sa projection
.url, donc body.html.a.count gt 0 compte les hrefs, et une règle enregistrée se relit
avec .url écrit explicitement, car une règle stockée dit toujours exactement ce qu'elle évalue. Et
.url est l'attribut href brut exactement tel que le balisage l'a écrit, donc un lien
relatif reste relatif ; .absolute est ce même lien résolu contre l'URL propre de la page, ce que
vous voulez quand vous vérifiez le schéma ou l'hôte des liens sortants
(body.html.a.absolute.scheme in ["https"]).
Opérateurs
La moitié prédicat de chaque règle : quel test exécuter contre le sujet. Les 15 sont partagés entre tous les
types de vérification, et lesquels conviennent à un sujet donné dépend de son type (un code de statut prend
lt/gt, un corps prend contains, une collection prend
exists/unique/in).
| Nom | Ce que c'est | S'applique à | Exemple |
|---|---|---|---|
eq | Égal à. Contre un littéral json("…") / xml("…") / yaml("…") c'est une correspondance structurelle EXACTE : mêmes clés (dans n'importe quel ordre), tableaux dans l'ordre, mêmes valeurs. | tout type | body.json eq json("{\"ok\": true}") |
lt | Inférieur à. | nombres | time lt 2000 |
le | Inférieur ou égal à. | nombres | cert.days.left le 30 |
gt | Supérieur à. | nombres | body.size gt 0 |
ge | Supérieur ou égal à. | nombres | status ge 500 |
contains | Contient le texte - sur une liste, réussit quand la valeur EST l'un des éléments (correspondance exacte ; utilisez matches pour chercher à l'intérieur des éléments). Contre un littéral json("…") / xml("…") / yaml("…") c'est un confinement STRUCTUREL : tout ce que le littéral énonce doit être présent et correspondre ; la réponse peut en avoir plus. | texte ou liste | body.json contains json("{\"status\": \"ok\"}") |
startsWith | Commence par le texte - sur une liste, quand N'IMPORTE QUEL élément le fait. | texte | url.path startsWith "/api" |
endsWith | Se termine par le texte - sur une liste, quand N'IMPORTE QUEL élément le fait. | texte | url.path endsWith ".json" |
matches | Correspond à l'expression régulière n'importe où dans le texte - sur une liste, quand N'IMPORTE QUEL élément le fait. | texte | body matches "order-\\d+" |
containsAny | Contient au moins une des valeurs listées (sur une liste : un élément quelconque ÉGALE l'une d'elles). | liste | body containsAny ["In stock", "Pre-order"] |
containsAll | Contient chacune des valeurs listées (sur une liste : chaque valeur égale un élément quelconque - les témoins peuvent différer). | liste | body.html.a.text containsAll ["Home", "Contact"] |
in | Est l'une des valeurs ou plages listées - sur une liste, chaque élément l'est. | valeur(s) ou plage | status in [200, 301, 302] |
exists | Le sujet est présent. | tout sujet | header("ETag") exists |
isNumber | La valeur se lit comme un nombre. | texte ou tout | bind("id") isNumber |
unique | La liste n'a pas de doublons. | liste | dns.ips unique |
Deux opérateurs signifient quelque chose de plus étroit qu'il n'y paraît. contains sur une liste
est une appartenance exacte : la valeur doit égaler un élément entier, pas apparaître comme une sous-chaîne à
l'intérieur d'un élément, donc utilisez matches quand vous voulez un comportement de sous-chaîne à
travers les éléments d'une collection. Et eq contre un littéral
json(...)/xml(...)/yaml(...) est une correspondance structurelle
complète (mêmes clés, tableaux dans le même ordre, mêmes valeurs), tandis que contains contre le
même type de littéral est un confinement structurel : tout ce que le littéral énonce doit être présent, mais la
vraie réponse peut en porter plus.
Réducteurs
Un réducteur réduit une collection à une seule valeur et ne peut apparaître qu'à la fin d'une chaîne. Les
exemples ci-dessous utilisent requests.status, la collection naturellement numérique que forment
les sujets HTTP, comme illustration ; les huit mêmes réducteurs fonctionnent sur n'importe quelle collection
numérique dans n'importe quel type de vérification (les temps d'aller-retour d'une vérification Ping, un
ensemble filtré de lignes de base de données).
| Nom | Ce qu'il réduit | S'applique à | Exemple |
|---|---|---|---|
count | Combien d'éléments la liste a. | toute collection | requests.count le 2 |
min | Le plus petit nombre de la liste. | collection numérique | requests.status.min ge 200 |
max | Le plus grand nombre de la liste. | collection numérique | requests.status.max lt 500 |
sum | La somme des nombres de la liste. | collection numérique | requests.status.sum gt 0 |
avg | La moyenne des nombres de la liste. | collection numérique | requests.status.avg lt 300 |
first | Le premier élément de la liste. | toute collection | redirects.status.first eq 301 |
last | Le dernier élément de la liste. | toute collection | requests.status.last eq status |
unique | La liste sans les doublons. | toute collection | dns.ips.unique.count le 3 |
unique est surchargé, et l'écriture distingue les deux sens. Écrit comme opérateur sans point
(x unique), c'est un prédicat, « cette collection n'a pas de doublons », et il échoue en nommant la
répétition. Écrit comme réducteur avec un point (x.unique), c'est une transformation, la collection
dédupliquée elle-même, qui a encore besoin de quelque chose après elle
(x.unique.count eq 1). Un x.unique en suspens sans rien qui suit est une erreur de
syntaxe, car le moteur ne peut pas deviner lequel des deux sens vous vouliez.
Sucre syntaxique
Les prédicats sucrés sont des raccourcis que le moteur développe en prédicats de base ordinaires avant même que la règle ne soit envoyée à un agent - ajouter un prédicat sucré ne coûte rien de plus (pas de paquet d'agent, pas de plancher de version) car au moment où il atteint le fil, il ressemble déjà à une règle ordinaire. Préférez le sucre dès qu'il existe : cela se lit mieux, et c'est exactement équivalent à écrire la forme longue à la main.
| Nom | Ce que ça signifie | S'applique à | Exemple |
|---|---|---|---|
isOk | Le statut est un code de succès (200-299). | status | - |
isRedirect | Le statut est un code de redirection (300-399). | status | status isRedirect |
isClientError | Le statut est une erreur client (400-499). | status | status isClientError |
isServerError | Le statut est une erreur serveur (500-599). | status | status isServerError |
isJson | Le contenu est vraiment du JSON. | document ou texte de type de média | header("Content-Type") isJson |
isXml | Le contenu est vraiment du XML - le corps s'analyse comme du XML, ou un en-tête nomme un type de média XML. | document ou texte de type de média | body isXml |
isHtml | Le contenu est vraiment du HTML - le corps s'analyse comme du HTML, ou un en-tête nomme un type de média HTML. | document ou texte de type de média | body isHtml |
isForm | Un type de média nomme un encodage de formulaire : application/x-www-form-urlencoded ou multipart/form-data. Contrairement à isJson/isXml/isHtml il n'y a pas d'espace de noms de corps correspondant, donc cela ne s'applique qu'à une valeur de type de média comme un en-tête Content-Type. | texte de type de média seulement | header("Content-Type") isForm |
isEmpty | Rien là : un texte vide, une taille de zéro ou une liste vide. | texte, taille ou liste | body isEmpty |
isNull | La valeur est null. | toute valeur | body.json.path("$.deletedAt") isNull |
absent | Le sujet n'est pas du tout présent. | tout sujet | header("X-Debug") absent |
between | Un nombre dans une plage incluse. | nombres (2 opérandes) | body.size between 50 and 500kb |
isJson/isXml/isHtml sont sensibles au contexte à dessein, et ce sur
quoi vous les écrivez détermine quel sens s'applique. Écrits sur le document lui-même (body isJson),
ils signifient « est-ce que ceci s'analyse comme ce format », la même chose que body.json exists.
Écrits sur une valeur texte qui nomme un type de média, comme un en-tête
(header("Content-Type") isJson), ils signifient « est-ce que ceci nomme la famille MIME de ce
format » ; voir les familles MIME ci-dessous pour savoir quels types de média se qualifient. isForm
n'a que le second sens, puisqu'il n'y a pas d'espace de noms body.form dans lequel s'analyser, donc
body isForm est une erreur statique plutôt qu'une règle qui ne pourrait jamais être vraie.
Le filtre where(...)
Ne garder que les éléments qui correspondent, puis continuer à partir de là. C'est l'unique construction de
filtrage du langage, et elle a exactement une forme :
where(current.<field> <condition> <value>).
Filtrer diffère de projeter : requests.url contains "cart" demande si un tel saut existe
n'importe où dans la chaîne, tandis que requests.where(current.url contains "cart").status demande
ce que ce saut a renvoyé. Filtrer ne réduit pas la liste, donc terminez avec .first, une
vérification in [...], ou .count. Cela ne va qu'à un seul niveau, et prend exactement
une condition.
| Partie | Ce qu'elle nomme | Notes |
|---|---|---|
current.<field> | Un champ de chaque élément filtré, écrit après current. | C'est la moitié que les gens confondent : current.url est l'URL du saut individuel, pas celle de la réponse finale. Seuls les propres champs de l'élément peuvent suivre current.. |
| la condition | N'importe quel prédicat ordinaire, y compris not et nocase | Toute condition qui fonctionne au niveau supérieur d'une règle fonctionne aussi ici. |
| la valeur | Ce à quoi le champ de chaque élément est comparé | Généralement une valeur simple. Un sujet écrit ici est lu depuis la réponse EXTÉRIEURE, pas l'élément - where(current.url eq url.original) compare chaque saut à l'URL avec laquelle la vérification a été configurée, c'est pourquoi le côté élément doit dire current. explicitement. |
Exemple : requests.where(current.url contains "cart").status.first eq 301 - ne garder que les
sauts dont l'URL contient « cart », puis regarder le statut du premier qui a correspondu.
Deux limites de plus, toutes deux imposées par l'analyseur avec leur propre message : where ne
peut pas être imbriqué dans un autre where, et son argument est exactement une condition, sans
and/or à l'intérieur. Il ne s'applique qu'à une collection dont les éléments portent
des champs nommés (requests, body.html.a), pas à une simple liste projetée comme
dns.ips, où il n'y a rien pour que current. nomme.
Référence de syntaxe
Tout le reste que la grammaire définit : comment nommer une règle, comment écrire des plages et des listes, ce que signifie un sujet nu, et les petites formes de ponctuation qui apparaissent dans beaucoup de règles.
| Forme | Ce qu'elle fait | Genre | Exemple |
|---|---|---|---|
where | Ne garder que les éléments qui correspondent, puis continuer à partir de là. | filtre de collection | requests.where(current.url contains "cart").status.first eq 301 |
not | Inverse la condition qui suit. | drapeau | body not contains "error" |
nocase | Comparer le texte sans tenir compte de la casse. | drapeau | body contains "welcome" nocase |
current | À l'intérieur de where(…), nomme l'unique élément filtré. | référence d'élément (à l'intérieur de where) | requests.where(current.status eq 301) |
range | Une plage de nombres, les deux bornes INCLUSES. | plage de nombres | status in [200..299] |
list | Une liste de valeurs à comparer. | liste de valeurs | status in [200, 301, 302] |
docLiteral | Une valeur de document typée pour comparaison structurelle : le texte entre guillemets est analysé comme JSON, XML ou YAML au moment où la règle est enregistrée. | texte json/xml/yaml | body.json contains json("{\"user\": {\"active\": true}}") |
implicitExists | Une règle qui ne nomme qu'un sujet vérifie qu'il est présent : écrire simplement body.json s'enregistre comme body.json exists. | ligne sujet nu | body.json |
index | Choisit UN élément d'une liste par position, en comptant depuis 0. | entier basé sur 0 | requests[0].status |
label | Un nom optionnel pour la règle, écrit avant un deux-points. | nom avant un deux-points | "json ok": body.json exists |
comment | Tout ce qui suit # est une note pour vous-même ; cela n'affecte pas la vérification. | texte # final | status isOk # the happy path |
Quelques-unes méritent un passage en langage clair. label donne à une règle un nom qui apparaît dans
l'alerte au lieu de l'expression rendue ; écrivez-le avant un deux-points, comme dans
"json ok": body.json exists. implicitExists signifie qu'une ligne ne nommant qu'un sujet et
aucun prédicat est un raccourci pour exists : écrire body.json s'enregistre comme
body.json exists, et rouvrir la règle montre la forme écrite en toutes lettres. range et
list sont les deux formes qu'une valeur peut prendre après in : une plage
([200..299], les deux bornes incluses) ou une liste explicite ([200, 301, 302]), et une
valeur peut être ouverte d'un côté ou de l'autre ([400..]). docLiteral est l'enveloppe
json(...)/xml(...)/yaml(...) utilisée pour la comparaison structurelle
contre le corps (couverte sous Opérateurs ci-dessus et dans les règles concrètes ci-dessous). index choisit
un élément d'une collection par position, basé sur 0, de la même façon que bind[0] lit une capture
positionnelle. current n'a de sens qu'à l'intérieur d'un filtre where(...), couvert dans sa
propre section plus haut.
Enveloppes : previous, delta et delta2
Trois formes qui regardent en arrière au lieu de seulement la réponse actuelle - chacune est réservée aux forfaits avec assertions à état, et chacune est expliquée en détail dans « Comparer à la vérification précédente » ci-dessous.
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
delta (nécessite un forfait avec assertions à état) | De combien une valeur numérique a changé depuis la vérification précédente - optionnellement comme un taux par ms/s/m/h. | number | delta(body.size, h) lt 1mb |
delta2 (nécessite un forfait avec assertions à état) | Le changement du changement - une valeur est-elle en train d'accélérer ? | number | delta2(time) gt 0 |
previous (nécessite un forfait avec assertions à état) | La valeur que ce sujet avait lors de la vérification précédente. | any | status eq previous.status |
Drapeaux : not et nocase
Deux modificateurs qui s'attachent à une règle plutôt que de se tenir comme des sujets ou des prédicats à part entière.
| Drapeau | Ce qu'il fait | Genre | Exemple |
|---|---|---|---|
not | Inverse la condition qui suit. | drapeau (s'attache à une règle) | body not contains "error" |
nocase | Comparer le texte sans tenir compte de la casse. | drapeau (s'attache à une règle) | body contains "welcome" nocase |
not se compose avec le prédicat qui suit plutôt que de nier la règle entière comme un tout -
x not != y se lit comme x eq y, pas comme une double négation. Quand un sujet peut être
totalement absent, préférez le sucre absent à not exists : les deux signifient
exactement la même chose, mais absent le dit directement. nocase ne change quelque
chose que sur une comparaison réellement textuelle ; l'éditeur (et cette référence) vous laissent quand même
l'écrire n'importe où, mais c'est silencieusement sans effet sur un test numérique comme
status eq 200 nocase.
Familles MIME
Les tables de correspondance derrière isJson, isXml, isHtml et
isForm quand ils sont appliqués à une valeur de type de média comme un en-tête. Chaque famille fait
correspondre le type de média de premier niveau évident plus, pour JSON et XML, tout type se terminant par le
suffixe de syntaxe structurée correspondant - ce qui fait que
header("Content-Type") isJson réussit correctement sur application/problem+json ou
application/vnd.api+json et pas seulement le simple application/json.
| Famille | Correspond à | Sucre associé | Exemple |
|---|---|---|---|
json | application/json, text/json, ou tout type de média se terminant par +json (application/problem+json, application/vnd.api+json, application/ld+json, ...). | sucre : isJson | header("Content-Type") isJson |
xml | application/xml, text/xml, ou tout type de média se terminant par +xml (image/svg+xml, application/atom+xml, ...). | sucre : isXml | header("Content-Type") isXml |
html | text/html ou application/xhtml+xml. | sucre : isHtml | header("Content-Type") isHtml |
form | application/x-www-form-urlencoded ou multipart/form-data. | sucre : isForm | header("Content-Type") isForm |
La correspondance ignore tout à partir du premier ; (donc application/json; charset=utf-8
correspond quand même) et ne tient pas compte de la casse.
Sujets pour les vérifications base de données, compteur, SNMP, port et ping
Chaque opérateur, réducteur, raccourci sucré et forme de syntaxe ci-dessus est identique pour ces cinq types
de vérification : le moteur enregistre les mêmes 15 opérateurs, 8 réducteurs, 12 prédicats sucrés et 11 formes de
syntaxe pour les six types sans exception. Ce qui diffère par type est la liste de sujets. Chaque type expose un
petit ensemble de sujets propres à ce qu'il mesure, plus un sous-ensemble des sujets réseau/timing/TLS déjà
documentés ci-dessus, dont le sens s'adapte au type (le time d'une vérification Database est
connexion-plus-requête plutôt que connexion-plus-TLS-plus-téléchargement, puisqu'il n'y a pas de réponse HTTP à
télécharger).
Vérifications base de données
Partage time, time.connect et time.dns avec les sujets documentés
ci-dessus (recentrés sur une connexion de base de données : connexion-plus-requête, résolution DNS de l'hôte de
base de données). Propres aux vérifications base de données :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
scalar | La valeur unique renvoyée par la requête (mode Scalar). | any | - |
rows | Les lignes que la requête a affectées ou renvoyées (mode NonQuery). | collection | - |
time.query | Le temps qu'a pris la requête elle-même. | number | - |
Un exemple concret se trouve dans la section suivante : utilisez rows.count pour vérifier combien
de lignes une requête a affectées ou renvoyées, et scalar pour vérifier directement une seule
valeur renvoyée.
Vérifications compteur
Partage time avec les sujets documentés ci-dessus - comme champ à statut candidat spécifiquement
pour les vérifications Counter (temps d'aller-retour de la requête du compteur ; voir la section Honnêteté pour
ce que « candidat » signifie). Propre aux vérifications compteur :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
value | La valeur mesurée du compteur. | number | - |
Vérifications SNMP
Partage time et time.dns avec les sujets documentés ci-dessus (résolution du nom
d'hôte plus la requête SNMP elle-même). Propres aux vérifications SNMP :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
time.request | Le temps qu'a pris la requête SNMP. | number | - |
value | La valeur renvoyée par l'OID. | any | - |
value.type (candidat - en cours de déploiement vers les agents) | Le nom du type de donnée SNMP de la valeur renvoyée. | string | - |
value.type est à statut candidat ; voir la section Honnêteté. Remarque sur la
disponibilité : l'interrupteur Validation de la réponse du mode assertion n'a pas encore atteint l'éditeur de
moniteur SNMP. Il affiche un panneau « Bientôt disponible » nommant ces deux sujets plutôt qu'une liste de règles
fonctionnelle. Les sujets et l'évaluateur sous-jacent sont déjà enregistrés ; seule l'interface de l'éditeur SNMP
est en attente.
Vérifications port
La plus grande liste partagée de tous les types non-HTTP. Une vérification de port TCP porte essentiellement
les mêmes sujets de connexion, DNS, TLS et certificat qu'une vérification HTTP, puisqu'une vérification de port
peut aussi négocier TLS : bind, cert et ses six sous-champs, conn et ses
quatre sous-champs, dns et ses deux sous-champs,
time/time.connect/time.dns/time.tls, et
tls/tls.cipher/tls.protocol - tous documentés dans les sections
ci-dessus, avec les mêmes sens. Propres aux vérifications port :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
banner | Les données lues sur le socket après la connexion. | string | - |
banner.hash (candidat - en cours de déploiement vers les agents) | Un condensé de la bannière - comparez avec previous.banner.hash pour détecter des changements de service. | string | - |
banner.regex | Faire correspondre le texte avec une expression régulière et prendre ce qui a été capturé. | string | body.regex("order-(?<id>\\d+)") exists |
banner.size (candidat - en cours de déploiement vers les agents) | La taille de la bannière, en octets. | number | - |
banner.hash et banner.size sont à statut candidat - voir la section Honnêteté.
banner.regex est vivant aujourd'hui et fonctionne exactement comme body.regex(...) sur
une vérification HTTP : les captures nommées alimentent le même espace de noms bind(...).
Vérifications ping
Partage les sujets de connexion et DNS avec les sections ci-dessus : conn,
conn.failed, conn.failedIps, conn.ip, conn.ip.family,
dns, dns.ips, dns.server, time (ici, le temps d'aller-retour
moyen des réponses réussies) et time.dns. Propres aux vérifications ping :
| Nom | Ce que c'est | Type/valeurs | Exemple |
|---|---|---|---|
loss | Le pourcentage de requêtes echo qui n'ont eu aucune réponse. | number | loss eq 0 |
reply | Les réponses echo réussies. | collection | - |
sentCount (candidat - en cours de déploiement vers les agents) | Combien de requêtes echo ont été envoyées. | number | - |
time.max | Le temps d'aller-retour de la réponse la plus lente. | number | - |
time.min | Le temps d'aller-retour de la réponse la plus rapide. | number | - |
ttl | Le TTL de la première réponse réussie - comparez avec previous.ttl pour repérer des changements de route. | number | - |
sentCount est à statut candidat - voir la section Honnêteté. ttl est bon à connaître
même en dehors d'une règle stricte de réussite/échec : l'associer avec previous.ttl (voir Enveloppes
ci-dessus) signale un changement de route entre deux vérifications, puisque le temps de vie d'un paquet à son
arrivée reflète combien de sauts il a traversés.
Les règles que les gens veulent vraiment écrire
La page est en ligne et dit vraiment ce qu'il faut
Un code de statut seul ne peut pas vous dire qu'une page s'est bien affichée - une réponse 200 avec une coquille vide est l'échec silencieux classique qu'une vérification limitée au statut manque.
status isOk
body contains "Add to cart"
Une API répond en JSON avec le champ attendu
Vérifiez que le point de terminaison parle toujours JSON, puis allez chercher dedans. La première ligne attrape une page d'erreur HTML servie là où du JSON était attendu, une forme de panne courante derrière un proxy ; la seconde vérifie l'état de santé rapporté par l'API elle-même, pas seulement son statut de transport.
body isJson
body.json.path("$.status") eq "ok"
La réponse a ralenti plus qu'elle ne le devrait
Décomposez quand vous avez besoin de savoir quoi corriger plutôt que juste que quelque chose est lent -
time.connect, time.tls, time.dns et time.head séparent le
temps réseau, de poignée de main, de résolveur et d'application.
time lt 2s
Une redirection a envoyé les visiteurs hors de votre propre domaine
Compare là où la vérification a atterri à l'URL que vous avez configurée - elle échoue dès qu'une chaîne de redirection, détournée, mal configurée, ou simplement changée par un déploiement, atterrit quelque part que vous ne vouliez pas.
url.host eq url.original.host
La page a changé depuis la dernière vérification
Utile sur un contenu censé rester stable entre les vérifications - tarification, conditions, une politique publiée - et fait aussi office de signal basique de défiguration.
previous.body.hash eq body.hash
Un nombre dans une plage, écrit de la façon courte
Attrape à la fois une page dépouillée et une page qui s'emballe dans une seule règle, sans écrire une plage explicite.
body.size between 50 and 500kb
Un certificat sur le point d'expirer
La vérification TLS la plus courante de loin, et l'une qu'un simple moniteur actif/en panne ne peut pas
exprimer du tout - un certificat encore valide aujourd'hui mais qui expire la semaine prochaine ne donne aucun
autre signe d'alerte. Associez-la à cert.issuer si vous voulez aussi attraper un certificat émis
discrètement par la mauvaise autorité.
cert.days.left gt 14
Une requête de base de données renvoyant le mauvais nombre de lignes
Sur une vérification Database, rows est la collection qu'une requête a affectée ou renvoyée -
la compter attrape une requête censée renvoyer exactement un enregistrement de compte qui se met
silencieusement à en renvoyer zéro (supprimé, ou une jointure cassée) ou plus d'un (un doublon qui ne devrait
pas exister).
rows.count eq 1
Une valeur SNMP qui dérive hors de sa plage
Un équipement SNMP qui répond n'est pas la même chose qu'un équipement en bonne santé - un OID surveillé
(utilisation disque, profondeur de file d'attente, température) peut grimper bien au-delà d'un seuil sûr
pendant que l'équipement lui-même reste parfaitement joignable. Comparer la value interrogée à une
plage attrape ce qu'une simple vérification de joignabilité ne peut pas.
value lt 90
Un service TCP qui répond avec la mauvaise bannière
Un port qui accepte les connexions n'est pas la même chose que le bon service qui écoute dessus - un processus figé, un proxy mal configuré, ou un service dégradé/substitué peuvent tous quand même compléter une poignée de main TCP. Lire le texte d'accueil qu'un service envoie juste après la connexion (une bannière SMTP, FTP ou similaire) attrape ce qu'une simple vérification de port ouvert ne peut pas.
banner contains "220"
Comparer à la vérification précédente
Une poignée de sujets regardent en arrière au lieu de seulement la réponse actuelle : mettez
previous. devant un sujet pour lire ce qu'il était à la dernière vérification, ou enveloppez-le
dans delta(...) pour obtenir la différence entre alors et maintenant, ou dans
delta2(...) pour obtenir le changement de ce changement - utile pour repérer une valeur qui
accélère plutôt qu'elle ne dérive (un temps de réponse qui monte plus vite à chaque vérification).
previous.body.hash eq body.hash ci-dessus est exactement cela - « l'empreinte du corps
correspond-elle à ce qu'elle était la dernière fois ». delta(body.size, h) lit le changement comme
un taux par heure plutôt qu'une différence brute, pour des valeurs censées croître régulièrement plutôt que
sauter.
La première fois qu'une règle comme celle-ci s'exécute, elle n'a rien à quoi comparer, donc elle est ignorée
plutôt qu'en échec : la vérification est marquée « en chauffe », pas cassée, et ajouter la règle ne déclenche
aucune fausse alerte. La chauffe ne s'applique que quand la lecture actuelle est saine et que la référence
manque. Si la lecture actuelle elle-même échoue (disons, le corps n'est pas du JSON valide cette fois), la règle
échoue exactement comme le ferait sa version simple, sans previous.. Une telle règle a aussi besoin
que la valeur change entre les vérifications, ce qui la rend dénuée de sens sur une méthode de vérification qui
ne fait jamais avancer l'état, une requête HEAD par exemple.
Comparer à la vérification précédente nécessite un forfait de niveau supérieur ; sans cela, ces sujets apparaissent grisés dans l'éditeur avec une explication.
Limites, et ce qui manque délibérément
Combien de règles vous pouvez ajouter dépend de votre forfait, montré comme un compteur en direct à côté de « Ajouter une règle ». Le moteur impose aussi un plafond absolu sur chaque vérification quel que soit le forfait, une protection contre les abus plutôt qu'une limite sur l'usage ordinaire : une vérification approchant ce nombre de règles serait déjà inhabituellement grande.
Il n'y a aucun moyen d'écrire du JavaScript personnalisé pour une règle, et il n'y en aura jamais. Chaque règle est construite à partir d'un vocabulaire fixe et nommé de sujets et de prédicats plutôt que d'un bac à sable de script ouvert, ce qui garde une règle lisible d'un coup d'œil et sûre à exécuter sur chaque agent de surveillance dans le monde.
Toutes les règles ne fonctionnent pas partout dès l'instant où elles sont écrites : certaines conditions plus récentes nécessitent une version récente de l'agent de surveillance qui exécute votre vérification, donc une nouvelle capacité met du temps à atteindre chaque vérification de votre compte à mesure que les agents se mettent à jour en arrière-plan. Les règles construites sur le socle stable du langage ne sont pas affectées.
Une poignée d'entrées de cette référence ne sont pas encore pleinement en service, et chacune est étiquetée dans son tableau ci-dessus :
- Réservé (déclaré, pas encore peuplé par aucun agent) :
ttfb,httpVersion,cert.subject. - Candidat (déjà en cours de déploiement, pas encore sur tous les agents) :
conn.ip.familyetconn.failedIpssur les vérifications HTTP, Port et Ping,value.typesur les vérifications SNMP,banner.hashetbanner.sizesur les vérifications Port,sentCountsur les vérifications Ping, et letimepropre à la vérification Counter. - Pas encore disponible :
steps, réservé à un futur type de vérification multi-étapes. - Nécessite un forfait avec assertions à état : toute la famille d'enveloppes
previous/delta/delta2, sur chaque type de vérification.
Tout le reste de cette référence est vivant aujourd'hui sur tout forfait ayant le mode assertion.
Où le mode assertion fonctionne aujourd'hui
L'interrupteur Validation de la réponse pour le mode assertion apparaît sur les moniteurs HTTP (site web) et API, qui partagent le même éditeur de règles et la même syntaxe. Le même langage et le même évaluateur tournent déjà en dessous des vérifications Database, Counter, Port, Ping et SNMP au niveau du protocole : le registre ci-dessus sert les six types de vérification, et une règle enregistrée pour l'un se lit de la même façon si le mode atteint l'éditeur d'un autre type plus tard.
SNMP montre l'aperçu le plus clair : son éditeur a déjà un panneau Règles d'assertion nommant
value et value.type, étiqueté « Bientôt disponible », sans liste de règles
fonctionnelle derrière pour l'instant. Les vérifications Database, Counter et Ping ne montrent aucun panneau de
mode assertion du tout, même si leurs sujets sont tout aussi vivants dans le moteur sous-jacent.
Mettre en place une vraie vérification
Si vous validez une API REST plutôt qu'une simple page web, commencez par la
validation de réponse API, qui couvre ensemble l'uptime, le temps de
réponse et le corps de votre propre API. Pour une page ou un site qui doit rester en ligne et répondre
correctement depuis partout où se trouvent vos utilisateurs, la
surveillance d'uptime mondiale depuis plus de 300
emplacements est le tableau d'ensemble dans lequel s'insère le mode assertion. Pour définir des règles par
le code plutôt que par le panneau, la propre API v2 de HostTracker crée et met
à jour les règles d'assertion d'un moniteur de la même façon que l'éditeur. Pour la règle d'expiration de
certificat ci-dessus et tout ce qui touche à TLS, la
surveillance de domaine et de certificat TLS couvre le type de vérification
sur lequel vivent cert.days.left et les autres sujets TLS. Pour voir une règle s'évaluer contre une
vraie URL dès maintenant, sans compte, utilisez l'outil gratuit de vérification
HTTP. Pour les codes de statut auxquels le sujet status compare, commencez par
200 OK, et les guides de
surveillance couvrent la mise en place de chaque type de vérification sous lequel ce langage tourne.
Questions fréquentes
Qu'advient-il de mes anciens réglages de code de statut et de mot-clé si j'active le mode assertion ?
Ils sont remplacés par la liste de règles tant que le mode est actif. Le désactiver de nouveau avant d'enregistrer restaure les champs classiques exactement comme ils étaient : rien n'est supprimé, les deux modes ne peuvent simplement pas être actifs en même temps.
Puis-je combiner plusieurs conditions dans un seul moniteur ?
Oui : chaque règle de la liste doit réussir. Il n'y a pas encore de « OU » entre des règles séparées, donc
pour accepter l'une de plusieurs valeurs, utilisez une seule règle avec in [...] ou
containsAny [...].
Le mode assertion me laissera-t-il un jour écrire mon propre script ?
Non. Chaque règle est composée à partir de l'ensemble fixe de sujets et de prédicats du langage. Il n'y a pas de JavaScript personnalisé, par conception.
Que se passe-t-il la première fois que j'ajoute une règle qui compare à la vérification précédente ?
Elle n'a encore rien à quoi comparer, donc elle est marquée comme en chauffe et ignorée plutôt qu'en échec. Ajouter une règle « est-ce que ça a changé » ne déclenche jamais de fausse alerte à elle seule.
Ai-je besoin d'un forfait précis pour utiliser le mode assertion ?
Le mode lui-même et les règles du quotidien (statut, corps, en-têtes, timing, redirections) sont largement
disponibles ; combien de règles vous pouvez ajouter à la fois dépend de votre forfait et est montré en direct
dans l'éditeur. Les règles qui comparent à une vérification précédente (previous,
delta, delta2) nécessitent un forfait de niveau supérieur et sont grisées avec une
explication.
Le mode assertion fonctionne-t-il sur les moniteurs API de la même façon que sur les moniteurs de site web ?
Oui. Les moniteurs HTTP et API partagent le même éditeur de règles, les mêmes sujets et les mêmes prédicats, et une règle écrite pour l'un se lit de façon identique sur l'autre.
Que fait vraiment where(...), et quand en ai-je besoin ?
Il filtre une collection jusqu'aux éléments correspondant à une condition avant que vous ne lisiez un champ
du résultat. Utilisez-le quand une simple projection comme requests.status n'est pas assez précise
et que vous avez besoin d'un saut, d'un lien ou d'un élément particulier plutôt que de toute la collection (voir
la section ci-dessus).
Puis-je écrire une règle contre une requête de base de données, une valeur SNMP, une bannière de port ou un résultat de ping aujourd'hui ?
Le langage et l'évaluateur les prennent tous en charge, et les tableaux de sujets ci-dessus couvrent chacun d'eux. L'éditeur de règles, non : seuls les moniteurs HTTP et API montrent l'interrupteur Validation de la réponse aujourd'hui. SNMP montre un aperçu « Bientôt disponible » de ses deux sujets, et Database, Counter et Ping ne montrent aucun panneau de mode assertion du tout.
Pourquoi certains sujets de cette référence disent-ils « réservé » ou « candidat » plutôt que d'être simplement listés normalement ?
« Réservé » signifie que le champ est déclaré dans le registre mais qu'aucun agent ne le peuple encore ; « candidat » signifie qu'il est en cours de déploiement vers les agents mais ne les a pas tous atteints. Les deux sont signalés partout où ils apparaissent dans cette référence et dans la liste récapitulative de la section Limites ci-dessus.