Перейти к содержимому
Hogin Hogin
Назад

Sentry: ловим ошибки в проде раньше пользователей

6 мин чтения

Логи в проде отвечают на вопрос «было ли что-то в ERROR» — и на этом заканчиваются. Они не скажут, сколько живых пользователей задело, та же это ошибка или новая, в какой версии она появилась и какие шаги к ней привели. Sentry берёт исключение в момент, когда оно случилось, и превращает его в воспроизводимое событие: стек, контекст, релиз, пользователь. Разберёмся, как это устроено, как не утонуть в шуме и что нужно, чтобы поднять Sentry у себя.

Содержание

Открыть содержание

Почему grep по логам — это не мониторинг ошибок

Классический разбор инцидента выглядит так: пользователь пишет «у меня не работает», вы идёте в логи, грепаете по времени и трейсбеку и надеетесь, что нужная строка не уехала за retention. Проблем тут три.

Логи плоские. Одно и то же исключение, случившееся 4000 раз, — это 4000 строк, и по ним нельзя за секунду сказать «это один баг у 300 пользователей» или «это 4000 разных проблем». Логи без контекста: строка NullPointerException at OrderService:42 не несёт ни версии сборки, ни того, что пользователь делал за три клика до падения. И логи реактивны: вы узнаёте о проблеме, когда пожаловались, а не когда она началась.

Можно возразить: «поставим структурированное логирование и агрегатор». Это помогает искать, но не решает главного — логи не знают, что две строки с чуть разными адресами в стеке суть одна ошибка, и не считают, скольких живых пользователей она задела. Ровно эту работу — дедупликацию и подсчёт влияния — берёт на себя error tracking.

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

Строка в логе против события с контекстом в Sentry

Что Sentry делает с ошибкой

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

Что несёт одно событие: стек, breadcrumbs, release, пользователь, теги

Вместе это меняет сам разбор: вы открываете issue и видите готовую картину — вот версия, вот шаги, вот кого задело, — вместо того чтобы реконструировать её по обрывкам логов.

Путь события: от исключения до алерта

Один проход выглядит так: SDK ловит необработанное исключение → считает fingerprint и группирует в issue → прикрепляет стек, breadcrumbs и контекст → issue назначается владельцу и, если правило сработало, летит алерт в Slack или на почту.

Важный узел здесь — не разбудить дежурного зря. На высоконагруженном сервисе одна и та же ошибка может генерить сотни событий в секунду. Помогают sample_rate (шлём долю событий) и rate limiting на стороне проекта: issue всё равно создастся и счётчик вырастет, но канал алертов не захлебнётся.

Путь ошибки: SDK ловит, fingerprint группирует, issue, алерт

Сравнение в одной таблице

Логи + grepSentry
Дубликаты4000 строкодно issue со счётчиком
Контексттолько строкастек, breadcrumbs, user, теги
Версияискать вручнуюпривязка к release из коробки
Фронтенд-стекминифицированразвёрнут через source maps
Как узнаёмпользователь пожаловалсяалерт в момент всплеска
Шумрежется sample rate + rate limit

Что нужно, чтобы завести Sentry

Минимум — DSN проекта и инициализация SDK на старте приложения. Пример для Node.js; в других экосистемах API такой же по смыслу:

// instrument.js — подключить ДО остального кода приложения
import * as Sentry from "@sentry/node";

Sentry.init({
  dsn: process.env.SENTRY_DSN,        // из настроек проекта
  environment: process.env.NODE_ENV,  // prod / staging — разводим по средам
  release: process.env.GIT_SHA,       // привязка событий к сборке
  tracesSampleRate: 0.1,              // 10% транзакций — производительность
  sampleRate: 1.0,                    // доля ошибок (снижаем на шумных сервисах)
});

Дальше — три шага, которые превращают «поставил SDK» в рабочий мониторинг:

Self-hosted, если данные не должны уходить наружу: официальный getsentry/self-hosted поднимается через docker compose — но это не «одна коробка». Внутри Postgres, ClickHouse (Snuba), Kafka и Redis; заложите ресурсы, диск под события и бэкапы, а также ретеншн — иначе ClickHouse со временем съест всё место. Практическое правило: начинайте с облака, чтобы проверить, что Sentry вообще приживётся в команде, и переезжайте на self-hosted только когда появится жёсткое требование не выпускать данные за периметр. Иначе легко потратить неделю на эксплуатацию инструмента, на который потом никто не смотрит.

Как убедиться, что работает

Не ждите настоящего инцидента — бросьте тестовое исключение и проверьте, что оно долетело со стеком:

// временный роут / скрипт
Sentry.captureException(new Error("sentry smoke test"));

Через несколько секунд событие должно появиться в проекте — с правильным environment, привязанным release и читаемым стеком. Если стек минифицирован — не доехали source maps; если нет release — CI не передаёт версию. Проверьте и обратное: намеренно отфильтрованная в ignoreErrors ошибка появляться не должна.

Итог

Sentry закрывает разрыв между «в логах есть ERROR» и «мы понимаем, что сломалось». Цена — SDK на старте приложения, отдача release и source maps из CI и дисциплина держать алерты и фильтры осмысленными. Payoff — вы узнаёте о регрессе в момент всплеска, а не из тикета поддержки, и открываете issue с готовым контекстом вместо археологии по логам.

А в связке с трейсингом и метриками (тот же OpenTelemetry из соседней статьи) Sentry занимает свою нишу в наблюдаемости: метрики говорят «что-то деградировало», трейсы — «где узкое место», Sentry — «вот конкретное исключение, вот стек и вот кого оно задело». Три угла, которые вместе дают полную картину прод-инцидента.


Поделиться:

Предыдущая статья
Trivy в CI: ловим уязвимости и собираем SBOM до прода
Следующая статья
Gateway API вместо Ingress: миграция, пока ingress-nginx не умер