Короткий ответ
Кардинальность метрики — это количество уникальных комбинаций значений её labels, то есть количество отдельных временных рядов, которые она порождает; высокая кардинальность (например, label со значением user_id или request_id) приводит к взрывному росту числа рядов, потребления памяти и диска в Prometheus.
Как это работает подробнее
каждая уникальная комбинация значений labels — это отдельный временной ряд в TSDB, который Prometheus хранит и индексирует независимо. Если добавить в метрику label с миллионом возможных значений (например, user_id), то вместо одной метрики с разумным числом рядов получится до миллиона отдельных рядов, что резко увеличивает потребление памяти (в первую очередь — индекса TSDB).
Пример кода
query.promql
# Опасно: request_id практически уникален для каждого запроса
http_requests_total{request_id="a1b2c3", service="checkout"}
# Безопасно: ограниченный набор значений label
http_requests_total{method="POST", status="200", service="checkout"}Что использовать на практике
- Практика. labels должны иметь ограниченное и предсказуемое количество значений — например,
method,status_code,region,serviceобычно безопасны, аuser_id,email,request_id, полный URL с параметрами — нет. Для таких "уникальных на запрос" идентификаторов данные нужно класть в логи или трейсы, а не в labels метрики. - Практика. Запрос
count({__name__="http_requests_total"})после первого варианта инструментации может показать миллионы рядов и постоянно растущее потребление памяти Prometheus, тогда как второй вариант даёт стабильное и предсказуемое число рядов независимо от объёма трафика.
Подводные камни
- Частые ошибки. добавлять в labels динамические значения "для удобства фильтрации", не оценив количество уникальных значений; не мониторить саму кардинальность (
prometheus_tsdb_symbol_table_size_bytes,count by (__name__)(...)) и обнаруживать проблему только когда Prometheus начинает падать по памяти (OOM); включать в URL-путь как label сырой путь с параметрами запроса вместо шаблона маршрута (/users/123вместо/users/:id).