Однажды мне понадобилось внедрить метрики в сервисы своей команды. С самого начала я не понимал, что именно хочу получить: одно дело — прикрутить библиотеку и нарисовать графики, другое дело — показывать осмысленные данные.

Мне нужен был гайд, который сочетает эти две вещи: сначала «почему так принято», а затем — «как правильно делать». В результате такой гайд мне пришлось написать самому. Его цель — объяснить разработчикам с любым бэкграундом, что такое метрики, как правильно о них думать и осмысленно использовать. Сначала гайд жил во внутренней документации Точки, но я решил сделать его публичным — возможно, кому-то этот опыт будет полезен. Разбираться будем с Prometheus и Grafana. Если у вас другой стек — не страшно. Мы затронем и фундаментальные темы: например, перцентили, производные и кардинальность.

Гайд будет выходить как цикл статей. Сначала посмотрим на архитектуру: как собираются метрики и где хранятся. Дальше разберемся с типами метрик — они не так просты, как кажется. Потом придется немного отвлечься на математику (но только с инженерной точки зрения!). И, наконец, научимся писать запросы, но не просто так: сразу посмотрим на разные грабли и неочевидные моменты.

Какие статьи выйдут в цикле:

  1. Потерянное введение.

  2. Prometheus.

  3. Перцентили для чайников.

  4. PromQL.

Прежде чем подключать библиотеки, поднимать сервера и писать запросы, давайте восстановим справедливость и найдем введение, которого мне не хватило при изучении метрик. В этой статье мы определимся, какую вообще решаем задачу, и почему решение такое непривычное.

Здравый смысл

Вот захотели вы собирать разные метрики, «чтобы было видно все, что происходит в сервисах». Теперь задайте себе и команде важные вопросы:

  • А как это вообще сделать?

  • А что именно хочется увидеть в результате?

  • Как решают эту задачу другие люди?

Чтобы не придумывать свой велосипед, можно изучить общепринятые подходы, найти готовый стек. Но там будет, что называется, своя атмосфера. И нет коллеги или гайда, которые бы объяснили, почему оно вообще так странно устроено.

Технически задача выглядит как-то так: в компании уже есть, например, Grafana (если нет, ее несложно поднять). Есть сотня способов собрать и передать туда данные, но сразу возникают вопросы: что мы хотим там отобразить? А почему нельзя это просто в SQL сложить? Зачем нужен этот ваш Prometheus, наконец?

Для сложных технологий хорошо иметь не только инструкцию, но и правильный mindset, тогда все инструменты будут даваться легче.

Вот со всем этим и будем разбираться.

Вообще метрики — это неожиданно сложно: мы пытаемся разными инженерно-математическими фокусами сжать неудобный, большой массив данных до чего-то наглядного. В отличие от логов, которые просто пишутся «как есть» и наверняка уже используются в ваших сервисах. Кстати, а почему бы не парсить логи и на основании этого уже строить какие-то графики? Так, конечно, можно, и это нормально — до некоторого предела.

Метрики vs логи

Логи — это про точность: мы собираем информацию на каждое событие. Если их агрегировать, можно увидеть общую картину и даже вытащить детали вплоть до единичного запроса. Но отправка логов на каждый чих плохо масштабируется.

Трафик логов зависит от трафика приложения: больше запросов, больше действий – и логов пропорционально больше. Часто они не структурированы, их сложно индексировать и парсить — для графиков нужно вытаскивать числа из текста. Ну и традиционно в логи пишется много лишнего, а значит обработка и агрегация будут страдать и отставать от реального времени.

Метрики – это сразу общая картина о состоянии приложения. Мы собираем не все детали, а только готовую выжимку: например, количество запросов к сервису. Картину мы получим, но в детали провалиться нельзя. Зато такой подход хорошо масштабируется и быстро работает. Можно моментально реагировать и рассылать алерты. Если нужны детали – думаем и добавляем по чуть-чуть.

Например, считаем количество запросов к разным endpoint-ам. Трафик метрик зависит от их количества и периодичности сбора/отправки их в хранилище. И, наконец, в метрики мы не пишем ничего лишнего, а, наоборот, стараемся писать как можно меньше. В следующих частях станет понятно, почему.

Пишем все и потом думаем (ценой трафика и сложности обработки) vs думаем и пишем только, что надо (ценой потери деталей).

Если у вас не очень много сервисов, и вы не планируете масштабирование, то можно не усложнять и остановиться на парсинге логов. В популярном стеке ELK есть встроенные средства визуализации.

Push vs Pull

Сбор метрик можно организовать двумя способами. У каждого есть свои плюсы и минусы. Чем глубже копать и чем больше масштабы, тем сложнее становится выбор — вплоть до холиваров.

Push – принцип такой же, как с логами или базой данных: произошло событие – пишем данные в хранилище. События можно отправлять пачками. Способ прост в реализации с точки зрения клиента.

Pull – наоборот: приложения хранят в памяти компактные данные вроде обработано запросов: 25. Кто-то периодически приходит и собирает их, например по HTTP. С точки зрения клиента pull сложнее реализовать, но проще отлаживать: у каждого приложения появляется endpoint, куда можно зайти браузером и увидеть, что происходит конкретно в этом приложении. Не нужно писать хитрые запросы, фильтровать данные по репликам и вообще иметь доступ в общее хранилище метрик. Кроме того, эта модель стимулирует разработчиков писать в метрики только то, что необходимо, а не все подряд.

Чтобы метрики не занимали лишнюю память приложения и быстро отдавались, мы вынуждены их агрегировать. Никто не хочет хранить в памяти подробности о каждом запросе, потому что эти данные очень быстро займут всю память. Приходится ограничиваться минимумом: например, вести счетчики запросов и ошибок. Это в итоге уменьшает нагрузку на инфраструктуру: ей нужно забрать и сохранить уже максимально сжатые данные, о которых уже подумали разработчики приложения.

Конечно, push тоже можно приготовить аналогичным образом, но там гораздо проще отправлять все подряд, а потом разбираться.

Мы выбрали pull: Prometheus на тот момент был построен в основном вокруг этой модели, и нам было проще выбрать решение с централизованным управлением.

TSDB

Метрики нужно куда-то складывать и потом делать выборки. Эту задачу решают специализированные БД: Time Series Database.

Особенности TSDB – обработка временны́х рядов, то есть однотипных измерений во времени. БД этого типа оптимизируют хранение какого-то числа, которое записано через равные интервалы времени. Проще понять на примере: чтобы собирать ежедневную температуру воздуха, нам надо хранить что-то вроде [(day1, t1), (day2, t2), ...] и больше ничего.

Главное сейчас – понять вот эту особенность: TSDB нужны, чтобы сохранять время и одно число, привязанное к этому времени. Потом снова время и число, и так далее. Пока что обойдемся без конкретики и деталей реализации.

Специфика:

  • реляционку умеют по минимуму: если SQL, то ограниченный, а то и вовсе его нет;

  • типы хранимых данных урезаны;

  • оптимизация на постоянную непрерывную запись.

Раз на SQL это все не похоже, то не обязательно поддерживать сложный язык запросов. Можно сделать свой, упоротый метрико-ориентированный простой язык.

Когда-то мы использовали для метрик InfluxDB — у него как раз SQL-подобные запросы. Но на наших объемах он просто взорвался, и с high availability было плохо, поэтому от него отказались.

Для работы с TSDB существуют свои специализированные форматы данных, и они проще, чем SQL. В следующей части мы разберемся, как готовить TSDB Prometheus: он устроен так, что формат метрик и язык запросов — это практически одно и то же, поэтому страдать придется всего один раз!

Визуализация

Когда у нас появится БД для хранения метрик и способ доставки данных в нее, мы сможем писать запросы, но... Просто так смотреть на таблицы с числами неинтересно. Поэтому запросы к БД обычно делает Grafana: она парсит таблицы из ответов и рисует удобные графики. В ней уже можно настроить масштаб, покрасить и добавить прочие украшения. Но писать запросы все равно придется самостоятельно.

Дальше мы будем разбираться именно с запросами Prometheus, без нюансов, которые добавляет Grafana. Поэтому для начала она вообще не понадобится — у Prometheus есть простой web-интерфейс, который визуализирует результаты запросов. Его вполне хватит для обучения, тестов и отладки.

Алерты

Самое полезное, что можно выжать из метрик и графиков – это алерты: нам не нужен живой человек, который постоянно следит за свободным местом на диске или за количеством ответов HTTP 500. Можно настроить автоматику, которая реагирует на выход графиков за допустимые границы и рассылает уведомления. Но, чтобы до этого добраться, придется сначала научиться собирать и хранить метрики, потом их запрашивать и отображать на графиках, и только потом уже расставлять алерты.

С алертами мы разбираться не будем, потому что концептуально тема уже не настолько сложная для понимания, как метрики, а архитектура решения будет очень сильно зависеть от специфики: кому-то нужна рассылка в мессенджере, кому-то телефонный бот.


Теперь должно быть более-менее понятно, из чего будет состоять решение для сбора метрик, и почему оно такое непривычное. Дальше будем разбирать формат данных и язык запросов Prometheus.

Комментарии (2)


  1. RomTec
    22.08.2022 23:49
    +1

    Но на наших объемах он просто взорвался

    А на каких? И в чем проявлялось - потери потока измерений или отказ ?


    1. Rast1234 Автор
      23.08.2022 10:43
      +1

      Дело было давно, по воспоминаниям коллег - он хотел слишком много RAM. Объемы данных не подскажу, но это не главное: когда проявились проблемы, мы решили особо не вкладываться в тюнинг инфлюкса, потому поняли, что мы не можем сделать high availability - что-то было доступно только в платной версии (репликация вроде бы). Поэтому решили дать ему умереть и переехать на Prometheus. Хотя если как минимум следить за кардинальностью, можно было бы жить дальше.