Режим правил: повний довідник перевірки відповіді
Режим правил (assertion mode) замінює фіксовані поля успіху/невдачі монітора списком правил, які ви пишете самі, і кожне правило називає точно те, що має бути істинним у відповіді. Більшість моніторів аптайму оцінюють перевірку жменькою фіксованих полів: код стану, що вважається "лежить", список статусів, які треба ігнорувати, можливо ключове слово, що має десь з'явитися в тілі. Ці поля не можуть виразити API, що законно відповідає 404 на відсутній ресурс, сторінку, що повертає 200 із порожньою оболонкою, бо база даних відповіла з таймаутом, чи ланцюжок переспрямувань, що починає вести через чужий домен.
Режим assertion mode у HostTracker замінює ці фіксовані поля невеликою мовою правил, яку ви пишете самі, правило за правилом, прямо в редакторі монітора. Кожне правило точно каже, що має бути істинним у відповіді: статус, частина тіла, заголовок, скільки часу це зайняло, куди привело переспрямування. Перевірка провалюється лише тоді, коли провалюється одне з ваших правил. Це та сама мова для сайту, REST API, запиту до бази даних, TCP-порту, цілі Ping, лічильника SNMP чи загальної перевірки Counter: один набір суб'єктів, один набір предикатів, що використовуються всюди, де є цей режим. Цей посібник охоплює кожен суб'єкт, оператор, редюсер, sugar-скорочення і синтаксичну форму, які реалізує рушій.
Що замінює режим правил
Класичні поля Response Validation нікуди не діваються, коли режим правил вимкнено: очікуваний діапазон статусу, список статусів для ігнорування, ключове слово, яке має (чи не має) з'явитися. Режим - це перемикач, що міняє цей фіксований набір на список правил, які ви будуєте самі, а вимкнення його назад перед збереженням повертає класичні поля на місце. Жоден монітор не прив'язаний до одного режиму назавжди.
Одна мова замість купи гаджетів під кожен тип складається природно. Перевірка "має бути JSON і містити поле", перевірка "має все ще казати Add to cart" і перевірка "не мала стати повільнішою" - це три правила в одному синтаксисі, в одному списку, кожне проходить чи провалюється саме по собі.
Як увімкнути
Режим правил живе всередині розділу Response Validation редактора монітора, для HTTP (сайт) і API моніторів. Перемкніть перемикач, і класичні поля замінить пронумерований список правил із кнопкою "Add rule" і живим лічильником, що показує, скільки правил ви використали відносно ліміту вашого тарифу.

Кожне правило перевіряється, поки ви його будуєте: ще не завершене правило має окремий стан "незавершено", а правило, яке редактор може оцінити, позначається як завершене. Кожне правило також має маленьку кнопку </>, що відкриває його форму звичайного текстового джерела, тож ви можете прочитати чи скопіювати точний вираз, а не лише переглядати покроковий вигляд.
Ментальна модель: суб'єкт, предикат, значення
Кожне правило має однакову форму: суб'єкт (код стану, тіло, заголовок, час відповіді), предикат (дорівнює, містить, існує, менше за) і, для більшості предикатів, значення, з яким порівнювати. status eq 200 - це суб'єкт, предикат і значення; body.json exists - це суб'єкт і предикат без значення, бо "exists" більше нічого не потребує.
Побудова правила в редакторі починається з вибору того, що перевіряти, потім умови, потім значення:

Правила в списку поєднуються через AND: перевірка провалюється, коли провалюється хоч одне правило, і проходить, лише коли проходять усі. Поки що немає OR, тож щоб прийняти один із кількох статусів чи рядків, вираз це всередині одного правила (status in [200, 301, 302], body containsAny ["In stock", "Pre-order"]). Правило, що провалилося, називає себе у сповіщенні, тож дайте кожному коротку мітку, де можете, і сповіщення скаже, яке саме очікування зламалося.
Що можна перевіряти
Селектор групує суб'єкти на власний документ відповіді (тіло, заголовки) і її транспорт (статус, час, переспрямування, TLS). Кілька найважливіших суб'єктів, а повний список - у довіднику далі:
| Суб'єкт | Що це | Приклад |
|---|---|---|
status | Код стану HTTP фінальної відповіді, після переспрямувань | status isOk |
body | Тіло відповіді як звичайний текст | body contains "Add to cart" |
body.json / body.xml / body.html / body.yaml | Тіло, але лише коли воно справді розбирається як цей формат - інакше суб'єкт просто відсутній | body.json exists |
body.json.path("$.a") | Запит JSONPath до тіла JSON (та сама мова запитів працює і над YAML, бо YAML розбирається в ту саму об'єктну модель) | body.json.path("$.status") eq "ok" |
body.size / body.hash | Розмір відповіді в байтах і відбиток вмісту тіла | body.size gt 1kb |
header("Name") | Один заголовок відповіді, за назвою | header("Content-Type") isJson |
time та time.connect / time.tls / time.dns / time.head | Загальний час відповіді, і його мережева, TLS-рукостискальна, DNS-фаза та фаза очікування сервера | time lt 2s |
redirects / requests | Кроки, за якими пройшла перевірка, і весь ланцюжок (включно з фінальною відповіддю) | redirects.count eq 0 |
url та його частини (.host, .scheme, .path...) | Фінальна URL, на якій зупинилася перевірка | url.scheme eq "https" |
cert.days.left | Днів до закінчення терміну дії TLS-сертифіката | cert.days.left gt 14 |
Числа приймають суфікси одиниць, тож вам ніколи не доведеться конвертувати вручну: 2s означає 2000 мілісекунд, 1kb означає 1024 байти. Текстові порівняння чутливі до регістру, якщо ви не додасте до правила nocase.
Повний довідник
Далі - кожен суб'єкт, оператор, редюсер, sugar-скорочення, фільтр і синтаксична форма, які рушій assertion реєструє для HTTP і API перевірок, узяті прямо з власного реєстру рушія (тих самих даних, що живлять селектори редактора правил і його документацію). Записи, які ще не доступні всюди, мають примітку в дужках: зарезервовані поля, які рушій ще не почав наповнювати, кандидати, що все ще розкочуються на агентів, і stateful-родина, що потребує певного тарифу. Усе без такої примітки живе вже сьогодні на кожному тарифі з режимом правил.
Довідник іде за власним групуванням рушія: поля відповіді, потім способи дістатися до тіла, потім час, мережа й TLS, потім оператори, редюсери й скорочення, що працюють над усіма ними, а далі типи перевірок за межами HTTP, що говорять тією самою мовою.
Відповідь
Суб'єкти, що описують саму відповідь: її статус, сире тіло, заголовки, URL, з якої вона справді відповіла, і ланцюжок запитів, що до неї привів.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
body | Тіло відповіді як декодований текст. | string | body contains "Welcome" |
header | Один заголовок фінальної відповіді, за назвою. | string | header("Content-Type") isJson |
redirects | Пройдені кроки переспрямування - ланцюжок запитів без останнього елемента. | collection | redirects.count eq 0 |
status | Код стану HTTP фінальної відповіді, після переспрямувань. | number | status isOk |
body.size | Розмір завантаженого тіла, в байтах. | number | body.size lt 500000 |
url | URL, що справді відповіла, після всіх переспрямувань. url: порівнюйте як текст, або читайте її частини (url.host, .port, .path, .query, .scheme). | url | url.host eq "www.example.com" |
requests | Кожен запит цієї перевірки, по порядку - кроки переспрямування і потім фінальний запит. | collection | requests.count le 2 |
url.host | Частина host URL. | string | url.host eq "example.com" |
url.path | Частина path URL. | string | url.path startsWith "/api" |
url.port | Частина port URL. | number | url.port eq 443 |
url.query | Рядок запиту URL. | string | url.query contains "token" |
url.scheme | Схема URL (http чи https). | string | url.scheme eq "https" |
body.hash | Дайджест тіла відповіді - порівняйте з previous.body.hash, щоб виявити зміни вмісту. | string | body.hash eq previous.body.hash |
httpVersion (зарезервовано - ще не наповнюється) | Узгоджена версія HTTP. | string | httpVersion eq "HTTP/2" |
setCookie | Значення Set-Cookie фінальної відповіді, по одному елементу на cookie - зіставляйте одне з contains чи matches, рахуйте їх через .count. | collection | setCookie exists |
steps (поки недоступно) | Кроки багатоетапної перевірки. Поки недоступно. | collection | steps.count le 1 |
url.original | URL, з якою налаштована перевірка, до будь-якого переспрямування. url так само, як url: має ті самі частини (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.original.host | Частина host URL. | string | url.original.host eq "example.com" |
url.original.path | Частина path URL. | string | url.original.path startsWith "/start" |
url.original.port | Частина port URL. | number | url.original.port eq 80 |
url.original.query | Рядок запиту URL. | string | url.original.query contains "utm_" |
url.original.scheme | Схема URL (http чи https). | string | url.original.scheme eq "http" |
Два псевдоніми: redirectCount - скорочення для redirects.count - redirectCount eq 0 читається трохи природніше за еквівалентну довгу форму, коли ви маєте на увазі "перевірка відповіла напряму, без переспрямувань". А setCookie на верхньому рівні - це список cookie фінальної відповіді; та сама назва повторюється на рівні кожного кроку всередині requests/redirects (див. суб'єкти кроку нижче), несучи cookie лише того одного запиту.
Витягування значень із тіла
Ці суб'єкти розв'язуються, лише коли тіло справді має названий формат: простір імен JSON на сторінці HTML просто відсутній, а не типізовано помилковий. Це робить exists стандартним способом перевірити формат, і body.json exists запитує, чи розібралося тіло як JSON. Кожен із чотирьох просторів імен формату має свою функцію-запит .path(...) (JSONPath для json/yaml, XPath для xml, CSS-селектори для html) і свій .regex(...), а також формато-незалежний body.regex(...), що читає сирий текст незалежно від формату. body.html.a, body.html.script і body.html.link - готові колекції кожного посилання, скрипту та елемента <link> на сторінці; поля, доступні для кожного з них, дивіться в розділі "Області елементів" нижче.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
body.json | Тіло відповіді, але лише коли воно справді JSON. | string | body.json exists |
body.json.path | Запит до тіла JSON виразом JSONPath. | json | body.json.path("$.status") eq "ok" |
body.html | Тіло відповіді, але лише коли воно справді HTML. | string | body.html exists |
body.html.path | Оберіть елементи сторінки CSS-селектором. | collection | body.html.path("h1").first contains "Welcome" |
body.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml | Тіло відповіді, але лише коли воно справді XML. | string | body.xml exists |
body.xml.path | Запит до тіла XML виразом XPath. | string | body.xml.path("//item/@id") exists |
body.html.a | Кожне посилання на сторінці. | collection | body.html.a.count gt 0 |
body.html.link | Кожен елемент <link>, який декларує сторінка. Сама назва без поля означає цілі посилань. | collection | body.html.link.count gt 0 |
body.html.script | Кожен скрипт, що завантажує сторінка. Сама назва без поля означає джерела скриптів. | collection | body.html.script.count gt 0 |
body.yaml | Тіло відповіді, але лише коли воно справді YAML. | string | body.yaml exists |
body.yaml.path | Запит до тіла YAML виразом JSONPath. | json | body.yaml.path("$.services.web.image") contains ":1." |
body.html.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
body.json.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
body.xml.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
body.yaml.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
Деталь про родину regex варто виділити окремо: іменовані групи захоплення ((?<id>...)) всередині правила .regex(...) записуються в простір імен прив'язок, спільний для перевірки, і пізніше правило може прочитати їх назад через bind("id") чи bind[0] за позицією - дивіться "Захоплені значення" нижче.
Захоплені значення
Один суб'єкт живе у власній групі реєстру, бо він не читає відповідь напряму - він читає те, що захопило раніше правило.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
bind | Значення, захоплене раніше правилом regex, за назвою захоплення чи за позицією. | string | bind("id") gt 1000 |
Поєднайте його з правилом regex раніше в списку: правило на кшталт body.regex("order-(?<id>\d+)") exists захоплює ідентифікатор замовлення в ім'я id, і пізніше правило може перевірити його через bind("id") gt 1000 чи, для позиційного (неіменованого) захоплення, bind[0].
Час
Одне загальне значення плюс розбивка по фазах, тож сповіщення "стало повільніше" може ще й сказати, яка саме частина сповільнилася.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
time | Загальний час відповіді: з'єднання + TLS + очікування + завантаження. Розв'язання DNS не входить. | number | time lt 2000 |
ttfb (зарезервовано - ще не наповнюється) | Час до першого байта. | number | ttfb lt 200 |
time.connect | Час на встановлення TCP-з'єднання. | number | time.connect lt 500 |
time.data | Час на завантаження тіла відповіді. | number | time.data lt 1000 |
time.dns | Час на розв'язання доменного імені. Не входить у голий суб'єкт time. | number | time.dns lt 200 |
time.head | Час очікування заголовків відповіді. | number | time.head lt 500 |
time.tls | Час на TLS-рукостискання. | number | time.tls lt 300 |
Голий суб'єкт time - це з'єднання + TLS + очікування заголовків + завантаження тіла. Розв'язання DNS виключене і живе лише в суміжному time.dns, бо DNS часто кешується і інакше змушував би ту саму точку доступу виглядати то швидкою, то повільною між перевірками без причини.
Мережа: DNS і з'єднання
dns і conn у реєстрі - чисті простори імен, група без власного значення, тож правило ніколи не може зупинитися на голій назві (і редактор, і рушій відмовляють у ланцюжку, що закінчується просто на dns чи conn, і вказують на справжні поля нижче).
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
conn | Мережеве з'єднання, яке зробила перевірка - адреса, що обслужила відповідь, і будь-які невдалі спроби з'єднання. | string | - |
conn.failed | Скільки з розв'язаних адрес не вдалося з'єднати. | number | conn.failed eq 0 |
conn.failedIps (кандидат - розкочується на агентів) | Розв'язані адреси, з'єднання з якими не вдалося. | collection | conn.failedIps.count eq 0 |
conn.ip | IP-адреса, що справді обслужила відповідь. | string | conn.ip eq "203.0.113.10" |
conn.ip.family (кандидат - розкочується на агентів) | Чи обслуговувалась відповідь через IPv4 чи IPv6. | string | conn.ip.family eq "IPv4" |
dns | Розв'язання DNS моніторованого імені - до яких адрес воно розв'язалось і який сервер відповів. | string | - |
dns.ips | Усі IP-адреси, до яких доменне ім'я розв'язалося під час цієї перевірки. | collection | dns.ips contains "1.2.3.4" |
dns.server | DNS-сервер, що відповів на розв'язання. | string | dns.server eq "8.8.8.8" |
TLS і сертифікат
Як і dns та conn, tls і cert - чисті простори імен, факти про сертифікат/рукостискання живуть на рівень нижче.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
cert.days.left | Днів до закінчення терміну дії сертифіката сайту. | number | cert.days.left gt 14 |
cert | Сертифікат, який показав сервер - днів до закінчення терміну дії, видавець і поля ідентичності. | string | - |
cert.days | Днів від видачі сертифіката. | number | cert.days gt 0 |
cert.issuer | Центр сертифікації, що видав сертифікат сайту. | string | cert.issuer contains "Let's Encrypt" |
cert.san | Доменні імена, для яких дійсний сертифікат. | collection | cert.san contains "www.example.com" |
cert.serial | Серійний номер сертифіката. | string | cert.serial exists |
cert.subject (зарезервовано - ще не наповнюється) | Поле subject сертифіката. Поки не захоплюється - з'явиться з майбутньою версією агента. | string | cert.subject contains "example.com" |
tls | TLS-рукостискання захищеного з'єднання - узгоджена версія протоколу й шифр. | string | - |
tls.cipher | Узгоджений набір шифрів. | string | tls.cipher contains "AES" |
tls.protocol | Узгоджена версія TLS. | string | tls.protocol eq "Tls13" |
cert.subject наведено тут для повноти, але поки не наповнюється - дивіться розділ "Чесність" нижче про те, що на практиці означає "зарезервовано". Повсякденне правило для сертифіката - cert.days.left gt 14, розглянуте в розділі готових правил.
Суб'єкти кроку: поля всередині requests і redirects
requests і redirects - це колекції, і кожен елемент - повний запис запиту/відповіді зі своїм скороченим набором полів. Не кожен суб'єкт верхнього рівня має сенс на рівні кроку (у кроку немає власного сертифіката), і одне поле існує лише на рівні кроку: hstsHeader, заголовок Strict-Transport-Security того запиту в ланцюжку.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
status | Код стану цього запиту в ланцюжку. | number | status eq 200 |
url | URL, на яку було зроблено цей запит. | url | url startsWith "https://" |
header | Заголовок відповіді цього запиту. Крок тримає скорочений, одиничний запис заголовка - предикати для списків (containsAny, containsAll, unique) застосовуються лише до заголовка фінальної відповіді. | string | header("Content-Type") contains "json" |
hstsHeader | Заголовок Strict-Transport-Security цього запиту. | string | requests[0].hstsHeader exists |
setCookie | Значення заголовка Set-Cookie цього запиту. | collection | setCookie exists |
url.original | URL, з якою налаштована перевірка, до будь-якого переспрямування. url так само, як url: має ті самі частини (url.original.host, .port, .path, .query, .scheme). | url | url.original.scheme eq "http" |
url.host | Частина host URL. | string | url.host eq "example.com" |
url.port | Частина port URL. | number | url.port eq 443 |
url.path | Частина path URL. | string | url.path startsWith "/api" |
url.query | Рядок запиту URL. | string | url.query contains "token" |
url.scheme | Схема URL (http чи https). | string | url.scheme eq "https" |
url.original.host | Частина host URL. | string | url.original.host eq "example.com" |
url.original.port | Частина port URL. | number | url.original.port eq 80 |
url.original.path | Частина path URL. | string | url.original.path startsWith "/start" |
url.original.query | Рядок запиту URL. | string | url.original.query contains "utm_" |
url.original.scheme | Схема URL (http чи https). | string | url.original.scheme eq "http" |
Заголовок header(...) на рівні кроку тримає скорочений, одиничний запис: предикати у формі списку на кшталт containsAny чи unique мають сенс лише на повній мапі заголовків фінальної відповіді, тож вони застосовуються там, а не на рівні кроку. Дві колекції означають різне. requests - це весь ланцюжок, включно з фінальною відповіддю, що відповіла, тож вона ніколи не порожня навіть для прямого 200, тоді як redirects - лише кроки, пройдені на шляху туди, порожня, коли нічого не переспрямовувало.
Області елементів: поля всередині одного елемента колекції
Область елемента - це набір полів, доступний на ОДНОМУ елементі колекції - після індексації в нього (requests[0]) чи під час фільтрації через where(current. ...) (див. наступний розділ). Шість колекцій мають власну область елемента: чотири колекції елементів HTML мають спільну форму, а requests/redirects мають форму суб'єктів кроку, задокументовану щойно вище.
| Область елемента | Як виглядає один елемент |
|---|---|
body.html.path | Один елемент, знайдений CSS-запитом body.html.path("selector"). |
body.html.a | Один елемент посилання <a> з body.html.a. |
body.html.script | Один елемент <script> з body.html.script. |
body.html.link | Один елемент <link> з body.html.link. |
requests | Один запит у повному ланцюжку (див. таблицю суб'єктів кроку вище). |
redirects | Один пройдений крок переспрямування (ті самі поля, що і requests, див. вище). |
Спільна форма для body.html.path(...), body.html.a, body.html.script і body.html.link - один рядок на кожне посилання, тег скрипту чи елемент <link>:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
url | Ціль посилання точно так, як її пише розмітка. | string | body.html.a.url contains "/checkout" |
text | Видимий текст елемента. | string | body.html.a.text contains "Sign in" |
absolute | Ціль посилання, розв'язана відносно URL сторінки в абсолютну адресу - список url, з частинами url, доступними для кожного елемента (.host, .path, .port, .query, .scheme). | url | body.html.a.absolute.scheme in ["https"] |
rel | Атрибут rel елемента. | string | body.html.a.where(current.rel eq "nofollow").count eq 0 |
absolute.host | Частина host URL. | string | body.html.a.absolute.host.unique.count le 3 |
absolute.port | Частина port URL. | number | body.html.a.absolute.port in [443] |
absolute.path | Частина path URL. | string | body.html.a.absolute.path startsWith "/" |
absolute.query | Рядок запиту URL. | string | body.html.a.absolute.query not contains "session" |
absolute.scheme | Схема URL (http чи https). | string | body.html.a.absolute.scheme in ["https"] |
Перш ніж писати правило проти цих колекцій, застосовуються два значення за замовчуванням. Гола згадка body.html.a (чи .script/.link) означає проєкцію .url, тож body.html.a.count gt 0 рахує href-атрибути, а збережене правило зчитується назад із явно вказаним .url, бо збережене правило завжди каже точно те, що воно оцінює. А .url - це сирий атрибут href точно так, як його записала розмітка, тож відносне посилання лишається відносним; .absolute - те саме посилання, розв'язане відносно власної URL сторінки, що потрібно, коли перевіряєте схему чи хост вихідних посилань (body.html.a.absolute.scheme in ["https"]).
Оператори
Друга половина кожного правила - предикат: яку перевірку виконати над суб'єктом. Усіх 15 спільні для кожного типу перевірки, а те, які з них підходять до конкретного суб'єкта, залежить від його типу (код стану приймає lt/gt, тіло приймає contains, колекція приймає exists/unique/in).
| Назва | Що це | Застосовується до | Приклад |
|---|---|---|---|
eq | Дорівнює. Проти літералу json("…") / xml("…") / yaml("…") це ТОЧНИЙ структурний збіг: ті самі ключі (в будь-якому порядку), масиви по порядку, ті самі значення. | будь-який тип | body.json eq json("{\"ok\": true}") |
lt | Менше за. | числа | time lt 2000 |
le | Менше або дорівнює. | числа | cert.days.left le 30 |
gt | Більше за. | числа | body.size gt 0 |
ge | Більше або дорівнює. | числа | status ge 500 |
contains | Містить текст - над списком проходить, коли значення Є одним з елементів (точний збіг; для пошуку всередині елементів використовуйте matches). Проти літералу json("…") / xml("…") / yaml("…") це СТРУКТУРНЕ включення: усе, що заявлено в літералі, має бути присутнім і збігатися; у відповіді може бути й більше. | текст чи список | body.json contains json("{\"status\": \"ok\"}") |
startsWith | Починається з тексту - над списком, коли БУДЬ-ЯКИЙ елемент так починається. | текст | url.path startsWith "/api" |
endsWith | Закінчується текстом - над списком, коли БУДЬ-ЯКИЙ елемент так закінчується. | текст | url.path endsWith ".json" |
matches | Відповідає регулярному виразу будь-де в тексті - над списком, коли БУДЬ-ЯКИЙ елемент відповідає. | текст | body matches "order-\\d+" |
containsAny | Містить хоча б одне з перелічених значень (над списком: якийсь елемент ДОРІВНЮЄ одному з них). | список | body containsAny ["In stock", "Pre-order"] |
containsAll | Містить кожне з перелічених значень (над списком: кожне значення дорівнює якомусь елементу - свідки можуть відрізнятися). | список | body.html.a.text containsAll ["Home", "Contact"] |
in | Є одним із перелічених значень чи діапазонів - над списком, кожен елемент є. | значення чи діапазон | status in [200, 301, 302] |
exists | Суб'єкт присутній. | будь-який суб'єкт | header("ETag") exists |
isNumber | Значення читається як число. | текст чи будь-що | bind("id") isNumber |
unique | Список без дублікатів. | список | dns.ips unique |
Два оператори означають дещо вужче, ніж здається на слух. contains над списком - точна належність: значення має дорівнювати цілому елементу, а не з'являтися як підрядок усередині одного, тож для поведінки підрядка над елементами колекції звертайтеся до matches. А eq проти літералу json(...)/xml(...)/yaml(...) - повний структурний збіг (ті самі ключі, масиви в тому самому порядку, ті самі значення), тоді як contains проти того самого типу літералу - структурне включення: усе, що заявляє літерал, має бути присутнім, але справжня відповідь може нести й більше.
Редюсери
Редюсер згортає колекцію в одне значення і може стояти лише в кінці ланцюжка. Приклади нижче використовують requests.status, природно числову колекцію суб'єктів HTTP, як ілюстрацію; ті самі вісім редюсерів працюють над будь-якою числовою колекцією в будь-якому типі перевірки (часи проходження туди-й-назад для Ping, відфільтрований набір рядків бази даних).
| Назва | Що згортає | Застосовується до | Приклад |
|---|---|---|---|
count | Скільки елементів у списку. | будь-яка колекція | requests.count le 2 |
min | Найменше число в списку. | числова колекція | requests.status.min ge 200 |
max | Найбільше число в списку. | числова колекція | requests.status.max lt 500 |
sum | Сума чисел у списку. | числова колекція | requests.status.sum gt 0 |
avg | Середнє чисел у списку. | числова колекція | requests.status.avg lt 300 |
first | Перший елемент списку. | будь-яка колекція | redirects.status.first eq 301 |
last | Останній елемент списку. | будь-яка колекція | requests.status.last eq status |
unique | Список без дублікатів. | будь-яка колекція | dns.ips.unique.count le 3 |
unique перевантажений, і написання відрізняє два значення. Написаний як оператор без крапки (x unique) це предикат, "у цій колекції немає дублікатів", і провалюється, називаючи повтор. Написаний як редюсер із крапкою (x.unique) це трансформація, сама дедуплікована колекція, за якою все одно має щось іти (x.unique.count eq 1). Незавершений x.unique без нічого після нього - синтаксична помилка, бо рушій не може вгадати, що з двох ви мали на увазі.
Sugar
Sugar-предикати - це скорочення, які рушій розгортає у звичайні базові предикати ще до того, як правило взагалі надсилається агенту - sugar-предикат нічого не коштує додатково (жодного бандла агента, жодного порогу версії), бо на момент, коли він доходить до каналу, він уже виглядає як звичайне правило. Віддавайте перевагу sugar, коли він існує: читається краще, і це точний еквівалент того самого, що написати довгу форму вручну.
| Назва | Що означає | Застосовується до | Приклад |
|---|---|---|---|
isOk | Статус - код успіху (200-299). | status | - |
isRedirect | Статус - код переспрямування (300-399). | status | status isRedirect |
isClientError | Статус - клієнтська помилка (400-499). | status | status isClientError |
isServerError | Статус - серверна помилка (500-599). | status | status isServerError |
isJson | Вміст справді JSON. | документ чи текст типу медіа | header("Content-Type") isJson |
isXml | Вміст справді XML - тіло розбирається як XML, чи заголовок називає тип медіа XML. | документ чи текст типу медіа | body isXml |
isHtml | Вміст справді HTML - тіло розбирається як HTML, чи заголовок називає тип медіа HTML. | документ чи текст типу медіа | body isHtml |
isForm | Тип медіа називає кодування форми: application/x-www-form-urlencoded чи multipart/form-data. На відміну від isJson/isXml/isHtml тут немає відповідного простору імен тіла, тож це застосовується лише до значення типу медіа, наприклад заголовка Content-Type. | лише текст типу медіа | header("Content-Type") isForm |
isEmpty | Нічого немає: порожній текст, нульовий розмір чи порожній список. | текст, розмір чи список | body isEmpty |
isNull | Значення null. | будь-яке значення | body.json.path("$.deletedAt") isNull |
absent | Суб'єкт узагалі відсутній. | будь-який суб'єкт | header("X-Debug") absent |
between | Число у включному діапазоні. | числа (2 операнди) | body.size between 50 and 500kb |
isJson/isXml/isHtml навмисно контекстно-залежні, і те, на чому ви їх пишете, визначає, яке значення застосовується. Написані на самому документі (body isJson) вони означають "чи розбирається це як цей формат", те саме, що body.json exists. Написані на текстовому значенні, що називає тип медіа, наприклад заголовку (header("Content-Type") isJson), вони означають "чи називає це сімейство MIME цього формату"; дивіться "Родини MIME" нижче про те, які типи медіа підходять. isForm має лише друге значення, бо немає простору імен body.form для розбору, тож body isForm - статична помилка, а не правило, що ніколи не могло б бути істинним.
Фільтр where(...)
Залиште лише елементи, що збігаються, і продовжуйте звідти. Це єдина фільтрувальна конструкція в мові, і вона має рівно одну форму: where(current.<field> <condition> <value>).
Фільтрація відрізняється від проєкції: requests.url contains "cart" запитує, чи існує такий крок будь-де в ланцюжку, тоді як requests.where(current.url contains "cart").status запитує, що повернув саме той крок. Фільтрація не згортає список, тож завершіть його .first, перевіркою in [...] чи .count. Вона діє лише на один рівень і приймає рівно одну умову.
| Частина | Що позначає | Примітки |
|---|---|---|
current.<field> | Поле кожного елемента, що фільтрується, написане після current. | Це та половина, яку люди плутають найчастіше: current.url - це URL окремого кроку, а не фінальної відповіді. Після current. можуть іти лише власні поля елемента. |
| умова | Будь-який звичайний предикат, включно з not і nocase | Будь-яка умова, що працює на верхньому рівні правила, працює і тут. |
| значення | З чим порівнюється поле кожного елемента | Зазвичай просте значення. Суб'єкт, написаний тут, читається із ЗОВНІШНЬОЇ відповіді, а не з елемента - where(current.url eq url.original) порівнює кожен крок із URL, з якою налаштована перевірка, тому сторона елемента й має вимовляти current. явно. |
Приклад: requests.where(current.url contains "cart").status.first eq 301 - залишіть лише кроки, чия URL містить "cart", а потім погляньте на статус першого з них, що збігся.
Ще два обмеження, обидва застосовує парсер із власним повідомленням: where не можна вкладати всередину іншого where, а його аргумент - рівно одна умова, без and/or усередині. Він застосовується лише до колекції, чиї елементи несуть іменовані поля (requests, body.html.a), а не до простого проєктованого списку на кшталт dns.ips, де немає нічого, що міг би назвати current..
Синтаксичний довідник
Усе інше, що визначає граматика: як назвати правило, як писати діапазони й списки, що означає голий суб'єкт, і невеликі форми пунктуації, що з'являються в багатьох правилах.
| Форма | Що робить | Тип | Приклад |
|---|---|---|---|
where | Залиште лише елементи, що збігаються, і продовжуйте звідти. | фільтр колекції | requests.where(current.url contains "cart").status.first eq 301 |
not | Інвертує наступну умову. | прапорець | body not contains "error" |
nocase | Порівнювати текст без урахування регістру. | прапорець | body contains "welcome" nocase |
current | Всередині where(…) називає той один елемент, що фільтрується. | посилання на елемент (всередині where) | requests.where(current.status eq 301) |
range | Діапазон чисел, обидва кінці ВКЛЮЧНО. | числовий діапазон | status in [200..299] |
list | Список значень для порівняння. | список значень | status in [200, 301, 302] |
docLiteral | Типізоване значення документа для структурного порівняння: текст у лапках розбирається як JSON, XML чи YAML при збереженні правила. | текст json/xml/yaml | body.json contains json("{\"user\": {\"active\": true}}") |
implicitExists | Правило, що називає лише суб'єкт, перевіряє, чи він присутній: написання просто body.json зберігається як body.json exists. | рядок із голим суб'єктом | body.json |
index | Обирає ОДИН елемент списку за позицією, з нуля. | ціле число з нуля | requests[0].status |
label | Необов'язкова назва правила, написана перед двокрапкою. | назва перед двокрапкою | "json ok": body.json exists |
comment | Усе після # - нотатка для вас самих; на перевірку це не впливає. | текст # у кінці рядка | status isOk # the happy path |
Кілька з них варті пояснення простими словами. label дає правилу назву, яка з'являється в сповіщенні замість відображеного виразу; пишіть її перед двокрапкою, як у "json ok": body.json exists. implicitExists означає, що рядок, який називає лише суб'єкт і жодного предиката, - скорочення для exists: написання body.json зберігається як body.json exists, і повторне відкриття правила показує розгорнуту форму. range і list - дві форми, які може набути значення після in: діапазон ([200..299], обидва кінці включно) чи явний список ([200, 301, 302]), і значення може бути відкритим з будь-якого боку ([400..]). docLiteral - це обгортка json(...)/xml(...)/yaml(...), що використовується для структурного порівняння з тілом (розглянуто вище в "Операторах" і нижче в готових правилах). index обирає один елемент колекції за позицією, з нуля, так само, як bind[0] читає позиційне захоплення. current має сенс лише всередині фільтра where(...), розглянутого у власному розділі вище.
Обгортки: previous, delta і delta2
Три форми, що дивляться назад, а не лише на поточну відповідь - кожна доступна лише на тарифах зі stateful-твердженнями, і кожна детально пояснена в розділі "Порівняння з попередньою перевіркою" нижче.
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
delta (потребує тарифу зі stateful-твердженнями) | Наскільки змінилося числове значення з попередньої перевірки - за бажанням як швидкість за мс/с/хв/год. | number | delta(body.size, h) lt 1mb |
delta2 (потребує тарифу зі stateful-твердженнями) | Зміна зміни - чи прискорюється значення? | number | delta2(time) gt 0 |
previous (потребує тарифу зі stateful-твердженнями) | Значення, яке мав цей суб'єкт на попередній перевірці. | будь-що | status eq previous.status |
Прапорці: not і nocase
Два модифікатори, що приєднуються до правила, а не виступають самостійним суб'єктом чи предикатом.
| Прапорець | Що робить | Тип | Приклад |
|---|---|---|---|
not | Інвертує наступну умову. | прапорець (приєднується до правила) | body not contains "error" |
nocase | Порівнювати текст без урахування регістру. | прапорець (приєднується до правила) | body contains "welcome" nocase |
not поєднується з наступним предикатом, а не заперечує все правило як єдине ціле - x not != y читається як x eq y, а не як подвійне заперечення. Коли суб'єкт може бути цілком відсутнім, віддавайте перевагу sugar absent над not exists: обидва означають точно те саме, але absent каже про це прямо. nocase щось міняє лише в дійсно текстовому порівнянні; редактор (і цей довідник) все одно дозволяють написати його будь-де, але він мовчки безглуздий на числовому тесті на кшталт status eq 200 nocase.
Родини MIME
Таблиці пошуку за isJson, isXml, isHtml і isForm, коли їх застосовують до значення типу медіа, наприклад заголовка. Кожна родина збігається з очевидним типом медіа верхнього рівня плюс, для JSON і XML, будь-яким типом, що закінчується відповідним структурним суфіксом - саме це робить так, що header("Content-Type") isJson правильно проходить на application/problem+json чи application/vnd.api+json, а не лише на простому application/json.
| Родина | Збігається з | Парний sugar | Приклад |
|---|---|---|---|
json | application/json, text/json, чи будь-який тип медіа, що закінчується на +json (application/problem+json, application/vnd.api+json, application/ld+json, ...). | sugar: isJson | header("Content-Type") isJson |
xml | application/xml, text/xml, чи будь-який тип медіа, що закінчується на +xml (image/svg+xml, application/atom+xml, ...). | sugar: isXml | header("Content-Type") isXml |
html | text/html чи application/xhtml+xml. | sugar: isHtml | header("Content-Type") isHtml |
form | application/x-www-form-urlencoded чи multipart/form-data. | sugar: isForm | header("Content-Type") isForm |
Зіставлення ігнорує все від першого ; і далі (тож application/json; charset=utf-8 все одно збігається) і не чутливе до регістру.
Суб'єкти для перевірок бази даних, лічильника, SNMP, порту і ping
Кожен оператор, редюсер, sugar-скорочення і синтаксична форма вище - однакові для цих п'яти типів перевірок: рушій реєструє ті самі 15 операторів, 8 редюсерів, 12 sugar-предикатів і 11 синтаксичних форм для всіх шести типів без винятку. Що відрізняється по типах, так це список суб'єктів. Кожен тип виставляє невеликий набір суб'єктів, унікальних для того, що він вимірює, плюс підмножину вже задокументованих вище суб'єктів мережі/часу/TLS, зі значенням, що адаптується до типу (time перевірки Database - це з'єднання-плюс-запит, а не з'єднання-плюс-TLS-плюс-завантаження, бо тут немає HTTP-відповіді для завантаження).
Перевірки бази даних
Ділить time, time.connect і time.dns із задокументованими вище суб'єктами (перевизначені під з'єднання з базою даних: з'єднання-плюс-запит, розв'язання DNS хоста бази даних). Унікальні для перевірок бази даних:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
scalar | Єдине значення, яке повернув запит (режим Scalar). | будь-що | - |
rows | Рядки, які зачепив чи повернув запит (режим NonQuery). | collection | - |
time.query | Час, який зайняв сам запит. | number | - |
Готовий приклад - у наступному розділі: використовуйте rows.count, щоб перевірити, скільки рядків зачепив чи повернув запит, і scalar, щоб перевірити безпосередньо одне повернуте значення.
Перевірки лічильника (Counter)
Ділить time із задокументованими вище суб'єктами - як поле зі статусом кандидата саме для перевірок Counter (час проходження туди-й-назад запиту лічильника; про значення "кандидат" дивіться розділ "Чесність"). Унікальне для перевірок лічильника:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
value | Виміряне значення лічильника. | number | - |
Перевірки SNMP
Ділить time і time.dns із задокументованими вище суб'єктами (розв'язання імені хоста плюс сам запит SNMP). Унікальне для перевірок SNMP:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
time.request | Час, який зайняв запит SNMP. | number | - |
value | Значення, яке повернув OID. | будь-що | - |
value.type (кандидат - розкочується на агентів) | Назва типу даних SNMP поверненого значення. | string | - |
value.type має статус кандидата; дивіться розділ "Чесність". Примітка про доступність: перемикач Response Validation режиму правил ще не дійшов до редактора монітора SNMP. Він показує панель "Coming soon", що називає ці два суб'єкти, а не робочий список правил. Самі суб'єкти й обчислювач під ними вже зареєстровані; лише інтерфейс редактора SNMP ще в очікуванні.
Перевірки портів
Найбільший спільний список серед усіх не-HTTP типів. Перевірка TCP-порту несе по суті ті самі суб'єкти з'єднання, DNS, TLS і сертифіката, що й HTTP-перевірка, бо перевірка порту теж може узгодити TLS: bind, cert та його шість підполів, conn та його чотири підполя, dns та його два підполя, time/time.connect/time.dns/time.tls, і tls/tls.cipher/tls.protocol - усі задокументовані в розділах вище, з тими самими значеннями. Унікальне для перевірок портів:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
banner | Дані, зчитані з сокета після з'єднання. | string | - |
banner.hash (кандидат - розкочується на агентів) | Дайджест банера - порівняйте з previous.banner.hash, щоб виявити зміни сервісу. | string | - |
banner.regex | Зіставте текст регулярним виразом і візьміть те, що він захопив. | string | body.regex("order-(?<id>\\d+)") exists |
banner.size (кандидат - розкочується на агентів) | Розмір банера, в байтах. | number | - |
banner.hash і banner.size мають статус кандидата - дивіться розділ "Чесність". banner.regex живе вже сьогодні і працює точно так само, як body.regex(...) у HTTP-перевірці: іменовані захоплення живлять той самий простір імен bind(...).
Перевірки Ping
Ділить суб'єкти з'єднання й DNS із розділами вище: conn, conn.failed, conn.failedIps, conn.ip, conn.ip.family, dns, dns.ips, dns.server, time (тут - середній час проходження туди-й-назад вдалих відповідей) і time.dns. Унікальне для перевірок ping:
| Назва | Що це | Тип/значення | Приклад |
|---|---|---|---|
loss | Відсоток echo-запитів, що не отримали відповіді. | number | loss eq 0 |
reply | Вдалі echo-відповіді. | collection | - |
sentCount (кандидат - розкочується на агентів) | Скільки echo-запитів було надіслано. | number | - |
time.max | Час проходження туди-й-назад найповільнішої відповіді. | number | - |
time.min | Час проходження туди-й-назад найшвидшої відповіді. | number | - |
ttl | TTL першої вдалої відповіді - порівняйте з previous.ttl, щоб помітити зміну маршруту. | number | - |
sentCount має статус кандидата - дивіться розділ "Чесність". ttl варто знати навіть поза строгим правилом успіху/невдачі: поєднання його з previous.ttl (див. "Обгортки" вище) сигналізує про зміну маршруту між перевірками, бо час життя пакета на момент прибуття відображає, скільки переходів він пройшов.
Правила, які насправді хочуть писати люди
Сторінка працює і справді каже правильну річ
Сам по собі код стану не може сказати, чи сторінка відрендерилася правильно - відповідь 200 із порожньою оболонкою - класичний тихий збій, який пропускає перевірка лише за статусом.
status isOk
body contains "Add to cart"
API відповідає JSON і потрібним полем
Перевірте, що точка доступу все ще говорить JSON, а потім заглибтеся в неї. Перший рядок ловить сторінку помилки HTML, віддану там, де мав бути JSON, - типова форма збою за проксі; другий перевіряє власний заявлений стан здоров'я API, а не лише статус транспорту.
body isJson
body.json.path("$.status") eq "ok"
Відповідь стала повільнішою, ніж мала б бути
Розбийте на частини, коли вам треба знати, що виправляти, а не просто що щось повільне - time.connect, time.tls, time.dns і time.head розділяють час мережі, рукостискання, резолвера й застосунку.
time lt 2s
Переспрямування відправило відвідувачів за межі вашого власного домену
Порівнює, де опинилася перевірка, з URL, яку ви налаштували - провалюється в ту мить, коли ланцюжок переспрямувань, зламаний, неправильно налаштований чи просто змінений деплоєм, веде туди, куди ви не мали на увазі.
url.host eq url.original.host
Сторінка змінилася з останньої перевірки
Корисно на вмісті, що має лишатися стабільним між перевірками - ціни, умови, опублікована політика - і водночас служить базовим сигналом дефейсу.
previous.body.hash eq body.hash
Число в діапазоні, написане коротким шляхом
Ловить і урізану сторінку, і таку, що розрослася, одним правилом, без написання явного діапазону.
body.size between 50 and 500kb
Сертифікат, що ось-ось закінчиться
Найпоширеніша TLS-перевірка з усіх, і та, яку звичайний монітор працює/не працює взагалі не може виразити - сертифікат, що сьогодні ще проходить валідацію, а наступного тижня спливає, не дає жодного іншого попереднього сигналу. Поєднайте з cert.issuer, якщо хочете ще й ловити сертифікат, тихо виданий не тим центром.
cert.days.left gt 14
Запит до бази даних повертає неправильну кількість рядків
У перевірці Database rows - колекція, яку зачепив чи повернув запит - підрахунок ловить запит, що мав повертати рівно один запис облікового запису, а тихо почав повертати нуль (видалено, чи зламаний join) чи більше одного (дублікат, якого не мало бути).
rows.count eq 1
Значення SNMP виходить за межі діапазону
Пристрій SNMP, що взагалі відповідає, - не те саме, що справний: моніторований OID (використання диска, глибина черги, температура) може піднятися далеко за безпечний поріг, поки сам пристрій лишається цілком досяжним. Порівняння опитаного value з діапазоном ловить те, чого не ловить проста перевірка досяжності.
value lt 90
Сервіс TCP відповідає неправильним банером
Порт, що приймає з'єднання, - не те саме, що правильний сервіс, який на ньому слухає: завислий процес, неправильно налаштований проксі чи знижений/підмінений сервіс все ще можуть завершити TCP-рукостискання. Читання вітального тексту, який сервіс надсилає одразу після з'єднання (банер SMTP, FTP чи подібний), ловить те, чого не ловить гола перевірка відкритого порту.
banner contains "220"
Порівняння з попередньою перевіркою
Жменька суб'єктів дивиться назад, а не лише на поточну відповідь: поставте previous. перед суб'єктом, щоб прочитати, яким він був на останній перевірці, або загорніть його в delta(...), щоб отримати різницю між тоді й тепер, або в delta2(...), щоб отримати зміну цієї зміни - корисно, щоб помітити значення, що радше прискорюється, ніж просто дрейфує (час відповіді, що зростає швидше з кожною перевіркою). previous.body.hash eq body.hash вище - це точно воно: "чи збігається відбиток тіла з тим, яким він був минулого разу". delta(body.size, h) читає зміну як швидкість за годину замість сирої різниці, для значень, які ви очікуєте зростати рівномірно, а не стрибати.
Коли таке правило запускається вперше, йому нема з чим порівнювати, тож воно пропускається, а не провалюється: перевірка позначається як "розігрівається", а не зламана, і додавання правила не спричиняє жодного хибного сповіщення. Розігрів застосовується лише тоді, коли поточне зчитування справне, а базового значення бракує. Якщо саме поточне зчитування провалюється (скажімо, цього разу тіло не є дійсним JSON), правило провалюється точно так само, як провалилася б його звичайна версія без previous.. Таке правило також потребує, щоб значення змінювалося між перевірками, що робить його безглуздим на методі перевірки, який ніколи не просуває стан, наприклад HEAD-запиті.
Порівняння з попередньою перевіркою потребує тарифу вищого рівня; без нього ці суб'єкти виглядають сірими в редакторі з поясненням.
Ліміти, і що відсутнє навмисно
Скільки правил можна додати, залежить від вашого тарифу, показується живим лічильником поруч із "Add rule". Рушій також застосовує абсолютну стелю на кожну перевірку незалежно від тарифу - це запобіжник проти зловживання, а не обмеження на звичайне використання: перевірка з приблизно такою кількістю правил уже була б незвично великою.
Немає способу написати власний JavaScript для правила, і ніколи не буде. Кожне правило будується з фіксованого, іменованого словника суб'єктів і предикатів, а не з відкритої скриптової пісочниці, що тримає правило читабельним з одного погляду і безпечним для виконання на кожному агенті моніторингу у всьому світі.
Не кожне правило працює всюди в ту саму мить, коли його написано: деяким новішим умовам потрібна свіжіша версія агента моніторингу, що виконує вашу перевірку, тож нова можливість потребує часу, щоб дійти до кожної перевірки на вашому акаунті, поки агенти оновлюються у фоні. Правила, побудовані на стабільному ядрі мови, це не зачіпає.
Жменька записів у цьому довіднику ще не повністю живі, і кожен позначений у своїй таблиці вище:
- Зарезервовано (декларовано, ще не наповнюється жодним агентом):
ttfb,httpVersion,cert.subject. - Кандидат (уже розкочується, ще не на кожному агенті):
conn.ip.familyіconn.failedIpsу перевірках HTTP, Port і Ping,value.typeу перевірках SNMP,banner.hashіbanner.sizeу перевірках Port,sentCountу перевірках Ping, і власнийtimeперевірки Counter. - Поки недоступно:
steps, зарезервовано для майбутнього багатоетапного типу перевірки. - Потребує тарифу зі stateful-твердженнями: уся родина обгорток
previous/delta/delta2, у кожному типі перевірки.
Усе інше в цьому довіднику живе вже сьогодні на кожному тарифі з режимом правил.
Де режим правил працює вже сьогодні
Перемикач Response Validation для режиму правил з'являється в моніторах HTTP (сайт) і API, що мають спільний редактор правил і синтаксис. Та сама мова й обчислювач уже працюють під перевірками Database, Counter, Port, Ping і SNMP на рівні протоколу: реєстр вище обслуговує всі шість типів перевірок, і правило, збережене для одного, читається так само, якщо режим пізніше дійде до редактора іншого типу.
SNMP показує найяскравіший попередній перегляд: у його редакторі вже є панель Assertion rules, що називає value і value.type, позначена "Coming soon", але поки без робочого списку правил за нею. Перевірки Database, Counter і Ping не показують жодної панелі режиму правил узагалі, хоч їхні суб'єкти так само живі в рушії під капотом.
Налаштування реальної перевірки
Якщо ви перевіряєте REST API, а не просту вебсторінку, почніть із перевірки відповіді API, що охоплює аптайм, час відповіді й тіло власного API разом. Для сторінки чи сайту, що має лишатися доступним і відповідати правильно звідусіль, де є ваші користувачі, глобальний моніторинг аптайму з понад 300 локацій - ширша картина, в яку вбудовується режим правил. Щоб налаштовувати правила через код, а не через панель, власний API v2 HostTracker створює й оновлює правила режиму монітора так само, як це робить редактор. Для правила закінчення терміну дії сертифіката вище і всього іншого про TLS моніторинг домену й TLS-сертифіката охоплює тип перевірки, на якому живуть cert.days.left та інші суб'єкти TLS. Щоб побачити, як одне правило оцінюється проти реальної URL прямо зараз, без акаунта, скористайтеся безкоштовним інструментом HTTP-перевірки. Щодо кодів стану, з якими порівнює суб'єкт status, почніть із 200 OK, а посібники з моніторингу охоплюють налаштування кожного типу перевірки, на якому виконується ця мова.
Часті запитання
Що станеться з моїми старими налаштуваннями коду стану й ключового слова, якщо я увімкну режим правил?
Їх замінює список правил, поки режим увімкнено. Вимкнення його назад перед збереженням повертає класичні поля точно такими, якими вони були: нічого не видаляється, просто обидва режими не можуть бути активними одночасно.
Чи можу я поєднати кілька умов в одному моніторі?
Так: кожне правило в списку має пройти. Поки що немає "OR" між окремими правилами, тож щоб прийняти одне з кількох значень, використовуйте одне правило з in [...] чи containsAny [...].
Чи дозволить мені колись режим правил написати власний скрипт?
Ні. Кожне правило складається з фіксованого набору суб'єктів і предикатів мови. Власного JavaScript немає навмисно.
Що станеться першого разу, коли я додаю правило, що порівнює з попередньою перевіркою?
Йому ще нема з чим порівнювати, тож воно позначається як таке, що розігрівається, і пропускається, а не провалюється. Додавання правила "чи це змінилося" ніколи саме по собі не спричиняє хибного сповіщення.
Чи потрібен мені конкретний тариф, щоб використовувати режим правил?
Сам режим і повсякденні правила (статус, тіло, заголовки, час, переспрямування) широко доступні; скільки правил можна додати одночасно, залежить від вашого тарифу й показується живо в редакторі. Правила, що порівнюють із попередньою перевіркою (previous, delta, delta2), потребують тарифу вищого рівня і виглядають сірими з поясненням.
Чи працює режим правил на API-моніторах так само, як на моніторах сайтів?
Так. HTTP і API монітори мають спільний редактор правил, суб'єкти й предикати, і правило, написане для одного, читається ідентично на іншому.
Що насправді робить where(...), і коли він мені потрібен?
Він фільтрує колекцію до елементів, що збігаються з умовою, перш ніж ви прочитаєте поле результату. Використовуйте його, коли проста проєкція на кшталт requests.status недостатньо конкретна, і вам потрібен один певний крок, посилання чи елемент, а не вся колекція (див. розділ вище).
Чи можу я вже сьогодні написати правило проти запиту до бази даних, значення SNMP, банера порту чи результату ping?
Мова й обчислювач підтримують усі з них, і таблиці суб'єктів вище охоплюють кожен. Редактор правил - ні: лише монітори HTTP і API показують перемикач Response Validation сьогодні. SNMP показує попередній перегляд "Coming soon" своїх двох суб'єктів, а Database, Counter і Ping взагалі не показують панелі режиму правил.
Чому деякі суб'єкти в цьому довіднику названі "зарезервовано" чи "кандидат" замість того, щоб просто бути в списку як звичайні?
"Зарезервовано" означає, що поле декларовано в реєстрі, але жоден агент ще його не наповнює; "кандидат" означає, що воно розкочується на агентів, але ще не дійшло до всіх. Обидва позначені всюди, де з'являються в цьому довіднику, і в підсумковому списку в розділі "Ліміти" вище.