1. Философия мониторинга: фундаментальные различия между метриками и логами
Философия мониторинга: фундаментальные различия между метриками и логами
Во время пиковой нагрузки платежный шлюз крупного e-commerce проекта начинает отклонять каждую третью транзакцию. Трафик составляет запросов в секунду. Если система алертинга опирается на парсинг текстовых логов для вычисления процента ошибок в реальном времени, кластер логирования неизбежно исчерпает ресурсы CPU и дискового ввода-вывода раньше, чем окончательно откажет само приложение. Попытка использовать инструмент, предназначенный для глубокой отладки, в качестве измерителя пульса системы — одна из самых частых и дорогих архитектурных ошибок.
Построение надежной системы наблюдения (observability) для высоконагруженных проектов требует жесткого разделения телеметрии по ее физической природе и стоимости обработки. В основе этого разделения лежит понимание того, как данные рождаются, сколько они весят и на какие вопросы способны ответить.
Природа логов: дискретный контекст
Лог — это неизменяемая запись о конкретном дискретном событии, произошедшем в системе в определенный момент времени. Фундаментальная ценность лога заключается в его высокой детализации и способности сохранять уникальный контекст транзакции.
Когда пользователь пытается авторизоваться, приложение генерирует строку (или JSON-объект), которая содержит метку времени, уровень важности (INFO, ERROR), идентификатор пользователя, его IP-адрес, User-Agent, идентификатор сессии и, в случае сбоя, полный stack trace ошибки.
Эта детализация порождает главную проблему логов — их объем прямо пропорционален пользовательскому трафику.
Если один запрос генерирует в среднем килобайт логов, то при нагрузке в запросов в секунду микросервис будет производить около мегабайт данных каждую секунду. В сутки это почти гигабайта сырого текста только от одного компонента системы. Чтобы эти данные можно было искать, их необходимо индексировать (например, в Elasticsearch), что удваивает или утраивает требования к дисковому пространству и требует огромных вычислительных мощностей.
Поиск по логам — это всегда ресурсоемкая операция. Даже при наличии индексов, запрос вида «посчитай количество 500-х ошибок за последний час» заставляет систему логирования поднять с диска тысячи документов, отфильтровать их и произвести агрегацию "на лету". Именно поэтому логи абсолютно не подходят для построения дашбордов реального времени и систем мгновенного оповещения. Их истинное предназначение — расследование инцидентов (Root Cause Analysis), когда факт сбоя уже зафиксирован, и инженеру необходимо понять, почему он произошел.
Природа метрик: непрерывное измерение
Метрика — это числовое представление состояния системы, измеренное на интервалах времени. В отличие от логов, метрики не фиксируют каждое отдельное событие. Они агрегируют события в момент их возникновения.
!Агрегация событий во временные ряды
В экосистеме Prometheus метрика представляет собой временной ряд (Time Series), который идентифицируется именем и набором пар ключ-значение, называемых лейблами (labels). Каждая точка данных (sample) в этом временном ряду состоит всего из двух элементов:
Независимо от того, обработал ли сервер запрос или запросов за прошедшую секунду, в базу данных временных рядов (TSDB) будет записано ровно байт полезной нагрузки, отражающей текущее значение счетчика. Объем генерируемых метрик зависит не от пользовательского трафика, а от количества измеряемых параметров и частоты их сбора (scrape interval).
Это свойство делает метрики невероятно дешевыми для хранения и молниеносно быстрыми для запросов. Построение графика количества ошибок за неделю по метрикам занимает миллисекунды, так как базе данных нужно лишь прочитать последовательность чисел из заранее известного временного ряда, а не сканировать миллионы текстовых строк.
Метрики идеально отвечают на вопросы «Что происходит?» и «Насколько все плохо?». Они служат фундаментом для систем алертинга и визуализации, позволяя мгновенно реагировать на деградацию сервиса. Однако за эту скорость приходится платить потерей контекста: глядя на график, показывающий скачок ошибок, невозможно узнать идентификатор конкретного пользователя, который с ними столкнулся.
Проблема кардинальности (Cardinality)
Глубокое понимание метрик невозможно без осознания концепции кардинальности. Кардинальность — это количество уникальных временных рядов в системе мониторинга.
Каждая уникальная комбинация имени метрики и ее лейблов создает в памяти Prometheus новый, независимый временной ряд. Формула расчета максимальной кардинальности для одной метрики выглядит как произведение количества возможных значений каждого лейбла:
где — количество уникальных значений для -го лейбла.
Рассмотрим метрику http_requests_total, которая считает количество входящих HTTP-запросов. Если мы добавим к ней лейбл method (GET, POST, PUT, DELETE — значения) и лейбл status (200, 400, 404, 500 — допустим, вероятных значений), общая кардинальность этой метрики составит временных рядов. Это абсолютно безопасное значение, которое не окажет заметного влияния на производительность TSDB.
Стремясь компенсировать отсутствие контекста в метриках, инженеры часто совершают критическую ошибку: они начинают добавлять в качестве лейблов данные с неограниченным множеством значений (unbounded dimensions).
!Взрыв кардинальности при добавлении неограниченных лейблов
Если к той же метрике http_requests_total добавить лейбл user_id (идентификатор пользователя) или client_ip (IP-адрес клиента), произойдет так называемый «взрыв кардинальности» (cardinality explosion). При наличии миллиона активных пользователей Prometheus будет вынужден создать и поддерживать в оперативной памяти отдельных временных рядов только для одной метрики.
Каждый новый временной ряд требует выделения памяти, создания индексов и регулярного сброса данных на диск. Взрыв кардинальности приводит к экспоненциальному росту потребления RAM сервером Prometheus (часто приводя к OOM Killer — принудительному завершению процесса операционной системой) и резкому замедлению выполнения запросов PromQL.
Золотое правило проектирования систем на базе метрик гласит: значения лейблов должны принадлежать к строго ограниченному, небольшому множеству (bounded dimensions). Коды ответов HTTP, названия дата-центров, версии релизов, имена микросервисов — это хорошие кандидаты для лейблов. ID транзакций, email-адреса, полные URL-пути с параметрами запроса — это данные, которым место исключительно в логах.
Синергия: рабочий процесс расследования инцидентов
Противопоставление логов и метрик имеет смысл только на этапе проектирования хранилищ. В реальной эксплуатации они образуют единый конвейер наблюдения, где сильные стороны одного инструмента компенсируют слабости другого. Эффективный процесс локализации и устранения сбоя (troubleshooting) строится в виде воронки, идущей от общего к частному.
Первым срабатывает алерт, настроенный на метрику. Например, правило в Alertmanager фиксирует, что доля ответов с кодом 5xx превысила за последние две минуты. Метрика обеспечивает минимальное время реакции (Time To Detect, TTD), так как вычисление процента по числовым рядам происходит практически мгновенно.
Инженер дежурной смены переходит по ссылке из алерта на дашборд (Grafana). Дашборд, опираясь на те же метрики, позволяет локализовать проблему на уровне архитектуры. Используя агрегации по лейблам, инженер видит, что всплеск ошибок наблюдается только в сервисе checkout, только в дата-центре eu-central-1 и только для HTTP-метода POST. Метрики сузили зону поиска с тысяч серверов до одного конкретного компонента.
Только на этом этапе инженер обращается к системе логирования (например, ELK Stack или Loki). Вместо того чтобы искать иголку в стоге сена из миллиардов строк, он формирует узконаправленный запрос: показать логи сервиса checkout в дата-центре eu-central-1 за последние пять минут, отфильтрованные по уровню ERROR.
Система логирования быстро возвращает несколько десятков строк, в которых содержится искомый контекст: Connection refused to database pg-master-03. Метрики указали путь, логи назвали конкретную причину.
Пограничные случаи и антипаттерны
В высоконагруженных системах граница между логами и метриками иногда размывается, порождая специфические архитектурные решения и антипаттерны, о которых необходимо знать.
Антипаттерн: Log-based метрики в критическом пути
Существует класс инструментов (например, mtail или модули парсинга в Logstash), которые читают поток логов, извлекают из них числа с помощью регулярных выражений и экспортируют их в формате метрик Prometheus.Этот подход оправдан при работе с legacy-системами («черными ящиками»), код которых невозможно изменить для прямой отправки метрик. Однако использование log-based метрик для современных микросервисов является антипаттерном. Парсинг текста — дорогая операция, вносящая задержку. Если приложение пишет логи на диск асинхронно, а демон парсинга читает их с отставанием, метрики теряют свою главную ценность — актуальность в реальном времени. Инструментация (добавление метрик) должна происходить непосредственно в коде приложения на этапе обработки запроса.
Сэмплирование: почему метрики нельзя прореживать
Когда объем логов начинает угрожать стабильности инфраструктуры, инженеры применяют сэмплирование (sampling) — сохраняют не все логи, а лишь определенный процент (например, успешных запросов и ошибочных).Сэмплирование логов — стандартная практика, но применять сэмплирование к метрикам категорически запрещено. Если приложение будет инкрементировать счетчик http_requests_total только для каждого десятого запроса, любые производные вычисления (например, рейт запросов в секунду) станут математически недостоверными. Метрики изначально спроектированы так, чтобы быть легковесными, поэтому они должны отражать происходящих событий.
Проблема усреднения (The Flaw of Averages)
При проектировании метрик часто возникает соблазн свести сложные процессы к одному числу. Классический пример — вычисление среднего времени ответа (Average Latency).Представим, что запросов обрабатываются за миллисекунд, а один запрос — за миллисекунд (таймаут базы данных). Среднее время ответа составит около миллисекунд. Глядя на эту цифру, инженер может решить, что система работает нормально, полностью игнорируя тот факт, что пользователей сталкивается с катастрофической деградацией сервиса.
Обычные счетчики (Counters) и датчики (Gauges) не способны корректно отразить распределение данных. Для решения этой проблемы в метрических системах существуют специальные, более сложные структуры данных, которые позволяют фиксировать перцентили и распределение задержек, не скатываясь при этом на уровень детализации сырых логов.
Понимание того, что метрики — это не просто числа, а агрегированные векторы состояния системы, позволяет проектировать мониторинг, который выдержит любую нагрузку. Логи остаются незаменимым инструментом для глубокого анализа, но на передовой линии обороны высоконагруженных проектов всегда стоят легковесные, быстрые и математически строгие временные ряды.