В IT-мире мониторинг инфраструктуры тесно связан с внедрением практик DevOps. Один из таких инструментов — Prometheus, система мониторинга и сбора метрик с открытым исходным кодом. Чтобы раскрыть её потенциал, необходимо освоить язык запросов PromQL.
Из статьи вы узнаете, как выбирать временные ряды, считать скорость счетчиков и агрегировать результаты. Эти навыки необходимы клиентам хостинга и облачных серверов, чтобы в реальном времени видеть нагрузку на ресурсы, вовремя замечать падение сайтов и не переплачивать за лишние мощности. В материале представлена основная информация об инструменте и путь от архитектуры до отладки.
Основные тезисы статьи
-
PromQL запрашивает временные ряды Prometheus по именам метрик и прикрепленным меткам.
-
Тип возвращаемого результата напрямую зависит от используемого селектора и выбранного диапазона времени.
-
Функцию rate применяют исключительно к счетчикам с обязательным учетом их сбросов (resets).
-
Различные агрегирующие функции PromQL с модификаторами by и without определяют итоговые метки результата.
-
Слишком широкие селекторы и высокая мощность множества (количество уникальных рядов) существенно замедляют или обрывают запросы.
-
Сложный запрос надежнее собирать, фильтровать и проверять последовательно по шагам.
PromQL: что это
PromQL, или Prometheus Query Language, представляет собой язык запросов, который был создан специально для работы с метриками в системе Prometheus. И если классический SQL в большей степени оперирует привычными таблицами, то этот инструмент изначально спроектирован для взаимодействия с временными рядами, непрерывными потоками телеметрии, и каждое значение здесь жестко привязано к моменту времени.
Что такое сам Prometheus и зачем он нужен? Prometheus — это бесплатная система мониторинга, своего рода база данных для метрик сервера. По умолчанию она работает в фоновом режиме: опрашивает ваши сервисы и собирает цифровые показатели — загрузку CPU, свободна ли память, есть ли ошибки. Чтобы развернуть его, нужно установить готовый бинарный файл или запустить Docker-контейнер.
Зачем вам нужен PromQL? Собрать метрики — это хорошо, но дальше их нужно читать. PromQL как раз и служит переводчиком между вами и базой данных. С его помощью вы превращаете сырые цифры в конкретные ответы:
-
Сколько памяти прямо сейчас свободно на VPS?
-
Сколько запросов в секунду падают с ошибкой 500?
-
Не перегружен ли процессор в пиковые часы?
Результат этих запросов выводится на графиках в Grafana или отправляет вам уведомление в Telegram, если сайт лёг.
Изучив, как работает язык запросов Prometheus PromQL, вы сможете извлекать данные и применять к ним математические операции, фильтровать по атрибутам и вычислять производные показатели на лету. Вы отправляете query Prometheus, а база возвращает точный срез: от текущего потребления памяти сервером до количества ошибок за последний час.
Результат вычислений визуализируется в дашбордах или используется менеджером для отправки алертов. Здесь вместо объединений таблиц в привычном понимании реляционных баз применяется механизм векторного сопоставления (vector matching) для сравнения многомерных массивов.
Модель данных Prometheus
Перед тем как писать запросы PromQL, следует понять внутреннюю структуру хранения. В основе модели баз данных Prometheus time series лежит временной ряд, который идентифицируется двумя элементами: названием и набором пар ключ-значение, которые называются метками — labels.
Например, http_requests_total{method="GET", status="200"} — это один уникальный временной ряд. Если изменится хотя бы одна метка (скажем, status="500"), система создаст абсолютно новый, независимый ряд. Внутри каждого такого ряда хранятся сэмплы. Каждый из них содержит значение и отметку времени — timestamp. Значение может быть числом с плавающей точкой или native histogram.
Поведение этого числа зависит от типа метрики:
-
Counter/счетчик. Монотонно увеличивающееся значение, которое может сбрасываться при перезапуске или другой причине reset.
-
Gauge/измеритель. Показатель способен как увеличиваться, так и уменьшаться. Применяется для оценки уровня использования CPU или свободной памяти.
-
Histogram/гистограмма. Собирает наблюдения по диапазонам значений и считает их количество. В classic histogram данные представлены в том числе bucket-рядами; гистограммы используют для анализа распределения, например времени ответа приложения.
Когда вы поймете эту концепцию, то перестанете воспринимать метрику как статичную таблицу и начнете работать с ней как с многомерным потоком.
Типы выражений PromQL
Любому человеку, изучающему PromQL синтаксис, важно различать базовые типы выражений, с которыми оперирует язык. Каждый запрос при выполнении возвращает результат одного из четырех типов:
-
Instant vector/мгновенный вектор. Набор временных рядов, содержащий по одному значению для каждого ряда на момент оценки выражения. Пример такого запроса: http_requests_total{instance="app1"}. Это готовый снимок метрик для табличного вида.
-
Range vector/диапазонный вектор. Набор временных рядов, для каждого из которых содержит выборку значений за выбранный временной интервал. В PromQL обозначение интервала указывается в квадратных скобках.
-
Scalar/скаляр. Одиночное числовое значение с плавающей точкой без меток и привязки к временному ряду. Может использоваться в операциях со скалярами и в качестве аргумента некоторых функций.
-
String/строка. Текстовое значение — редко используется в обычных запросах и вычислениях PromQL.
Эти типы могут отличаться по назначению: instant vector подходит для текущего состояния и агрегаций, а range vector обязателен для расчетных функций скорости роста.
Селекторы и фильтры по labels
Самый простой и доступный инструмент извлечения метрик — прямое указание имени: http_requests_total. Если выполнить запрос в таком виде, система вернет данные по всем приложениям и нодам. Чтобы отфильтровать лишний шум, применяют селекторы с фильтрацией по меткам.
В PromQL поддерживаются четыре основных оператора соответствия для labels:
-
= — точное совпадение строки;
-
!= — неравенство (исключение значения);
-
=~ — соответствие регулярному выражению;
-
!~ — отрицание регулярного выражения.
Пример сложной фильтрации:
http_requests_total{environment=~"staging|testing|(dev.*)", method!="GET"}
В данном случае извлекаются записи, где метка environment соответствует одному из окружений, и исключаем все HTTP-запросы с методом GET. Вы можете передавать сколько угодно меток через запятую — внутри фильтра они логически объединяются по правилу AND.
Важно: селектор без имени метрики должен содержать хотя бы один matcher, который не допускает пустое значение. Поэтому {job=~".*"} или {method!="GET"} без имени метрики использовать нельзя. Слишком широкие селекторы могут возвращать большое количество рядов и увеличивать нагрузку на Prometheus.
Диапазоны, offset и subquery
Чтобы проанализировать изменения во времени, PromQL запросы можно дополнять выбором интервала временного окна, смещением временной шкалы и вложенными вычислениями.
Для превращения мгновенного вектора в диапазонный применяется квадратная скобка в конце выражения: http_requests_total{job="prometheus"}[5m].
Здесь [5m] задает пятиминутное окно: для каждого ряда выбираются точки данных за этот интервал относительно момента оценки запроса.
Если вам требуется сравнить текущие показатели с историческими данными (например, за прошлую неделю или вчерашний день), используется оператор offset: http_requests_total offset 1d. Он смещает временную рамку запроса на указанный период назад. Модификатор offset указывается непосредственно после селектора, к которому применяется.
Для построения сложных временных конструкций применяются subqueries — так называемые вложенные запросы. Они позволяют получить диапазон значений, вычисляя мгновенный запрос на заданном временном интервале с указанным шагом. Синтаксис субзапроса выглядит так:
rate(http_requests_total[5m])[30m:1m]
В этой записи [30m:1m] означает: взять окно в 30 минут и вычислять значения функции с шагом в 1 минуту. Субзапросы незаменимы для функций вроде max_over_time, но требуют осторожности из-за нагрузки на процессор.
Операторы и vector matching
Язык PromQL предоставляет стандартный набор математических, сравнительных и логических операторов PromQL. С их помощью можно выполнять базовую арифметику со скалярами и векторами:
metric{tag="value"} * 10 >= 50
При работе с несколькими временными рядами вступают в силу правила vector matching. В отличие от SQL с его командами JOIN, PromQL выполняет бинарные операции на основе совпадения меток.
Существует два основных типа сопоставления:
-
One-to-one — один к одному. Применяется по умолчанию. PromQL сопоставляет пары рядов с одинаковым набором labels. Если соответствующего ряда нет, элемент не попадает в результат.
-
Many-to-one и one-to-many. Используются, когда одной стороне соответствуют несколько рядов другой. Для явного указания такого сопоставления применяются group_left и group_right. group_left используют, когда несколько рядов слева сопоставляются с одним рядом справа, а group_right — когда несколько рядов справа сопоставляются с одним рядом слева.
Если после применения правил сопоставления нескольким рядам с одной стороны соответствуют несколько рядов с другой, возникает ошибка many-to-many. group_left и group_right не разрешают произвольное many-to-many-сопоставление.
Для точной настройки сопоставления используются модификаторы:
-
on(label_list) — сопоставлять ряды только по указанным меткам;
-
ignoring(label_list) — игнорировать указанные метки при поиске соответствующих рядов.
Например:
http_requests_total * on(instance) group_left(role) node_meta
Здесь on(instance) задаёт метку, по которой сопоставляются ряды, а group_left(role) позволяет перенести метку role из правого вектора в результат левой стороны.
Агрегации
Агрегация — способ комбинирования несколько графиков или метрик в одну цельную единицу. Когда приложение работает в десятках подах или контейнерах, анализировать каждый поток отдельно неэффективно. В PromQL операторы агрегации вычисляют итоговые показатели по вектору прямо во время выполнения запроса.
Основные агрегирующие функции PromQL включают:
-
sum — суммирование значений;
-
avg — расчет среднего арифметического;
-
min/max — поиск крайних показателей;
-
count — подсчет количества рядов в выборке;
-
topk/bottomk — выборка N наибольших или наименьших элементов.
По умолчанию агрегатор объединяет все элементы входного instant vector в один элемент результирующего instant vector без исходных меток. Чтобы сохранить контекст и структуру метрик, применяются модификаторы by и without:
-
Модификатор by оставляет в итоговом результате только указанные метки:
sum by (app, instance) (http_requests_total)
-
Модификатор without исключает конкретные метки, сохраняя все остальные:
sum without (instance) (http_requests_total)
С помощью этих операторов вы можете легко группировать данные по регионам, подам, типам HTTP-ошибок и убирать лишнюю детализацию конкретных нод.
rate, irate и increase
Счетчики в Prometheus — это монотонно возрастающие величины. Анализировать их абсолютные значения не имеет смысла, так что разработчиков интересует интенсивность событий: для обработки таких показателей применяются PromQL функции вычисления динамики.
Базовая функция rate рассчитывает среднее число событий в секунду на выбранном временном отрезке:
rate(http_requests_total{app="nginx"}[5m])
При расчёте rate Prometheus учитывает сбросы счетчика, поэтому перезапуск сервиса не воспринимается как обычное уменьшение значения. Конструкция PromQL rate принимает исключительно диапазонный вектор (range vector), сглаживает кратковременные колебания и показывает среднюю скорость изменения за выбранное окно.
Для быстрого обнаружения кратковременных всплесков трафика применяется irate. В отличие от rate, эта функция вычисляет мгновенную скорость по последним двум точкам внутри временного окна. Она реагирует на кратковременные изменения быстрее rate, поэтому подходит для выявления резких всплесков.
Если же требуется узнать абсолютное количество событий за период, используется increase. Например, она подскажет, сколько ошибок произошло за прошедшие сутки. Математическая связь между ними очевидна: rate(metric[1h]) дает то же значение, что и выражение increase(metric[1h])/3600.
Для gauge применяются delta и deriv. Функция delta показывает разницу между начальным и конечным значениями за выбранный период:
delta(node_memory_MemAvailable_bytes[1h])
Функция deriv вычисляет производную значения по времени методом линейной регрессии:
deriv(node_memory_MemAvailable_bytes[1h])
Обе функции принимают range vector.
Практические примеры запросов
Составлять выражения с нуля бывает непросто. Ниже рабочие PromQL example — примеры запросов, которые перекрывают ключевые задачи мониторинга. В примерах используются метрики стандартных модулей экспорта, поэтому перед применением запросов нужно заменить их на фактические имена метрик вашей системы.
-
Доля ошибок/Error Rate. Расчет процента сбоев (коды 5xx) от общего потока за последние 5 минут:
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) * 100
-
Анализ задержки ответов/Latency Quantile. Оценка 95-го перцентиля времени обработки HTTP-запросов через гистограммы:
histogram_quantile(0.95, sum by (le)
(rate(http_request_duration_seconds_bucket[5m])))
-
Загрузка процессора и нагрузка на сервер. Вычисление активного потребления CPU с исключением времени простоя (idle):
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Этот показатель отражает, насколько высока нагрузка на сервер в пиковые часы.
-
Использование оперативной памяти. Отслеживание процента задействованной RAM на целевой ноде:
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
-
Метрики контейнеризации. Если на хосте развернуты контейнеры Docker, отслеживать расход ресурсов отдельными сервисами поможет следующий запрос:
sum(container_memory_working_set_bytes{container!=""}) by (container)
Развернуть тестовое окружение для проверки таких показателей поможет развернутая установка Docker на Ubuntu.
-
Проверка доступности и аптайм сайта. Мониторинг доступности узлов через Blackbox Exporter для контроля показателей SLA:
probe_success{job="blackbox_http"} == 0
Запрос возвращает цели, для которых probe_success равен 0, то есть проверка доступности завершилась неуспешно.
Эти проверенные PromQL примеры запросов помогут вам быстро сформировать базовый дашборд в Grafana и настроить правила оповещений.
Как отлаживать PromQL
Сложные вычисления в PromQL редко отрабатывают с первого раза без ошибок. Если запрос возвращает пустой вектор или неверные значения, отладку следует выполнять последовательно, разбирая сложную цепочку на отдельные компоненты.
Алгоритм локализации проблем:
-
Проверьте базовый селектор. Выполните запрос без функций и дополнительных операторов, например http_requests_total. Если выборка пустая, проблема в наименовании метрики или отсутствии сбора данных Prometheus.
-
Снимите жесткие фильтры. Убирайте метки по одной. Ошибка часто кроется в опечатке значения метки или использовании точного равенства (=) вместо регулярного выражения (=~).
-
Проверьте тип вектора. Функции rate и increase принимают на вход только range vector (с временным окном в квадратных скобках [5m]). Передача мгновенного вектора вызовет синтаксическую ошибку.
-
Изолируйте векторное сопоставление. При ошибках в бинарных операциях (/, *, +) выполните левую и правую части выражения отдельно. Посмотрите на наборы меток: если в них нет полного совпадения, добавьте модификаторы on() или ignoring().
-
Проверьте cardinality и соответствие рядов. Если после on() или ignoring() несколько рядов с одной стороны сопоставляются с несколькими рядами с другой, возникнет ошибка many-to-many. Уточните метки или используйте group_left/group_right, если действительно требуется many-to-one или one-to-many.
-
Используйте встроенную консоль. Проверяйте гипотезы во вкладке Table веб-интерфейса Prometheus, а не на графике. Это позволяет сразу увидеть точные timestamp и набор возвращаемых тегов.
Производительность и recording rules
Выполнение тяжелых запросов по большим массивам данных при каждой загрузке дашборда Grafana с запросами PromQL или проверке правил алертинга создает критическую нагрузку на сервер мониторинга. Анализ миллионов сэмплов с высокой cardinality — например, с уникальными IP-адресами или ID пользователей в метках, может приводить к значительной нагрузке на Prometheus и таймаутам..
Для решения этой проблемы применяются Recording Rules. Они позволяют Prometheus предвычислять сложные и часто запрашиваемые выражения в фоновом режиме по расписанию и сохранять результат в виде нового временного ряда.
Преимущества использования recording rules — правил записи:
-
Ускорение дашбордов. Загрузка готового предвычисленного ряда обычно требует меньше вычислений, чем повторный расчёт исходного выражения.
-
Снижение нагрузки на CPU и RAM. База данных вычисляет тяжелую агрегацию один раз в интервал (например, каждые 15 секунд), а не при каждом обращении пользователей.
-
Упрощение синтаксиса. В конечных запросах и правилах алертов используется простое имя новой метрики вместо длинной цепочки функций.
Пример конфигурации правила записи в YAML:
YAML
groups:
- name: http_rules
rules:
- record: job:http_requests_total:rate5m
expr: sum(rate(http_requests_total[5m])) by (job)
В наименовании созданной метрики принято соблюдать соглашение: level:metric:operations (в примере: уровень агрегации job, исходная метрика http_requests_total, выполненная операция rate5m).
Правильная оптимизация через правила записи и контроль cardinality — важнейший шаг для построения масштабируемой и отказоустойчивой системы мониторинга.
Освоив базовые конструкции PromQL, вы можете постепенно переходить от простых запросов к сложным дашбордам, алертам и оптимизации мониторинга.