Дебажить приложение в продакшене — нетривиальная задача. Когда у тебя микросервисная архитектура — проблема возводится в степень. Сейчас наше приложение включает больше сотни сервисов, написанных преимущественно на PHP и Go. Выбирая инструменты для отладки в продакшене, мы имели два ключевых требования. Первое — нам важно было составить стек из универсальных инструментов с хорошей документацией. Второе — большое комьюнити с easy-входом: команда постоянно растёт, хочется тратить меньше времени на погружение в работу.
В своих поисках и экспериментах мы остановились на ELK, Sentry и Jaeger.
Стек ELK мегапопулярен. Про Sentry большая часть разработчиков как минимум что-то слышала. Jaeger — малоизвестен. На собеседованиях мы часто слышали от кандидатов, что они не сталкивались с OpenTracing, — но хорошей альтернативы мы не нашли, а вход в него простой.
Основное преимущество нашего стека — ноль затрат на лицензии. Надеюсь, наш обзор будет полезен компаниям, которые ищут инструменты для дебага продакшена с минимальными затратами.
1. ELK — связка Elasticsearch, Logstash и Kibana
ELK мы начали использовать ещё на монолите. Здесь мы отслеживаем логи приложений и логи балансеров (nginx). Туда же пишется MySQL slow query log.
Что включает в себя:
Elasticsearch (ES) — NoSQL-база данных с возможностью полнотекстового поиска, позволяет хранить, искать и анализировать большие объёмы данных.
Logstash — средство сбора, преобразования и сохранения в общем хранилище событий из файлов, баз данных, логов и других источников в реальном времени. Logstash позволяет модифицировать полученные данные с помощью фильтров: разбить строку на поля, обогатить их, агрегировать несколько строк, преобразовать их в JSON-документы и т. п.
Kibana — UI-клиент для Elasticsearch, чтобы взаимодействовать с данными, которые хранятся в индексах ES. Веб-интерфейс Kibana позволяет быстро создавать и обмениваться динамическими панелями мониторинга, включая таблицы, графики и диаграммы, которые отражают изменения в ES-запросах в реальном времени.
Kibana зачастую помогает понять, что привело к ошибке или работает неправильно, потому что содержит логи бизнесового характера: клиент записался на встречу, дилер продлил абонентскую плату, аукцион был завершён и т. п. Сюда же мы пишем весь stdout, и в случае краша приложения всегда можем увидеть причины.
2. Jaeger. Позволяет отслеживать трейс между сервисами
Мы внедрили Jaeger пять лет назад, когда начали переходить на микросервисы. Это распределённая система отслеживания с открытым исходным кодом, написанная на Go. Данные Jaeger совместимы со спецификацией OpenTracing, определяющей, как будут выглядеть собранные трассировки. Есть готовые интеграционные SDK на разных языках для быстрого входа.
Единица трейса (span в терминологии OpenTracing) представляет действие: чтение файла, логическую операцию, запрос в какой-либо сервис или в базу данных. Span имеет название, время начала и длительность, а также может содержать теги и логи.
Сервис состоит из нескольких компонентов:
Jaeger client — это библиотеки, написанные на различных языках программирования и отвечающие за создание span’ов.
Jaeger Agent — сетевой демон, который прослушивает интервалы, полученные от клиента Jaeger по UDP. Он собирает их партиями, а затем отправляет сборщику.
Jaeger Collector отвечает за получение трассировок от агента Jaeger и выполняет проверки и преобразования. После этого отправляет их в хранилище.
Storage — Jaeger поддерживает различные хранилища, в которых лежат span’ы и трассировки для последующего их извлечения. Поддерживаемые хранилища: In-Memory, Cassandra, Elasticsearch. Мы используем Elasticsearch.
Jaeger Query — отвечает за извлечение трассировок из серверной части хранилища Jaeger и обеспечение их доступности для пользовательского интерфейса Jaeger UI.
Jaeger UI — приложение, написанное на React. Позволяет визуализировать трассировки и анализировать их — это полезно для отладки системных проблем. Фильтрует трассировки по сервису, типу операции, тегам, диапазону времени, длительности выполнения операции.
Возможности:
поиск ошибок;
поиск долгих сетевых запросов: как ко внутренним сервисам, так и ко внешним;
поиск длительных операций, которые нужно оптимизировать;
можно наглядно проследить весь путь запроса от сервиса к сервису.
Важно при возникновении ошибки добавлять соответствующий тег error, тогда Jaeger UI корректно выделит span с ней. Также можно добавлять в теги какую-то важную информацию, например ID пользователя, для дальнейшей фильтрации. А в лог span’а писать вспомогательную информацию, например текст ошибки.
Минус Jaeger: необходимо модифицировать код приложения, добавляя span’ы в тех случаях, где это необходимо.
3. Sentry. Отслеживание и агрегирование ошибок в реальном времени
Мы используем Sentry как основной инструмент трекинга ошибок с алертами в корпоративный чат.
Возможности:
подходит для фронтенда, бэкенда и мобильных приложений;
интеграция с CI/CD. Возможность быстро понять, какой релиз вызвал проблемы;
группирует одинаковые ошибки;
если ошибка повторяется слишком часто, то Sentry инкрементит количество появлений этой ошибки, а не сохраняет каждую — это экономит место;
позволяет смотреть время первого появления каждой ошибки;
есть клиентские библиотеки практически под все ЯП (в нашем случае интересовал JS, PHP и Go);
наличие интеграций с различными приложениями (Jira, Slack, GitLab и т. д.).
Удобно то, что можно прямо из Sentry поставить задачу в Jira. По выполнении Jira помечает ошибку как решённую, а если она возникает вновь, Sentry трекает её заново.
Знаю, что другие компании обычно используют больше инструментов. Но мы уже много лет работаем на нашем небольшом стеке — и не хотим его менять. Впрочем, я могу что-то упускать — и потому буду рад ответить на вопросы в комментариях.
teror4uks
Судя по вашему описанию jaeger выглядит как ещё один логгер только умнее и со своим веб интерфейсом. Это же самое можно сделать и с помощью ELK, просто отправляя и получая из сервиса к сервису уникальный для запроса реквест ид, который указывается при логгировании действий ну и получается отправляется в эластик где потом на его основе можно строить какие угодно графики.... хоть трекать потребление памяти хоть длительность запрса. Но конечно это просто мои рассуждения может он ещё что то может чего я не знаю. Кстати чисто для справки для logstash filebeat есть вполне годная замена vector используем его в проде.