PromQL посчитал все instance: почему bool меняет результат count
Нужно показать число доступных targets. Кто-то написал count(up == bool 1), получил общее количество серверов и решил, что все они работают. Проблема становится заметной, когда один target падает: значение панели не меняется. Выражение корректно синтаксически, но сочетает две разные операции не так, как ожидал автор.
Сравнение в PromQL без bool обычно фильтрует элементы. Сравнение с bool оставляет подходящие для операции серии и превращает значения в ноль или единицу в зависимости от результата сравнения. Count считает количество элементов в векторе, а не сумму их значений. Поэтому нулевая серия тоже попадает в count.
Разобрать маленький набор
Представим три target с up равными 1, 1 и 0. У выражения up == 1 остаются две серии. У up == bool 1 сохраняются три серии со значениями 1, 1 и 0. Значит, count второго результата даёт три, а sum — два. Для количества доступных целей подходят обе следующие формы с разным ходом рассуждения:
count(up{job="api"} == 1)
sum(up{job="api"} == bool 1)
У этих форм есть существенное различие: если все имеющиеся targets недоступны, фильтр up == 1 оставит пустой вектор, и count не покажет обычный ноль. Bool сохраняет нулевые элементы, поэтому sum второй формы вернёт 0. Если нужен именно числовой индикатор доступности при all-down, выбирайте сумму. Если исчезли сами targets, обе формы требуют отдельного контроля отсутствия данных.
У up значения уже представлены нулём и единицей, поэтому часто достаточно sum(up{job="api"}). Но в более общем сравнении bool полезен: например, превратить числовой порог в индикатор выполнения условия. Главное — дальше применять операцию, которая соответствует этому индикатору.
Если нужен процент доступных targets, числитель и знаменатель должны относиться к одному набору. Деление суммы up на count(up) даёт долю доступных среди обнаруженных targets. Оно не обнаружит сервер, который полностью исчез из service discovery: такого элемента в текущем знаменателе уже нет. Для контроля ожидаемого количества нужен отдельный источник ожиданий или правило обнаружения.
Смотреть промежуточный вектор
Перед агрегацией откройте результат в табличном виде. Проверьте labels и значения для одного доступного и одного недоступного instance. Затем добавьте count или sum и убедитесь, что исчезновение меток при агрегации соответствует нужному уровню обзора. Для нескольких сервисов, например, понадобится by(job) или другой выбранный разрез.
Не заменяйте этим правилом все сравнения в алертах. Алерт с выражением, возвращающим серию со значением ноль, всё ещё может считаться активным: для алертинга важен факт присутствия элемента результата. Если используете bool внутри алерт-выражения, убедитесь, что последующее условие действительно отфильтровывает ложный случай.
Проверка на трёх значениях 1, 1, 0 занимает мало времени и сразу показывает разницу между числом серий и суммой индикаторов. Её полезно повторять при review запросов, где рядом встречаются bool, count и доли. Так синтаксически правильный запрос не превращается в панель, которая остаётся зелёной после отказа.
Продолжить практику
Одно выражение или правило становится полезным, когда связано с конкретным действием инженера. В программе курса «Prometheus и Grafana: мониторинг и observability» — метрики учебного сервиса, exporters, обзорный и диагностический дашборды, SLI/SLO и алерты с инструкциями. Практика включает воспроизведение отказа или роста задержек и расследование по сигналам системы. Это продолжение для тех, кто хочет собрать мониторинг, по которому можно принимать решения во время сбоя.
Источник: официальная документация.
Другие задачи по теме: Метрики и уведомления без неверных выводов.
Продолжить на практике
- Prometheus и Grafana: мониторинг и observability ↗
Замечайте сбои до жалоб пользователей. Соберите мониторинг приложения: метрики Prometheus, запросы PromQL, дашборды Grafana и алерты, по которым понятно, что делать. Итог — наблюдаемый сервис и разбор учебного инцидента.
