Modo de asserções: referência completa de validação
O modo de asserções substitui os campos fixos de aprovado/reprovado de um monitor por uma lista de regras que você mesmo escreve, cada regra nomeando exatamente o que precisa ser verdade sobre a resposta. A maioria dos monitores de uptime julga uma verificação com um punhado de campos fixos: um código de status que conta como "fora do ar", uma lista de status a ignorar, talvez uma palavra-chave que precisa aparecer em algum lugar no corpo. Esses campos não conseguem expressar uma API que legitimamente responde 404 para um recurso ausente, uma página que devolve 200 com uma casca vazia porque o banco de dados deu timeout, ou uma cadeia de redirecionamento que começa a passar pelo domínio de outra pessoa.
O modo de asserções da HostTracker substitui esses campos fixos por uma pequena linguagem de regras que você escreve, regra por regra, dentro do editor do monitor. Cada regra diz exatamente o que precisa ser verdade sobre a resposta: o status, um trecho do corpo, um cabeçalho, quanto tempo levou, para onde um redirecionamento foi parar. Uma verificação falha apenas quando uma das suas regras falha. É a mesma linguagem para um site, uma API REST, uma consulta de banco de dados, uma porta TCP, um alvo de Ping, um contador SNMP ou uma verificação de Counter genérica: um único conjunto de sujeitos, um único conjunto de predicados, reutilizados em todo lugar onde o modo aparece. Este guia cobre todo sujeito, operador, redutor, atalho de açúcar sintático e forma de sintaxe que o motor implementa.
O que o modo de asserções substitui
Os campos clássicos de Validação de Resposta continuam lá quando o modo de asserções está desligado: um intervalo de status esperado, uma lista de status a ignorar, uma palavra-chave que precisa (ou não pode) aparecer. O modo é um interruptor que troca esse conjunto fixo por uma lista de regras que você mesmo constrói, e desligá-lo de novo antes de salvar traz os campos clássicos de volta imediatamente. Nenhum monitor fica preso a um modo permanentemente.
Uma única linguagem em vez de uma pilha de mecanismos específicos por tipo se compõe. Uma verificação "precisa ser JSON e conter um campo", uma verificação "ainda precisa dizer Adicionar ao carrinho" e uma verificação "não pode ter ficado mais lenta" são três regras na mesma sintaxe, na mesma lista, cada uma passando ou falhando por conta própria.
Ativando o modo
O modo de asserções fica dentro da seção Validação de Resposta do editor do monitor, para monitores HTTP (site) e API. Ative o interruptor, e os campos clássicos são substituídos por uma lista numerada de regras com um botão "Adicionar regra" e um contador ao vivo mostrando quantas regras você usou em relação ao limite do seu plano.

Cada regra é validada conforme você a constrói: uma regra ainda não terminada carrega um estado distinto de "inacabada", e uma regra que o editor consegue avaliar é marcada como completa. Toda regra também tem um pequeno botão </> que abre a forma de texto puro da fonte dela, para que você possa ler ou copiar a expressão exata em vez de só a visão caixa por caixa.
O modelo mental: sujeito, predicado, valor
Toda regra tem o mesmo formato: um sujeito (o código de status, o corpo, um cabeçalho, o tempo de resposta), um predicado (igual a, contém, existe, é menor que) e, para a maioria dos predicados, um valor para comparar. status eq 200 é sujeito, predicado e valor; body.json exists é um sujeito e um predicado sem valor, porque "existe" não precisa de mais nada.
Construir uma regra no editor começa escolhendo o que verificar, depois a condição, depois o valor:

As regras na lista são combinadas com E: uma verificação falha quando qualquer regra individual falha e passa apenas quando todas as regras passam. Ainda não existe OU, então, para aceitar um entre vários status ou textos, expresse isso dentro de uma única regra (status in [200, 301, 302], body containsAny ["In stock", "Pre-order"]). Uma regra que falha se nomeia no alerta, então dê um rótulo curto a cada uma onde puder, e o alerta vai dizer qual expectativa quebrou.
O que você pode verificar
O seletor agrupa os sujeitos entre o próprio documento da resposta (o corpo, os cabeçalhos) e o transporte dela (status, tempo, redirecionamentos, TLS). Alguns dos sujeitos mais importantes, com a lista completa na referência a seguir:
| Sujeito | O que é | Exemplo |
|---|---|---|
status | O código de status HTTP da resposta final, depois de os redirecionamentos serem seguidos | status isOk |
body | O corpo da resposta como texto puro | body contains "Add to cart" |
body.json / body.xml / body.html / body.yaml | O corpo, mas só quando ele realmente é interpretável nesse formato - caso contrário o sujeito simplesmente não está presente | body.json exists |
body.json.path("$.a") | Uma consulta JSONPath dentro de um corpo JSON (a mesma linguagem de consulta também funciona sobre YAML, já que YAML é interpretado no mesmo modelo de objeto) | body.json.path("$.status") eq "ok" |
body.size / body.hash | O tamanho da resposta em bytes, e uma impressão digital do conteúdo do corpo | body.size gt 1kb |
header("Name") | Um cabeçalho da resposta, buscado pelo nome | header("Content-Type") isJson |
time e time.connect / time.tls / time.dns / time.head | Tempo total de resposta, e suas fases de rede, handshake TLS, DNS e tempo de processamento do servidor | time lt 2s |
redirects / requests | Os saltos que uma verificação seguiu, e a cadeia completa (incluindo a resposta final) | redirects.count eq 0 |
url e suas partes (.host, .scheme, .path...) | A URL final em que a verificação chegou | url.scheme eq "https" |
cert.days.left | Dias restantes antes de o certificado TLS vencer | cert.days.left gt 14 |
Os números aceitam sufixos de unidade para que você nunca precise converter na mão: 2s significa 2000 milissegundos, 1kb significa 1024 bytes. As comparações de texto diferenciam maiúsculas de minúsculas, a menos que você adicione nocase à regra.
A referência completa
O que vem a seguir é todo sujeito, operador, redutor, atalho de açúcar sintático, filtro e forma de sintaxe que o motor de asserções registra para verificações HTTP e API, tirado diretamente do registro do próprio motor (os mesmos dados que alimentam os seletores do editor de regras e a sua documentação). As entradas que ainda não estão totalmente disponíveis carregam uma nota entre parênteses: campos reservados que o motor ainda não começou a popular, candidatos ainda em fase de lançamento para os agentes, e a família com estado que precisa de um plano específico. Qualquer coisa sem essa nota já está disponível hoje em todo plano que tem o modo de asserções.
A referência segue o agrupamento do próprio motor: campos da resposta, depois as formas de acessar um corpo, depois tempo, rede e TLS, depois os operadores, redutores e atalhos que funcionam sobre todos eles, depois os tipos de verificação além de HTTP que falam a mesma linguagem.
Resposta
Os sujeitos que descrevem a própria resposta: seu status, seu corpo bruto, seus cabeçalhos, a URL de onde ela de fato respondeu, e a cadeia de requisições que chegou até ali.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
body | O corpo da resposta como texto decodificado. | texto | body contains "Welcome" |
header | Um cabeçalho da resposta final, pelo nome. | texto | header("Content-Type") isJson |
redirects | Os saltos de redirecionamento seguidos - a cadeia de requisições sem o último elemento. | coleção | redirects.count eq 0 |
status | O código de status HTTP da resposta final, depois de os redirecionamentos serem seguidos. | número | status isOk |
body.size | O tamanho do corpo baixado, em bytes. | número | body.size lt 500000 |
url | A URL que efetivamente respondeu, depois de todos os redirecionamentos. Uma url: compare-a como texto, ou leia suas partes (url.host, .port, .path, .query, .scheme). | url | url.host eq "www.example.com" |
requests | Toda requisição que essa verificação fez, em ordem - os saltos de redirecionamento e depois a requisição final. | coleção | requests.count le 2 |
url.host | A parte de host da URL. | texto | url.host eq "example.com" |
url.path | A parte de caminho da URL. | texto | url.path startsWith "/api" |
url.port | A parte de porta da URL. | número | url.port eq 443 |
url.query | A string de consulta da URL. | texto | url.query contains "token" |
url.scheme | O esquema da URL (http ou https). | texto | url.scheme eq "https" |
body.hash | Um resumo (digest) do corpo da resposta - compare com previous.body.hash para detectar mudanças de conteúdo. | texto | body.hash eq previous.body.hash |
httpVersion (reservado - ainda não populado) | A versão de HTTP negociada. | texto | httpVersion eq "HTTP/2" |
setCookie | Os valores de Set-Cookie da resposta final, um item por cookie - combine um com contains ou matches, conte-os com .count. | coleção | setCookie exists |
steps (ainda não disponível) | As etapas de uma verificação em várias etapas. Ainda não disponível. | coleção | steps.count le 1 |
url.original | A URL com que a verificação foi configurada, antes de qualquer redirecionamento. Uma url como a própria url: tem as mesmas partes (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.original.host | A parte de host da URL. | texto | url.original.host eq "example.com" |
url.original.path | A parte de caminho da URL. | texto | url.original.path startsWith "/start" |
url.original.port | A parte de porta da URL. | número | url.original.port eq 80 |
url.original.query | A string de consulta da URL. | texto | url.original.query contains "utm_" |
url.original.scheme | O esquema da URL (http ou https). | texto | url.original.scheme eq "http" |
Dois apelidos: redirectCount é um atalho para redirects.count - redirectCount eq 0 lê um pouco mais naturalmente do que a forma longa equivalente quando você quer dizer "a verificação respondeu diretamente, sem redirecionamentos". E setCookie no nível superior é a lista de cookies da resposta final; o mesmo nome reaparece por salto dentro de requests/redirects (veja Sujeitos de salto abaixo), guardando apenas os cookies daquela requisição.
Extraindo valores do corpo
Esses sujeitos só se resolvem quando o corpo é o formato que eles nomeiam: um namespace JSON em uma página HTML simplesmente não está presente, não é um erro tipado. Isso faz de exists a forma padrão de sondar o formato, e body.json exists pergunta se o corpo foi interpretado como JSON. Os quatro namespaces de formato carregam cada um uma função .path(...) correspondente (JSONPath para json/yaml, XPath para xml, seletores CSS para html) e um .regex(...) correspondente, além de um body.regex(...) agnóstico de formato que lê o texto bruto independentemente do formato. body.html.a, body.html.script e body.html.link são coleções prontas de todo link, script e elemento <link> da página; veja Escopos de elemento abaixo para os campos disponíveis em cada um.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
body.json | O corpo da resposta, mas só quando realmente é JSON. | texto | body.json exists |
body.json.path | Consulta o corpo JSON com uma expressão JSONPath. | json | body.json.path("$.status") eq "ok" |
body.html | O corpo da resposta, mas só quando realmente é HTML. | texto | body.html exists |
body.html.path | Seleciona elementos da página com um seletor CSS. | coleção | body.html.path("h1").first contains "Welcome" |
body.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
body.xml | O corpo da resposta, mas só quando realmente é XML. | texto | body.xml exists |
body.xml.path | Consulta o corpo XML com uma expressão XPath. | texto | body.xml.path("//item/@id") exists |
body.html.a | Todo link da página. | coleção | body.html.a.count gt 0 |
body.html.link | Todo <link> que a página declara. Uma menção simples se refere aos alvos do link. | coleção | body.html.link.count gt 0 |
body.html.script | Todo script que a página carrega. Uma menção simples se refere às fontes dos scripts. | coleção | body.html.script.count gt 0 |
body.yaml | O corpo da resposta, mas só quando realmente é YAML. | texto | body.yaml exists |
body.yaml.path | Consulta o corpo YAML com uma expressão JSONPath. | json | body.yaml.path("$.services.web.image") contains ":1." |
body.html.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
body.json.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
body.xml.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
body.yaml.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
Um detalhe da família de regex que vale destacar: grupos de captura nomeados ((?<id>...)) dentro de uma regra .regex(...) gravam em um namespace de vínculos com escopo de verificação que uma regra posterior pode ler de volta com bind("id") ou bind[0] por posição - veja Valores capturados abaixo.
Valores capturados
Um sujeito vive em seu próprio grupo do registro porque não lê a resposta diretamente - ele lê o que uma regra anterior capturou dela.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
bind | Um valor capturado por uma regra de regex anterior, pelo nome da captura ou pela posição. | texto | bind("id") gt 1000 |
Combine com uma regra de regex anterior na lista: uma regra como body.regex("order-(?<id>\d+)") exists captura o id do pedido no nome id, e uma regra posterior pode testá-lo com bind("id") gt 1000 ou, para uma captura posicional (sem nome), bind[0].
Tempo
Um total mais uma divisão por fase, para que um alerta de "ficou mais lento" também possa dizer qual parte ficou mais lenta.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
time | Tempo total de resposta: conexão + TLS + espera + download. A resolução de DNS não está incluída. | número | time lt 2000 |
ttfb (reservado - ainda não populado) | Tempo até o primeiro byte. | número | ttfb lt 200 |
time.connect | Tempo levado para estabelecer a conexão TCP. | número | time.connect lt 500 |
time.data | Tempo levado para baixar o corpo da resposta. | número | time.data lt 1000 |
time.dns | Tempo levado para resolver o nome de domínio. Não incluído no sujeito time simples. | número | time.dns lt 200 |
time.head | Tempo de espera pelos cabeçalhos da resposta. | número | time.head lt 500 |
time.tls | Tempo levado pelo handshake TLS. | número | time.tls lt 300 |
O sujeito time simples é conexão + TLS + espera pelos cabeçalhos + download do corpo. A resolução de DNS fica de fora e só existe no irmão time.dns, porque o DNS costuma ficar em cache e faria o mesmo endpoint parecer inconsistentemente rápido ou lento entre verificações.
Rede: DNS e conexão
dns e conn são namespaces puros no registro - um grupo sem valor próprio, então uma regra nunca pode terminar no nome simples (o editor e o motor recusam uma cadeia que termina em dns ou conn sozinho, apontando para os campos reais abaixo).
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
conn | A conexão de rede que a verificação fez - o endereço que serviu a resposta e quaisquer falhas de conexão. | texto | - |
conn.failed | Quantos dos endereços resolvidos falharam ao conectar. | número | conn.failed eq 0 |
conn.failedIps (candidato - em rollout para os agentes) | Os endereços resolvidos que falharam ao conectar. | coleção | conn.failedIps.count eq 0 |
conn.ip | O endereço IP que efetivamente serviu a resposta. | texto | conn.ip eq "203.0.113.10" |
conn.ip.family (candidato - em rollout para os agentes) | Se a resposta foi servida sobre IPv4 ou IPv6. | texto | conn.ip.family eq "IPv4" |
dns | Resolução DNS do nome monitorado - para quais endereços ele resolveu e qual servidor respondeu. | texto | - |
dns.ips | Todos os endereços IP para os quais o nome de domínio resolveu durante essa verificação. | coleção | dns.ips contains "1.2.3.4" |
dns.server | O servidor DNS que respondeu a resolução. | texto | dns.server eq "8.8.8.8" |
TLS e certificado
Assim como dns e conn, tls e cert são namespaces puros - os fatos do certificado/handshake ficam um nível abaixo.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
cert.days.left | Dias restantes até o certificado do site vencer. | número | cert.days.left gt 14 |
cert | O certificado que o servidor apresentou - dias até o vencimento, emissor e campos de identidade. | texto | - |
cert.days | Dias desde que o certificado foi emitido. | número | cert.days gt 0 |
cert.issuer | A autoridade certificadora que emitiu o certificado do site. | texto | cert.issuer contains "Let's Encrypt" |
cert.san | Os nomes de domínio para os quais o certificado é válido. | coleção | cert.san contains "www.example.com" |
cert.serial | O número de série do certificado. | texto | cert.serial exists |
cert.subject (reservado - ainda não populado) | O assunto (subject) do certificado. Ainda não capturado - virá em uma versão futura do agente. | texto | cert.subject contains "example.com" |
tls | O handshake TLS da conexão segura - versão de protocolo e cifra negociadas. | texto | - |
tls.cipher | A suíte de cifra negociada. | texto | tls.cipher contains "AES" |
tls.protocol | A versão de TLS negociada. | texto | tls.protocol eq "Tls13" |
cert.subject está listado aqui por completude mas ainda não está populado - veja a seção Honestidade abaixo para o que "reservado" significa na prática. A regra de certificado do dia a dia é cert.days.left gt 14, coberta na seção de regras prontas.
Sujeitos de salto: campos dentro de requests e redirects
requests e redirects são coleções, e cada item é um registro completo de requisição/resposta com o próprio conjunto reduzido de campos. Nem todo sujeito de nível superior faz sentido por salto (um salto não tem certificado próprio), e um campo existe só por salto: hstsHeader, o cabeçalho Strict-Transport-Security daquela requisição na cadeia.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
status | O código de status dessa requisição na cadeia. | número | status eq 200 |
url | A URL para a qual essa requisição foi feita. | url | url startsWith "https://" |
header | Um cabeçalho de resposta dessa requisição. Um salto mantém um registro de cabeçalho reduzido, de valor único - predicados de lista (containsAny, containsAll, unique) se aplicam só ao cabeçalho da resposta final. | texto | header("Content-Type") contains "json" |
hstsHeader | O cabeçalho Strict-Transport-Security dessa requisição. | texto | requests[0].hstsHeader exists |
setCookie | Os valores do cabeçalho Set-Cookie dessa requisição. | coleção | setCookie exists |
url.original | A URL com que a verificação foi configurada, antes de qualquer redirecionamento. Uma url como a própria url: tem as mesmas partes (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.host | A parte de host da URL. | texto | url.host eq "example.com" |
url.port | A parte de porta da URL. | número | url.port eq 443 |
url.path | A parte de caminho da URL. | texto | url.path startsWith "/api" |
url.query | A string de consulta da URL. | texto | url.query contains "token" |
url.scheme | O esquema da URL (http ou https). | texto | url.scheme eq "https" |
url.original.host | A parte de host da URL. | texto | url.original.host eq "example.com" |
url.original.port | A parte de porta da URL. | número | url.original.port eq 80 |
url.original.path | A parte de caminho da URL. | texto | url.original.path startsWith "/start" |
url.original.query | A string de consulta da URL. | texto | url.original.query contains "utm_" |
url.original.scheme | O esquema da URL (http ou https). | texto | url.original.scheme eq "http" |
O header(...) por salto mantém um registro reduzido, de valor único: predicados no formato de lista como containsAny ou unique só fazem sentido no mapa completo de cabeçalhos da resposta final, então se aplicam lá e não por salto. As duas coleções significam coisas diferentes. requests é a cadeia inteira incluindo a resposta final que respondeu, então nunca fica vazia mesmo para um 200 direto, enquanto redirects é só os saltos seguidos no caminho até lá, vazia quando nada redirecionou.
Escopos de elemento: campos dentro de um item de coleção
Um escopo de elemento é o conjunto de campos disponível em UM item de uma coleção - depois de indexar nele (requests[0]) ou enquanto o filtra com where(current. ...) (veja a próxima seção). Seis coleções carregam o próprio escopo de elemento: as quatro coleções de elementos HTML compartilham um formato, e requests/redirects compartilham o formato de sujeitos de salto documentado logo acima.
| Escopo de elemento | Como é um item |
|---|---|
body.html.path | Um elemento encontrado por uma consulta CSS body.html.path("selector"). |
body.html.a | Um elemento <a> de body.html.a. |
body.html.script | Um elemento <script> de body.html.script. |
body.html.link | Um elemento <link> de body.html.link. |
requests | Uma requisição na cadeia completa (veja a tabela de sujeitos de salto acima). |
redirects | Um salto de redirecionamento seguido (os mesmos campos de requests, veja acima). |
O formato compartilhado para body.html.path(...), body.html.a, body.html.script e body.html.link - uma linha por link, tag de script ou elemento <link>:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
url | O alvo do link exatamente como o HTML escreve. | texto | body.html.a.url contains "/checkout" |
text | O texto visível do elemento. | texto | body.html.a.text contains "Sign in" |
absolute | O alvo do link resolvido contra a URL da página em um endereço absoluto - uma lista de urls, com as partes da url disponíveis por elemento (.host, .path, .port, .query, .scheme). | url | body.html.a.absolute.scheme in ["https"] |
rel | O atributo rel do elemento. | texto | body.html.a.where(current.rel eq "nofollow").count eq 0 |
absolute.host | A parte de host da URL. | texto | body.html.a.absolute.host.unique.count le 3 |
absolute.port | A parte de porta da URL. | número | body.html.a.absolute.port in [443] |
absolute.path | A parte de caminho da URL. | texto | body.html.a.absolute.path startsWith "/" |
absolute.query | A string de consulta da URL. | texto | body.html.a.absolute.query not contains "session" |
absolute.scheme | O esquema da URL (http ou https). | texto | body.html.a.absolute.scheme in ["https"] |
Dois padrões se aplicam antes de você escrever uma regra sobre essas coleções. Uma menção simples de body.html.a (ou .script/.link) significa a projeção .url dela, então body.html.a.count gt 0 conta hrefs, e uma regra salva é lida de volta com .url escrito por extenso, porque uma regra salva sempre diz exatamente o que avalia. E .url é o atributo href bruto exatamente como o HTML o escreveu, então um link relativo continua relativo; .absolute é o mesmo link resolvido contra a própria URL da página, o que é o que você quer ao verificar o esquema ou o host de links de saída (body.html.a.absolute.scheme in ["https"]).
Operadores
A metade de predicado de toda regra: qual teste rodar contra o sujeito. Os 15 são compartilhados por todo tipo de verificação, e quais deles se encaixam em um dado sujeito depende do tipo dele (um código de status aceita lt/gt, um corpo aceita contains, uma coleção aceita exists/unique/in).
| Nome | O que é | Se aplica a | Exemplo |
|---|---|---|---|
eq | Igual a. Contra um literal json("…") / xml("…") / yaml("…") é uma correspondência estrutural EXATA: mesmas chaves (em qualquer ordem), arrays na mesma ordem, mesmos valores. | qualquer tipo | body.json eq json("{\"ok\": true}") |
lt | Menor que. | números | time lt 2000 |
le | Menor ou igual a. | números | cert.days.left le 30 |
gt | Maior que. | números | body.size gt 0 |
ge | Maior ou igual a. | números | status ge 500 |
contains | Contém o texto - sobre uma lista, passa quando o valor É um dos itens (correspondência exata; use matches para buscar dentro dos itens). Contra um literal json("…") / xml("…") / yaml("…") é uma CONTENÇÃO estrutural: tudo o que o literal declara precisa estar presente e bater; a resposta pode ter mais. | texto ou lista | body.json contains json("{\"status\": \"ok\"}") |
startsWith | Começa com o texto - sobre uma lista, quando QUALQUER item começa. | texto | url.path startsWith "/api" |
endsWith | Termina com o texto - sobre uma lista, quando QUALQUER item termina. | texto | url.path endsWith ".json" |
matches | Bate com a expressão regular em algum ponto do texto - sobre uma lista, quando QUALQUER item bate. | texto | body matches "order-\\d+" |
containsAny | Contém pelo menos um dos valores listados (sobre uma lista: algum item É IGUAL a um deles). | lista | body containsAny ["In stock", "Pre-order"] |
containsAll | Contém todos os valores listados (sobre uma lista: cada valor é igual a algum item - as testemunhas podem ser diferentes). | lista | body.html.a.text containsAll ["Home", "Contact"] |
in | É um dos valores ou intervalos listados - sobre uma lista, todo item é. | valor(es) ou intervalo | status in [200, 301, 302] |
exists | O sujeito está presente. | qualquer sujeito | header("ETag") exists |
isNumber | O valor pode ser lido como número. | texto ou qualquer | bind("id") isNumber |
unique | A lista não tem duplicatas. | lista | dns.ips unique |
Dois operadores significam algo mais restrito do que parecem. contains sobre uma lista é associação exata: o valor precisa ser igual a um item inteiro, não aparecer como substring dentro de um, então recorra a matches quando quiser comportamento de substring pelos elementos de uma coleção. E eq contra um literal json(...)/xml(...)/yaml(...) é uma correspondência estrutural completa (mesmas chaves, arrays na mesma ordem, mesmos valores), enquanto contains contra o mesmo tipo de literal é contenção estrutural: tudo o que o literal declara precisa estar presente, mas a resposta real pode carregar mais.
Redutores
Um redutor reduz uma coleção a um único valor e só pode aparecer no fim de uma cadeia. Os exemplos abaixo usam requests.status, a coleção naturalmente numérica que os sujeitos HTTP formam, como ilustração; os mesmos oito redutores funcionam sobre qualquer coleção numérica em qualquer tipo de verificação (os tempos de ida e volta de uma verificação Ping, um conjunto filtrado de linhas de banco de dados).
| Nome | O que reduz | Se aplica a | Exemplo |
|---|---|---|---|
count | Quantos itens a lista tem. | qualquer coleção | requests.count le 2 |
min | O menor número da lista. | coleção numérica | requests.status.min ge 200 |
max | O maior número da lista. | coleção numérica | requests.status.max lt 500 |
sum | A soma dos números da lista. | coleção numérica | requests.status.sum gt 0 |
avg | A média dos números da lista. | coleção numérica | requests.status.avg lt 300 |
first | O primeiro item da lista. | qualquer coleção | redirects.status.first eq 301 |
last | O último item da lista. | qualquer coleção | requests.status.last eq status |
unique | A lista sem duplicatas. | qualquer coleção | dns.ips.unique.count le 3 |
unique é sobrecarregado, e a grafia distingue os dois sentidos. Escrito como operador sem ponto (x unique) é um predicado, "essa coleção não tem duplicatas", e falha nomeando a repetição. Escrito como redutor com ponto (x.unique) é uma transformação, a própria coleção deduplicada, que ainda precisa de algo depois (x.unique.count eq 1). Um x.unique solto sem nada depois é um erro de sintaxe, porque o motor não consegue adivinhar qual dos dois sentidos você quis.
Açúcar sintático
Os predicados de açúcar sintático são atalhos que o motor expande em predicados centrais comuns antes de a regra ser enviada a um agente - um predicado de açúcar não custa nada a mais para adicionar (nenhum pacote de agente, nenhum piso de versão) porque, quando chega na rede, já parece uma regra comum. Prefira o açúcar sintático sempre que existir: ele se lê melhor, e é exatamente equivalente a escrever a forma longa na mão.
| Nome | O que significa | Se aplica a | Exemplo |
|---|---|---|---|
isOk | O status é um código de sucesso (200-299). | status | - |
isRedirect | O status é um código de redirecionamento (300-399). | status | status isRedirect |
isClientError | O status é um erro de cliente (400-499). | status | status isClientError |
isServerError | O status é um erro de servidor (500-599). | status | status isServerError |
isJson | O conteúdo realmente é JSON. | documento ou texto de tipo de mídia | header("Content-Type") isJson |
isXml | O conteúdo realmente é XML - o corpo é interpretado como XML, ou um cabeçalho nomeia um tipo de mídia XML. | documento ou texto de tipo de mídia | body isXml |
isHtml | O conteúdo realmente é HTML - o corpo é interpretado como HTML, ou um cabeçalho nomeia um tipo de mídia HTML. | documento ou texto de tipo de mídia | body isHtml |
isForm | Um tipo de mídia nomeia uma codificação de formulário: application/x-www-form-urlencoded ou multipart/form-data. Diferente de isJson/isXml/isHtml, não há um namespace de corpo correspondente, então isso só se aplica a um valor de tipo de mídia, como um cabeçalho Content-Type. | somente texto de tipo de mídia | header("Content-Type") isForm |
isEmpty | Nada ali: um texto vazio, um tamanho zero ou uma lista vazia. | texto, tamanho ou lista | body isEmpty |
isNull | O valor é nulo. | qualquer valor | body.json.path("$.deletedAt") isNull |
absent | O sujeito não está presente de forma alguma. | qualquer sujeito | header("X-Debug") absent |
between | Um número dentro de um intervalo inclusivo. | números (2 operandos) | body.size between 50 and 500kb |
isJson/isXml/isHtml são sensíveis ao contexto de propósito, e o que você escreve determina qual sentido se aplica. Escritos sobre o próprio documento (body isJson) significam "isso é interpretável nesse formato", o mesmo que body.json exists. Escritos sobre um valor de texto que nomeia um tipo de mídia, como um cabeçalho (header("Content-Type") isJson), significam "isso nomeia a família MIME desse formato"; veja Famílias MIME abaixo para quais tipos de mídia se qualificam. isForm só tem o segundo sentido, já que não existe um namespace body.form para interpretar, então body isForm é um erro estático em vez de uma regra que nunca poderia ser verdadeira.
O filtro where(...)
Mantém só os elementos que combinam, e continua a partir daí. É o único mecanismo de filtragem da linguagem, e tem exatamente um formato: where(current.<campo> <condição> <valor>).
Filtrar é diferente de projetar: requests.url contains "cart" pergunta se tal salto existe em algum ponto da cadeia, enquanto requests.where(current.url contains "cart").status pergunta o que aquele salto devolveu. Filtrar não reduz a lista, então termine com .first, uma verificação in [...], ou .count. Vai só um nível, e recebe exatamente uma condição.
| Parte | O que nomeia | Notas |
|---|---|---|
current.<campo> | Um campo de cada elemento sendo filtrado, escrito depois de current. | Essa é a metade que as pessoas erram: current.url é a URL do salto individual, não a da resposta final. Só os campos próprios do elemento podem vir depois de current.. |
| a condição | Qualquer predicado comum, incluindo not e nocase | Qualquer condição que funciona no nível superior de uma regra também funciona aqui. |
| o valor | Contra o que o campo de cada elemento é comparado | Geralmente um valor simples. Um sujeito escrito aqui é lido da resposta EXTERNA, não do elemento - where(current.url eq url.original) compara cada salto contra a URL com que a verificação foi configurada, e é por isso que o lado do elemento precisa dizer current. explicitamente. |
Exemplo: requests.where(current.url contains "cart").status.first eq 301 - mantém só os saltos cuja URL contém "cart", depois olha o status do primeiro que combinou.
Mais dois limites, ambos aplicados pelo analisador com a própria mensagem: where não pode ser aninhado dentro de outro where, e o argumento dele é exatamente uma condição, sem and/or dentro. Só se aplica a uma coleção cujos elementos carregam campos nomeados (requests, body.html.a), não a uma lista projetada simples como dns.ips, onde não há nada para current. nomear.
Referência de sintaxe
Tudo o mais que a gramática define: como nomear uma regra, como escrever intervalos e listas, o que um sujeito solto significa, e as pequenas formas de pontuação que aparecem em várias regras.
| Forma | O que faz | Tipo | Exemplo |
|---|---|---|---|
where | Mantém só os elementos que combinam, e continua a partir daí. | filtro de coleção | requests.where(current.url contains "cart").status.first eq 301 |
not | Inverte a condição que segue. | sinalizador | body not contains "error" |
nocase | Compara texto sem diferenciar maiúsculas de minúsculas. | sinalizador | body contains "welcome" nocase |
current | Dentro de where(…), nomeia o único elemento sendo filtrado. | referência de elemento (dentro de where) | requests.where(current.status eq 301) |
range | Um intervalo de números, com AMBAS as pontas INCLUÍDAS. | intervalo numérico | status in [200..299] |
list | Uma lista de valores para comparar. | lista de valores | status in [200, 301, 302] |
docLiteral | Um valor de documento tipado para comparação estrutural: o texto entre aspas é interpretado como JSON, XML ou YAML quando a regra é salva. | texto json/xml/yaml | body.json contains json("{\"user\": {\"active\": true}}") |
implicitExists | Uma regra que nomeia só um sujeito verifica que ele está presente: escrever apenas body.json salva como body.json exists. | linha de sujeito solto | body.json |
index | Escolhe UM item de uma lista pela posição, contando a partir de 0. | inteiro de base 0 | requests[0].status |
label | Um nome opcional para a regra, escrito antes de dois-pontos. | nome antes de dois-pontos | "json ok": body.json exists |
comment | Tudo depois de # é uma nota para você mesmo; não afeta a verificação. | texto # no final | status isOk # the happy path |
Alguns valem uma passagem em português claro. label dá um nome à regra que aparece no alerta em vez da expressão renderizada; escreva-o antes de dois-pontos, como em "json ok": body.json exists. implicitExists significa que uma linha que nomeia só um sujeito e nenhum predicado é um atalho para exists: escrever body.json salva como body.json exists, e reabrir a regra mostra a forma por extenso. range e list são as duas formas que um valor pode ter depois de in: um intervalo ([200..299], com ambas as pontas incluídas) ou uma lista explícita ([200, 301, 302]), e um valor pode ficar em aberto de qualquer lado ([400..]). docLiteral é o wrapper json(...)/xml(...)/yaml(...) usado para comparação estrutural contra o corpo (coberto em Operadores acima e nas regras prontas abaixo). index escolhe um item de uma coleção pela posição, com base 0, da mesma forma que bind[0] lê uma captura posicional. current só tem sentido dentro de um filtro where(...), coberto na própria seção acima.
Wrappers: previous, delta e delta2
Três formas que olham para trás em vez de só para a resposta atual - cada uma restrita a planos com asserções com estado, e cada uma explicada por completo em "Comparando com a verificação anterior" abaixo.
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
delta (exige um plano com asserções com estado) | Quanto um valor numérico mudou desde a verificação anterior - opcionalmente como uma taxa por ms/s/m/h. | número | delta(body.size, h) lt 1mb |
delta2 (exige um plano com asserções com estado) | A mudança da mudança - um valor está acelerando? | número | delta2(time) gt 0 |
previous (exige um plano com asserções com estado) | O valor que esse sujeito tinha na verificação anterior. | qualquer | status eq previous.status |
Sinalizadores: not e nocase
Dois modificadores que se anexam a uma regra em vez de serem sujeitos ou predicados por conta própria.
| Sinalizador | O que faz | Tipo | Exemplo |
|---|---|---|---|
not | Inverte a condição que segue. | sinalizador (se anexa a uma regra) | body not contains "error" |
nocase | Compara texto sem diferenciar maiúsculas de minúsculas. | sinalizador (se anexa a uma regra) | body contains "welcome" nocase |
not se combina com o predicado que segue em vez de negar a regra inteira como unidade - x not != y se lê como x eq y, não como dupla negação. Quando um sujeito pode estar totalmente ausente, prefira o açúcar sintático absent a not exists: os dois significam exatamente a mesma coisa, mas absent diz isso diretamente. nocase só muda alguma coisa em uma comparação genuinamente textual; o editor (e esta referência) ainda deixam você escrevê-lo em qualquer lugar, mas ele é silenciosamente sem efeito em um teste numérico como status eq 200 nocase.
Famílias MIME
As tabelas de consulta por trás de isJson, isXml, isHtml e isForm quando aplicados a um valor de tipo de mídia, como um cabeçalho. Cada família combina com o tipo de mídia de nível superior óbvio mais, para JSON e XML, qualquer tipo que termine no sufixo de sintaxe estruturada correspondente - o que faz header("Content-Type") isJson passar corretamente em application/problem+json ou application/vnd.api+json e não só no simples application/json.
| Família | Combina com | Açúcar correspondente | Exemplo |
|---|---|---|---|
json | application/json, text/json, ou qualquer tipo de mídia terminado em +json (application/problem+json, application/vnd.api+json, application/ld+json, ...). | açúcar: isJson | header("Content-Type") isJson |
xml | application/xml, text/xml, ou qualquer tipo de mídia terminado em +xml (image/svg+xml, application/atom+xml, ...). | açúcar: isXml | header("Content-Type") isXml |
html | text/html ou application/xhtml+xml. | açúcar: isHtml | header("Content-Type") isHtml |
form | application/x-www-form-urlencoded ou multipart/form-data. | açúcar: isForm | header("Content-Type") isForm |
A correspondência ignora tudo a partir do primeiro ; em diante (então application/json; charset=utf-8 ainda combina) e não diferencia maiúsculas de minúsculas.
Sujeitos para verificações de banco de dados, counter, SNMP, porta e ping
Todo operador, redutor, atalho de açúcar sintático e forma de sintaxe acima é idêntico para esses cinco tipos de verificação: o motor registra os mesmos 15 operadores, 8 redutores, 12 predicados de açúcar e 11 formas de sintaxe para todos os seis tipos sem exceção. O que muda por tipo é a lista de sujeitos. Cada tipo expõe um pequeno conjunto de sujeitos exclusivos do que mede, mais um subconjunto dos sujeitos de rede/tempo/TLS já documentados acima, com o significado se adaptando ao tipo (o time de uma verificação de Database é conexão-mais-consulta em vez de conexão-mais-TLS-mais-download, já que não há uma resposta HTTP para baixar).
Verificações de banco de dados
Compartilha time, time.connect e time.dns com os sujeitos documentados acima (com o escopo redefinido para uma conexão de banco de dados: conexão-mais-consulta, resolução DNS do host do banco). Exclusivos das verificações de banco de dados:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
scalar | O valor único que a consulta devolveu (modo Scalar). | qualquer | - |
rows | As linhas que a consulta afetou ou devolveu (modo NonQuery). | coleção | - |
time.query | Tempo que a própria consulta levou. | número | - |
Um exemplo pronto está na próxima seção: use rows.count para verificar quantas linhas uma consulta afetou ou devolveu, e scalar para verificar diretamente um único valor devolvido.
Verificações de counter
Compartilha time com os sujeitos documentados acima - como campo em status candidato especificamente para verificações de Counter (tempo de ida e volta da requisição do counter; veja a seção Honestidade para o que "candidato" significa). Exclusivo das verificações de counter:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
value | O valor medido do counter. | número | - |
Verificações SNMP
Compartilha time e time.dns com os sujeitos documentados acima (resolução do nome de host mais a própria requisição SNMP). Exclusivos das verificações SNMP:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
time.request | Tempo que a requisição SNMP levou. | número | - |
value | O valor que o OID devolveu. | qualquer | - |
value.type (candidato - em rollout para os agentes) | O nome do tipo de dado SNMP do valor devolvido. | texto | - |
value.type está em status candidato; veja a seção Honestidade. Nota sobre disponibilidade: o interruptor de Validação de Resposta do modo de asserções ainda não chegou ao editor de monitor SNMP. Ele mostra um painel "Em breve" nomeando esses dois sujeitos em vez de uma lista de regras funcional. Os sujeitos e o avaliador por baixo já estão registrados; só a interface do editor SNMP está pendente.
Verificações de porta
A maior lista compartilhada de qualquer tipo não-HTTP. Uma verificação de porta TCP carrega essencialmente os mesmos sujeitos de conexão, DNS, TLS e certificado que uma verificação HTTP, já que uma verificação de porta também pode negociar TLS: bind, cert e seus seis subcampos, conn e seus quatro subcampos, dns e seus dois subcampos, time/time.connect/time.dns/time.tls, e tls/tls.cipher/tls.protocol - todos documentados nas seções acima, com os mesmos significados. Exclusivos das verificações de porta:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
banner | Os dados lidos do socket depois de conectar. | texto | - |
banner.hash (candidato - em rollout para os agentes) | Um resumo (digest) do banner - compare com previous.banner.hash para detectar mudanças de serviço. | texto | - |
banner.regex | Combina o texto com uma expressão regular e pega o que foi capturado. | texto | body.regex("order-(?<id>\\d+)") exists |
banner.size (candidato - em rollout para os agentes) | O tamanho do banner, em bytes. | número | - |
banner.hash e banner.size estão em status candidato - veja a seção Honestidade. banner.regex já está disponível hoje e funciona exatamente como body.regex(...) em uma verificação HTTP: capturas nomeadas alimentam o mesmo namespace bind(...).
Verificações de ping
Compartilha os sujeitos de conexão e DNS com as seções acima: conn, conn.failed, conn.failedIps, conn.ip, conn.ip.family, dns, dns.ips, dns.server, time (aqui, o tempo médio de ida e volta das respostas bem-sucedidas) e time.dns. Exclusivos das verificações de ping:
| Nome | O que é | Tipo/valores | Exemplo |
|---|---|---|---|
loss | A porcentagem de pedidos de eco que não obtiveram resposta. | número | loss eq 0 |
reply | As respostas de eco bem-sucedidas. | coleção | - |
sentCount (candidato - em rollout para os agentes) | Quantos pedidos de eco foram enviados. | número | - |
time.max | O tempo de ida e volta da resposta mais lenta. | número | - |
time.min | O tempo de ida e volta da resposta mais rápida. | número | - |
ttl | O TTL da primeira resposta bem-sucedida - compare com previous.ttl para notar mudanças de rota. | número | - |
sentCount está em status candidato - veja a seção Honestidade. ttl vale a pena conhecer mesmo fora de uma regra estrita de aprovado/reprovado: combiná-lo com previous.ttl (veja Wrappers acima) sinaliza uma mudança de rota entre verificações, já que o tempo de vida de um pacote na chegada reflete quantos saltos ele atravessou.
Regras que as pessoas realmente querem escrever
A página está no ar e realmente diz a coisa certa
Um código de status sozinho não consegue dizer se uma página renderizou corretamente - uma resposta 200 com uma casca vazia é a clássica falha silenciosa que uma verificação só de status não pega.
status isOk
body contains "Add to cart"
Uma API responde com JSON e o campo esperado
Verifique se o endpoint ainda fala JSON, depois busque dentro dele. A primeira linha pega uma página de erro em HTML servida onde deveria haver JSON, um formato comum de indisponibilidade atrás de um proxy; a segunda verifica a própria saúde reportada pela API, não só o status de transporte.
body isJson
body.json.path("$.status") eq "ok"
A resposta ficou mais lenta do que deveria
Detalhe quando você precisa saber o que corrigir e não só que algo está lento - time.connect, time.tls, time.dns e time.head separam tempo de rede, de handshake, de resolvedor e de aplicação.
time lt 2s
Um redirecionamento enviou visitantes para fora do seu domínio
Compara onde a verificação terminou contra a URL que você configurou - falha no momento em que uma cadeia de redirecionamento, sequestrada, mal configurada, ou apenas mudada por uma implantação, chega a algum lugar que você não pretendia.
url.host eq url.original.host
A página mudou desde a última verificação
Útil em conteúdo que deveria ficar estável entre verificações - preços, termos, uma política publicada - e também funciona como um sinal básico de desfiguração (defacement).
previous.body.hash eq body.hash
Um número dentro de um intervalo, escrito da forma curta
Pega tanto uma página reduzida demais quanto uma descontrolada em uma única regra, sem escrever um intervalo explícito.
body.size between 50 and 500kb
Um certificado prestes a vencer
A verificação TLS mais comum de todas, e uma que um monitor simples de no-ar/fora-do-ar não consegue expressar de jeito nenhum - um certificado que ainda é válido hoje mas vence semana que vem não dá nenhum outro sinal de aviso. Combine com cert.issuer se você também quiser pegar um certificado emitido silenciosamente pela autoridade errada.
cert.days.left gt 14
Uma consulta de banco de dados devolvendo o número errado de linhas
Em uma verificação de Database, rows é a coleção que uma consulta afetou ou devolveu - contá-la pega uma consulta que deveria devolver exatamente um registro de conta silenciosamente começando a devolver zero (apagado, ou um join quebrado) ou mais de um (uma duplicata que não deveria existir).
rows.count eq 1
Um valor SNMP saindo da faixa
Um dispositivo SNMP que responde não é a mesma coisa que um saudável - um OID monitorado (uso de disco, profundidade de fila, temperatura) pode subir bem além de um limite seguro enquanto o dispositivo em si continua perfeitamente alcançável. Comparar o value consultado contra uma faixa pega o que uma verificação simples de alcançabilidade não consegue.
value lt 90
Um serviço TCP respondendo com o banner errado
Uma porta que aceita conexões não é a mesma coisa que o serviço certo escutando nela - um processo travado, um proxy mal configurado, ou um serviço rebaixado/substituído ainda podem completar um handshake TCP. Ler o texto de saudação que um serviço envia logo após conectar (um banner de SMTP, FTP ou similar) pega o que uma verificação simples de porta aberta não consegue.
banner contains "220"
Comparando com a verificação anterior
Um punhado de sujeitos olha para trás em vez de só para a resposta atual: coloque previous. na frente de um sujeito para ler o que ele era na última verificação, ou envolva-o em delta(...) para obter a diferença entre antes e agora, ou em delta2(...) para obter a mudança dessa mudança - útil para identificar um valor que está acelerando em vez de apenas variando (um tempo de resposta que sobe mais rápido a cada verificação). previous.body.hash eq body.hash acima é exatamente isso - "a impressão digital do corpo bate com o que era da última vez". delta(body.size, h) lê a mudança como uma taxa por hora em vez de uma diferença bruta, para valores que você espera que cresçam de forma constante em vez de saltar.
Na primeira vez que uma regra assim roda, ela não tem nada para comparar, então é pulada em vez de falhar: a verificação é marcada como "aquecendo", não quebrada, e adicionar a regra não gera nenhum alerta falso. O aquecimento só se aplica quando a leitura atual é válida e falta a linha de base. Se a própria leitura atual falhar (digamos, o corpo não é JSON válido dessa vez), a regra falha exatamente como a versão dela sem previous. falharia. Uma regra assim também precisa que o valor mude entre verificações, o que a torna sem sentido em um método de verificação que nunca avança de estado, por exemplo uma requisição HEAD.
Comparar com a verificação anterior exige um plano de nível mais alto; sem ele, esses sujeitos aparecem esmaecidos no editor com uma explicação.
Limites, e o que está deliberadamente faltando
Quantas regras você pode adicionar depende do seu plano, mostrado como um contador ao vivo ao lado de "Adicionar regra". O motor também aplica um teto absoluto em toda verificação independentemente do plano, uma salvaguarda contra abuso e não um limite para o uso normal: uma verificação com um número de regras perto desse teto já seria incomumente grande.
Não há como escrever JavaScript personalizado para uma regra, e nunca haverá. Toda regra é construída a partir de um vocabulário fixo e nomeado de sujeitos e predicados em vez de um sandbox de script aberto, o que mantém uma regra legível à primeira vista e segura para rodar em todo agente de monitoramento do mundo.
Nem toda regra funciona em todo lugar no momento em que é escrita: algumas condições mais novas precisam de uma versão recente do agente de monitoramento que roda sua verificação, então uma capacidade nova leva tempo para chegar a toda verificação da sua conta conforme os agentes se atualizam em segundo plano. Regras construídas sobre o núcleo estável da linguagem não são afetadas.
Um punhado de entradas nesta referência ainda não está totalmente disponível, e cada uma está identificada na tabela correspondente acima:
- Reservado (declarado, ainda não populado por nenhum agente):
ttfb,httpVersion,cert.subject. - Candidato (já em rollout, ainda não em todo agente):
conn.ip.familyeconn.failedIpsem verificações HTTP, de porta e ping,value.typeem verificações SNMP,banner.hashebanner.sizeem verificações de porta,sentCountem verificações de ping, e o própriotimeda verificação de Counter. - Ainda não disponível:
steps, reservado para um futuro tipo de verificação em várias etapas. - Exige um plano com asserções com estado: toda a família de wrappers
previous/delta/delta2, em todo tipo de verificação.
Tudo o mais nesta referência já está disponível hoje em todo plano que tem o modo de asserções.
Onde o modo de asserções funciona hoje
O interruptor de Validação de Resposta para o modo de asserções aparece em monitores HTTP (site) e API, que compartilham o mesmo editor de regras e sintaxe. A mesma linguagem e o mesmo avaliador já rodam por baixo das verificações de Database, Counter, Port, Ping e SNMP no nível de protocolo: o registro acima serve os seis tipos de verificação, e uma regra salva para um deles se lê da mesma forma se o modo chegar ao editor de outro tipo mais tarde.
O SNMP mostra o preview mais claro: o editor dele já tem um painel de regras de asserção nomeando value e value.type, rotulado "Em breve", sem nenhuma lista de regras funcional por trás ainda. As verificações de Database, Counter e Ping não mostram nenhum painel de modo de asserções, mesmo que os sujeitos delas estejam igualmente disponíveis no motor por baixo.
Configurando uma verificação de verdade
Se você está validando uma API REST em vez de uma página web simples, comece pela validação de resposta de API, que cobre o uptime, o tempo de resposta e o corpo da sua própria API juntos. Para uma página ou site que precisa continuar no ar e respondendo corretamente de todo lugar onde seus usuários estão, o monitoramento global de uptime a partir de mais de 300 localidades é o panorama mais amplo em que o modo de asserções se encaixa. Para configurar regras por código em vez de pelo painel, a própria API v2 da HostTracker cria e atualiza as regras de asserção de um monitor da mesma forma que o editor faz. Para a regra de vencimento de certificado acima e todo o resto de TLS, o monitoramento de domínio e certificado TLS cobre o tipo de verificação em que cert.days.left e os outros sujeitos de TLS vivem. Para ver uma regra sendo avaliada agora contra uma URL real, sem conta, use a ferramenta gratuita de verificação HTTP. Para os códigos de status contra os quais o sujeito status compara, comece por 200 OK, e os guias de monitoramento cobrem como configurar cada tipo de verificação sob o qual essa linguagem roda.
Perguntas frequentes
O que acontece com minhas configurações antigas de código de status e palavra-chave se eu ativar o modo de asserções?
Elas são substituídas pela lista de regras enquanto o modo está ativo. Desativá-lo de volta antes de salvar restaura os campos clássicos exatamente como estavam: nada é apagado, os dois modos simplesmente não podem estar ativos ao mesmo tempo.
Posso combinar várias condições em um monitor?
Sim: toda regra na lista precisa passar. Ainda não existe um "OU" entre regras separadas, então, para aceitar um entre vários valores, use uma única regra com in [...] ou containsAny [...].
O modo de asserções algum dia vai deixar eu escrever meu próprio script?
Não. Toda regra é composta a partir do conjunto fixo de sujeitos e predicados da linguagem. Não há JavaScript personalizado, por design.
O que acontece na primeira vez que eu adiciono uma regra que compara com a verificação anterior?
Ainda não há nada para comparar, então ela é marcada como aquecendo e é pulada em vez de falhar. Adicionar uma regra de "isso mudou" nunca gera um alerta falso por conta própria.
Eu preciso de um plano específico para usar o modo de asserções?
O modo em si e as regras do dia a dia (status, corpo, cabeçalhos, tempo, redirecionamentos) estão amplamente disponíveis; quantas regras você pode adicionar de uma vez depende do seu plano e é mostrado ao vivo no editor. Regras que comparam com uma verificação anterior (previous, delta, delta2) exigem um plano de nível mais alto e aparecem esmaecidas com uma explicação.
O modo de asserções funciona em monitores de API da mesma forma que em monitores de site?
Sim. Monitores HTTP e API compartilham o mesmo editor de regras, sujeitos e predicados, e uma regra escrita para um deles se lê de forma idêntica no outro.
O que o where(...) realmente faz, e quando eu preciso dele?
Ele filtra uma coleção até os elementos que combinam com uma condição antes de você ler um campo do resultado. Use quando uma projeção simples como requests.status não é específica o suficiente e você precisa de um salto, link ou elemento em particular, em vez da coleção inteira (veja a seção acima).
Posso escrever uma regra contra uma consulta de banco de dados, um valor SNMP, um banner de porta ou um resultado de ping hoje?
A linguagem e o avaliador suportam todos eles, e as tabelas de sujeitos acima cobrem cada um. O editor de regras não: só monitores HTTP e API mostram o interruptor de Validação de Resposta hoje. O SNMP mostra um preview "Em breve" dos dois sujeitos dele, e Database, Counter e Ping não mostram nenhum painel de modo de asserções.
Por que alguns sujeitos nesta referência dizem "reservado" ou "candidato" em vez de simplesmente serem listados normalmente?
"Reservado" significa que o campo está declarado no registro mas nenhum agente ainda o popula; "candidato" significa que está em rollout para os agentes mas ainda não chegou a todos. Os dois são identificados em todo lugar onde aparecem nesta referência e na lista-resumo na seção Limites acima.