Модуль 2 · как работает prometheus · сбор метрик
Глава 2.1
Что такое
Prometheus
В этой главе разобрано, для чего нужен Prometheus и с какими данными он работает. Сначала описана его задача, затем метрика и её отличие от записи в логе, затем временной ряд и части системы. В конце одно число проходит весь путь: от счётчика в коде приложения до ответа на запрос.
- Категория
- Устройство системы
- Уровень
- Вводный
- Опирается на
- Модуль 1: мониторинг, метрики и логи
- Результат
- Схема пути данных для остальных глав модуля
§1Задача Prometheus
Пока программа работает на компьютере разработчика, её состояние видно сразу: ошибки появляются в терминале, медленный ответ заметен глазами. После запуска на сервере этого контакта нет. Сервис принимает запросы, копит очередь задач и занимает память, а разработчик узнаёт о проблеме, только когда пользователи начинают жаловаться.
Чтобы узнавать о состоянии сервиса раньше, его нужно измерять. При этом одного измерения мало. Число «в очереди 40 задач» ничего не говорит, пока неизвестно, сколько их было час назад: 38 или 2. Поэтому измерения повторяют через равные промежутки и сохраняют вместе с временем.
Медсестра по расписанию обходит палаты, измеряет температуру каждого пациента и записывает её в температурный лист вместе с временем. Врач по листу определяет, в какой час температура начала расти.
Prometheus по расписанию обходит программы, забирает у каждой числа и записывает их вместе с временем. Разработчик по этим записям определяет, в какую минуту выросло число ошибок.
Точное определение повторяет это сравнение.
Prometheusсистема мониторинга · открытый исходный код
Программа-сервер, которая регулярно забирает у других программ числовые показатели, хранит их с отметками времени и отвечает на запросы по этим данным.
Prometheus создан в компании SoundCloud в 2012 году. Сервер написан на языке Go и состоит из одного исполняемого файла.
В определении названы три действия, и сервер выполняет их по порядку. Сначала идёт сбор: раз в несколько секунд сервер запрашивает у приложения его текущие показатели. Затем хранение: каждое полученное число записывается на диск вместе с моментом, когда оно получено. После этого становятся возможны запросы: человек спрашивает, сколько запросов обработано за последний час, и сервер считает ответ по сохранённым числам.
Запросы пишут на собственном языке Prometheus, он называется PromQL. По результатам запросов сервер ещё отправляет оповещения, но в этом модуле они не разбираются: сначала нужно понять, как данные попадают в базу.
Первое из трёх действий — сбор. Поэтому следующий вопрос: какие данные Prometheus забирает у программы.
§2Какие данные собираются
Prometheus забирает у программы только числа. Они похожи на показания приборной панели автомобиля. Одометр показывает, сколько километров машина проехала за всё время. Указатель топлива показывает, сколько бензина в баке сейчас. Оба прибора показывают по одному числу, и маршрут поездки по ним восстановить нельзя.
У программы такие же приборы. Она считает, сколько запросов обработала и сколько задач ждёт в очереди. Кто отправил запрос и что в нём было, по этим числам определить нельзя. Такое число называется метрикой: это числовой показатель, который программа считает о себе сама и показывает по запросу.
Считается метрика так. Программа хранит число в своей памяти и при каждом событии увеличивает его или записывает новое значение. Отдельные события она никуда не отправляет. Prometheus раз в несколько секунд забирает то значение, которое есть в памяти на этот момент.
Два вида чисел
Одометр и указатель топлива ведут себя по-разному, и у метрик есть те же два вида. Число первого вида только растёт, как одометр: оно считает события с момента запуска программы. Такая метрика называется counter, по-русски счётчик. Число второго вида растёт и уменьшается, как указатель топлива: оно показывает текущую величину. Такая метрика называется gauge, измеритель.
В таблице четыре примера. В левом столбце вопрос о сервисе, в среднем — метрика, которая на него отвечает.
| Вопрос о сервисе | Метрика | Вид |
|---|---|---|
| Сколько запросов обработано | http_requests_total | counter: только растёт, после перезапуска программы начинается с нуля |
| Сколько запросов уложилось в 0,1 с | http_request_duration_seconds_bucket{le="0.1"} | counter: набор таких счётчиков описывает скорость ответа |
| Сколько задач ждёт в очереди | queue_length | gauge: растёт, когда задача приходит, и уменьшается, когда задача выполнена |
| Сколько памяти занимает процесс | process_resident_memory_bytes | gauge: значение в байтах на момент запроса |
Во всех четырёх строках значение метрики — одно число. Текста запроса, адреса клиента и текста ошибки в нём нет.
Подробности события в метрику не попадают. Их записывают в лог, и следующий раздел сравнивает эти два вида данных на одном примере.
§3Метрика и запись в логе
Разницу между метрикой и логом хорошо показывает магазин. Кассовый чек описывает одну покупку: что купили, во сколько, на какую сумму. Отчёт за день содержит несколько чисел: количество покупок и общую выручку. Чеков столько, сколько покупок, а число строк в отчёте от числа покупок не зависит.
Запись в логе — это чек: она описывает одно событие. Метрика — это строка отчёта: она содержит число по целой группе событий. На схеме ниже три запроса к приложению стенда записаны обоими способами. Слева строки лога, которые печатает сервер uvicorn. Справа метрика, которую получает Prometheus.
В логе три строки, по одной на запрос, и в каждой виден адрес. В метрике две строки: два успешных запроса сложены в число 2, запрос с ошибкой дал число 1. После тысячи запросов в логе будет тысяча строк, а в метрике останутся те же две строки с другими числами. Поэтому объём лога зависит от числа событий, а объём метрик — от числа групп.
Из этого следует, какие вопросы можно задать каждому виду данных. Метрика отвечает на вопрос «сколько»: сколько было ошибок и как это число менялось. Лог отвечает на вопрос «что произошло»: какой запрос вернул 404 и с какими параметрами. Найти конкретный запрос по метрике нельзя, потому что отдельных событий в ней нет.
Преобразование работает только в одну сторону. Из логов метрику получить можно: достаточно сосчитать записи со статусом 404. Из метрики лог получить нельзя: по числу 1 не определить, какой запрос вернул ошибку. Поэтому метрики и логи собирают разными системами. Документация Prometheus говорит об этом так: Prometheus собирает и обрабатывает метрики, а для логов она советует Grafana Loki или OpenSearch.
Одна строка метрики показывает число на текущий момент. Чтобы получить историю, Prometheus складывает такие числа в ряд.
§4Временной ряд
В §1 говорилось, что одно измерение мало что сообщает и нужна история. История одной величины в Prometheus называется временным рядом. Её устройство знакомо каждому, кого в детстве измеряли у дверного косяка.
Родители раз в полгода ставят отметку и пишут рядом дату. Одна отметка показывает рост сегодня. Все отметки вместе показывают, как ребёнок рос.
Prometheus сохраняет каждое полученное число вместе с временем. Одно число показывает состояние сейчас. Все числа вместе показывают, как состояние менялось.
Временной рядtime series · единица хранения Prometheus
Все сохранённые значения одной величины, расположенные по времени. Каждая запись ряда состоит из двух частей: отметки времени и значения.
Одна такая запись называется sample — отсчёт.
Так выглядит настоящий ряд. На стенде модуля Prometheus опрашивает приложение раз в 15 секунд и после каждого опроса записывает, удался ли он: 1 — удался, 0 — нет. Этот ряд называется up. Ниже восемь его отсчётов за две минуты.
Каждый столбец на схеме — один отсчёт: вверху время, внизу значение. Между соседними отсчётами 15 секунд, на стенде отклонение было не больше 4 миллисекунд. Отметку времени ставит Prometheus в момент начала опроса. Приложение время не передаёт: в §3 было видно, что в строке метрики есть только имя, метки и число.
Чем один ряд отличается от другого
У приложения стенда одна метрика http_requests_total, но в §3 у неё было две строки. Строки различались тем, что стоит в фигурных скобках. Эти пары «название — значение» называются метками. Метка уточняет, о чём число: status="404" означает, что посчитаны запросы с ответом 404.
Отсюда правило хранения: ряд определяется именем метрики и всеми метками сразу. Если отличается хотя бы одна метка, это другой ряд со своей историей. На стенде у метрики встретились три сочетания меток, поэтому рядов три.
Из правила прямо следует ограничение. Каждое новое значение метки создаёт новый ряд, а каждый ряд занимает память сервера. Пока в метках стоят метод и код ответа, рядов три. Если добавить метку с идентификатором пользователя, рядов станет столько, сколько пользователей: при тысяче пользователей до трёх тысяч. Число рядов называют кардинальностью. Чтобы она не росла, в метки записывают значения из небольшого набора, известного заранее: метод запроса, код ответа, название очереди.
Подробнее: в каком виде хранится отсчёт
Отметка времени — целое число миллисекунд, прошедших с 1 января 1970 года по UTC. Значение — число с плавающей точкой двойной точности (float64).
Соседние отсчёты одного ряда мало отличаются, и хранилище записывает только разницу между ними. По документации, на один отсчёт уходит в среднем 1–2 байта. Над числами работают сложение и другие вычисления: сумма по всем копиям сервиса, скорость роста, доля ошибок. Текст допускается только в метках.
Известно, что хранится: ряды из отсчётов. Следующий раздел называет программы, которые эти ряды создают и сохраняют.
§5Части системы
Словом «Prometheus» называют и сервер, и набор программ вокруг него. В работе участвуют как минимум две стороны, и у каждой своя роль. Внутри приложения работает клиентская библиотека: она хранит числа в памяти программы и по запросу выдаёт их в виде текста. Для Python это библиотека prometheus-client. Отдельной программой работает сервер Prometheus: он запрашивает числа, хранит их историю, отвечает на запросы и показывает веб-интерфейс.
Стрелка на схеме направлена от сервера к приложению: обмен начинает сервер, а приложение только отвечает. Почему сделано так, объясняет глава 2.5.
Кроме этих двух частей, есть ещё четыре программы. В модуле они не используются, но их названия встречаются в документации, поэтому они перечислены здесь. Exporter показывает числа чужой программы, код которой изменить нельзя: PostgreSQL, Redis, операционной системы. Pushgateway принимает числа от коротких задач, которые завершаются раньше очередного опроса. Alertmanager рассылает оповещения, которые вычислил сервер. Grafana — отдельный продукт другой компании, он строит графики по данным Prometheus.
Что внутри сервера
Сервер тоже состоит из частей. Их пять, и данные проходят через них в том же порядке, в каком в §1 шли три действия: сбор, хранение, запросы.
- Список адресов. Сервер читает файл
prometheus.ymlи узнаёт, какие программы опрашивать. - Сбор. Для каждого адреса сервер раз в интервал отправляет HTTP-запрос и разбирает ответ.
- TSDB. База временных рядов на диске сервера. Сюда записываются отсчёты.
- PromQL. Часть сервера, которая выполняет запросы к сохранённым рядам.
- Веб-интерфейс и HTTP API. Через них запросы отправляют человек и другие программы, например Grafana.
Подробнее: как TSDB хранит данные на диске
Новые отсчёты попадают в память сервера и одновременно в журнал на диске. Журнал называется WAL (write-ahead log). По нему сервер восстанавливает данные после перезапуска. Раз в два часа накопленные отсчёты записываются в отдельный блок на диске, который больше не меняется. По умолчанию данные хранятся 15 дней.
Содержимое папки с данными в контейнере стенда. Сервер работал меньше двух часов, поэтому блоков ещё нет:
chunks_head lock queries.active wal
wal — журнал, chunks_head — файлы с отсчётами из памяти. Файл lock запрещает второму серверу открыть ту же базу.
У каждого сервера Prometheus своя база. По документации, локальное хранилище не объединяется в кластер и не копируется на другие серверы. Так сервер не зависит от соседних систем и продолжает работать, когда они недоступны. Для долгого хранения Prometheus передаёт данные в отдельные системы.
Части названы по отдельности. В следующем разделе они работают вместе: одно число проходит через все пять.
§6Путь одного числа
Все понятия главы теперь можно собрать в одну цепочку. Для этого схема ниже ведёт одно число от момента, когда оно появилось в коде, до момента, когда его увидел человек. Это число 125: столько запросов GET со статусом 200 обработало приложение стенда.
В цепочке пять этапов. На первом число находится в памяти приложения, на втором становится строкой текста, на третьем его забирает сервер, на четвёртом оно попадает в базу, на пятом возвращается в ответе на запрос. Все строки на схеме взяты со стенда. Нажимайте на этапы по порядку или на кнопку «далее».
Остальные главы модуля идут по этой схеме слева направо. Глава 2.2 объясняет, откуда сервер берёт адрес api:8000. Глава 2.3 разбирает правила, по которым записан текст на этапе 2. Глава 2.4 посвящена самому опросу на этапе 3, а глава 2.5 — тому, почему запрос идёт от сервера к приложению. В главе 2.6 вся цепочка запускается на вашем компьютере.
Схема показывает, что Prometheus делает. Последний раздел главы показывает, для каких задач этого недостаточно.
§7Границы применения
На пути числа есть место, где данные могут потеряться. Приложение увеличило счётчик, а до следующего опроса программа аварийно завершилась. Значение было только в её памяти, и Prometheus его не получил. Такая потеря заложена в устройство системы: Prometheus проще и надёжнее работает во время сбоев, но не обещает, что учтёт каждое событие.
Это похоже на спидометр и чек на заправке. Спидометр показывает скорость приблизительно и работает всё время поездки. Чек точен до копейки. Скорость смотрят по спидометру, деньги считают по чекам.
Из этого получается правило выбора. Prometheus подходит, когда нужно число с историей и небольшая неточность допустима. Пример: заметить, что после обновления сервиса выросла доля ошибок, и получить оповещение. Доля ошибок — число, и Prometheus сравнит значения до обновления и после него.
Prometheus не подходит в двух случаях. Первый — точный учёт: посчитать запросы каждого клиента и выставить счёт. Часть событий теряется при падении программы, а метка с идентификатором клиента создаёт по ряду на каждого клиента. Документация приводит этот пример и советует для него другие системы. Второй случай — поиск одного события: найти запрос, который вернул ошибку, и его параметры. Метрика хранит количество ошибок, а параметры запроса есть в логах и трассах.
§8Проверьте себя
Вопрос 1В приложении одна метрика http_requests_total с метками method и status. Встретились сочетания GET 200, GET 404, POST 405. Сколько временных рядов хранит Prometheus для этой метрики с одного экземпляра приложения?
Ряд определяется именем и всеми метками. Имя одно, наборов меток три.
Верно. Каждое сочетание
methodиstatus— отдельный ряд. Меткиjobиinstanceу всех трёх одинаковые и числа рядов не меняют.Так растёт объём лога. Число рядов от числа запросов не зависит: запросы меняют только значения.
Вопрос 2Где хранится история значения http_requests_total?
Библиотека хранит только текущее значение. Страница
/metricsпоказывает одно число на ряд.Верно. История появляется на сервере: отсчёт за отсчётом, с отметкой времени начала опроса.
WAL — журнал сервера Prometheus. Приложение метрики на диск не пишет.
Вопрос 3Какую задачу документация Prometheus приводит как неподходящую?
Для таких сервисов Prometheus подходит: документация называет это его сильной стороной.
По документации, Prometheus рассчитан на работу во время сбоя.
Верно. Для учёта со стопроцентной точностью собранные данные недостаточно полны.
Вопрос 4Почему в метку не записывают идентификатор пользователя?
Значение метки — строка. Числом бывает только значение отсчёта.
Верно. Каждый ряд занимает память сервера. В метки записывают значения из небольшого набора.
Такого правила нет. Ограничения на длину меток настраиваются отдельно и по умолчанию выключены.
- Prometheus. Overview — prometheus.io/docs/introduction/overview
- Prometheus. Data model — prometheus.io/docs/concepts/data_model
- Prometheus. FAQ — prometheus.io/docs/introduction/faq
- Prometheus. Storage — prometheus.io/docs/prometheus/latest/storage
- Стенд модуля: Prometheus 3.5.0, prometheus-client 0.26.0; запросы выполнены 29.09.2026
