Инструментирование своего приложения
Урок про то, как заставить собственное приложение отдавать метрики Prometheus.
Инструментирование — это добавление в код приложения метрик с помощью клиентской библиотеки, чтобы оно само публиковало их на endpoint
/metrics.
Экспортеры дают метрики хоста и баз, но про бизнес-логику знает только ваше приложение: сколько заказов оформлено, сколько писем отправлено, как долго идёт обработка. Эти метрики добавляете вы сами.
Клиентские библиотеки
Под популярные языки есть официальные библиотеки (Python, Go, Java, Node.js и др.). Они дают объекты Counter, Gauge, Histogram и сами поднимают endpoint /metrics. Логика везде одинакова: создать метрику, обновлять её в коде, выставить endpoint.
Пример логики на чистом Python
Чтобы прочувствовать суть без внешних библиотек, смоделируем counter и histogram стандартными средствами. Реальный код использовал бы prometheus_client, но идея та же.
from collections import Counter
# counter: считаем запросы по статусу
requests_total = Counter()
def handle(status):
requests_total[status] += 1
for s in ["200", "200", "500", "200", "404"]:
handle(s)
for status, count in sorted(requests_total.items()):
print(f'http_requests_total{{status="{status}"}} {count}')Вывод:
http_requests_total{status="200"} 3
http_requests_total{status="404"} 1
http_requests_total{status="500"} 1Гистограмма задержек вручную
buckets = [0.1, 0.5, 1.0]
samples = [0.05, 0.2, 0.2, 0.8, 1.5]
counts = {b: 0 for b in buckets}
inf = 0
for s in samples:
placed = False
for b in buckets:
if s <= b:
counts[b] += 1
placed = True
break
if not placed:
inf += 1
for b in buckets:
print(f'le="{b}" count={counts[b]}')
print(f'le="+Inf" count={inf}')Вывод:
le="0.1" count=1 le="0.5" count=2 le="1.0" count=1 le="+Inf" count=1
Как работает под капотом
Клиентская библиотека держит метрики в памяти процесса. Counter инкрементируется в коде, histogram при каждом наблюдении кладёт значение в подходящую корзину и обновляет _sum и _count. На запрос /metrics библиотека сериализует текущее состояние в текстовый формат Prometheus, а scrape забирает снимок. Никакой истории приложение не хранит — она строится в TSDB.
Частые ошибки
- Лейблы с высокой кардинальностью. URL с ID или email в лейбле метрики порождают тысячи рядов — кладите такое в логи.
- Создавать метрику внутри обработчика. Метрики объявляют один раз при старте, иначе теряется накопленное.
- Забыть endpoint /metrics. Без него Prometheus нечего скрейпить.
Итог
- Инструментирование добавляет бизнес-метрики через клиентскую библиотеку.
- Counter растёт в коде, histogram кладёт наблюдения в корзины.
- Избегайте высокой кардинальности лейблов и объявляйте метрики один раз.