Нагрузочный тест, который завершился зелёным, но промахнулся мимо SLO по
латентности, — это ложная зелень. До сих пор поймать такое можно было только
клеем: --summary-export в jq, пара строк awk по перцентилям из stdout или
обёртка-скрипт, которую никто не хочет поддерживать. Инлайн-блоки check:
намеренно мягкие — они печатают и считают провалы, но прогон всё равно
завершается с кодом 0, потому что check — это обратная связь, а не вердикт.
Начиная с v0.8.1, вердикт встроен в движок. std/thresholds@v1
приносит в perfscale threshold-выражения в стиле k6: SLO-гейты уровня
прогона, вычисляемые один раз, после остановки всех VU, по метрикам,
собранным за весь прогон. И как остальное семейство std/*, это бесплатно
для всех — код живёт в
OSS-репозитории под двойной
лицензией MIT/Apache-2.0.
Гейты живут в after:
after:
- name: slo gate
use: std/thresholds@v1
with:
http_req_duration: ["p95<500", "avg<300", "max<2000"]
http_req_failed: ["rate<0.01"]
severity: fail
message: "checkout SLO"
Нарушенный fail-гейт печатает http_req_duration p95=612ms ≥ 500ms; checkout SLO, и прогон завершается ненулевым кодом — красная джоба в
CI, только без клея. severity: warn и info печатают предупреждение, не
роняя прогон, — для бюджетов, которые вы ещё подбираете. Несколько гейтов
комбинируются: побеждает худший статус.
Честные цифры по построению
Два свойства делают эти гейты надёжнее обёрток-скриптов:
- Те же самые гистограммы. Гейты вычисляются по тем же HDR-гистограммам,
которые печатает итоговая сводка.
p95<500сравнивается ровно с тем p95, который вы видели в консоли, — никакого расхождения между тем, что вы читали, и тем, что проверял CI. - Громкие ошибки. Неизвестная метрика, пустой
with:, непарсящееся выражение или агрегат, не подходящий типу метрики, роняют и гейт, и прогон. Зелёный гейт всегда значит: метрика существовала, выражение распарсилось, число удержалось.
Выражения — это <агрегат><оператор><число>: агрегаты — avg, min,
max, p50, p90, p95, p99, count, rate. Какие применимы — зависит
от метрики: сэмплируемые метрики (http_req_duration, grpc_msg_rtt,
ws_msg_rtt, db_query_duration, …) принимают перцентили; счётчики —
только count; а каждое семейство длительностей автоматически порождает
метрику <family>_failed, так что rate<0.05 работает без лишней
инструментации.
Сделано для пайплайнов
Каждый гейт отдаёт структурированный результат — статус, читаемую сводку
нарушений и список violations по выражениям, — а summary JSON прогона
(perfscale run --summary-export) получает поле thresholds той же формы.
Дашборды и аннотации в PR читают результаты гейтов без парсинга stdout; на
платформе результаты гейтов показываются в прогоне рядом с метриками,
которые они оценивали.
В CI это просто «запустить тест»:
GitHub Action или
шаблоны GitLab CI выполняют конфиг
как есть, а нарушенный fail-гейт красит джобу в красный. Никаких jq,
awk и обёрток.
С чего начать
- SLO-гейты с thresholds, шаг за шагом — полный туториал: базовый прогон, синтаксис гейтов, severity, summary JSON, подключение CI.
- Справочник
std/thresholds@v1— грамматика выражений, типы метрик, формат результата. - CI/CD-интеграция — триггеры, вебхуки и рецепты для пайплайнов.
Обновляйтесь через perfscale self-update — и пусть ваш следующий зелёный
прогон что-то да значит.
