Логи в проде отвечают на вопрос «было ли что-то в ERROR» — и на этом заканчиваются. Они не скажут, сколько живых пользователей задело, та же это ошибка или новая, в какой версии она появилась и какие шаги к ней привели. Sentry берёт исключение в момент, когда оно случилось, и превращает его в воспроизводимое событие: стек, контекст, релиз, пользователь. Разберёмся, как это устроено, как не утонуть в шуме и что нужно, чтобы поднять Sentry у себя.
Содержание
Открыть содержание
Почему grep по логам — это не мониторинг ошибок
Классический разбор инцидента выглядит так: пользователь пишет «у меня не работает», вы идёте в логи, грепаете по времени и трейсбеку и надеетесь, что нужная строка не уехала за retention. Проблем тут три.
Логи плоские. Одно и то же исключение, случившееся 4000 раз, — это 4000 строк, и по ним нельзя за секунду сказать «это один баг у 300 пользователей» или «это 4000 разных проблем». Логи без контекста: строка NullPointerException at OrderService:42 не несёт ни версии сборки, ни того, что пользователь делал за три клика до падения. И логи реактивны: вы узнаёте о проблеме, когда пожаловались, а не когда она началась.
Можно возразить: «поставим структурированное логирование и агрегатор». Это помогает искать, но не решает главного — логи не знают, что две строки с чуть разными адресами в стеке суть одна ошибка, и не считают, скольких живых пользователей она задела. Ровно эту работу — дедупликацию и подсчёт влияния — берёт на себя error tracking.
Нужен инструмент, который не пишет строки, а собирает события об ошибках: группирует одинаковые, тащит с собой контекст и сам поднимает тревогу. Sentry — де-факто открытый стандарт для этой задачи, с SDK почти под любой язык и опцией self-hosted.
Что Sentry делает с ошибкой
Ключевая идея — не «складывать ошибки», а превращать каждую в воспроизводимое событие. За это отвечают несколько механизмов:
- Группировка (fingerprint). Sentry считает отпечаток по стеку и типу исключения и схлопывает одинаковые в одно issue. Тысячи повторов — одна карточка со счётчиком, а не стена текста.
- Breadcrumbs. Хлебные крошки — последовательность действий до сбоя: запросы, клики, SQL, логи. Видно не только «где упало», но и «что к этому привело».
- Releases. Каждое событие привязано к версии сборки. Сразу видно, что баг пришёл с релизом
2.3.1— это регресс, а не «всегда так было». - Source maps / debug-символы. Минифицированный фронтенд или скомпилированный бинарь Sentry разворачивает обратно в ваши исходные строки — стек читается как в IDE.
- Контекст. Пользователь, окружение (prod/staging), теги (эндпоинт, ОС, регион). Ошибка перестаёт быть абстрактной.
Вместе это меняет сам разбор: вы открываете issue и видите готовую картину — вот версия, вот шаги, вот кого задело, — вместо того чтобы реконструировать её по обрывкам логов.
Путь события: от исключения до алерта
Один проход выглядит так: SDK ловит необработанное исключение → считает fingerprint и группирует в issue → прикрепляет стек, breadcrumbs и контекст → issue назначается владельцу и, если правило сработало, летит алерт в Slack или на почту.
Важный узел здесь — не разбудить дежурного зря. На высоконагруженном сервисе одна и та же ошибка может генерить сотни событий в секунду. Помогают sample_rate (шлём долю событий) и rate limiting на стороне проекта: issue всё равно создастся и счётчик вырастет, но канал алертов не захлебнётся.
Сравнение в одной таблице
| Логи + grep | Sentry | |
|---|---|---|
| Дубликаты | 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» в рабочий мониторинг:
-
Отдавайте release и source maps в CI. На каждом деплое сообщайте Sentry версию и заливайте source maps, иначе фронтенд-стек останется нечитаемым:
export SENTRY_RELEASE="$GIT_SHA" sentry-cli releases new "$SENTRY_RELEASE" sentry-cli sourcemaps upload --release "$SENTRY_RELEASE" ./dist sentry-cli releases finalize "$SENTRY_RELEASE" -
Настройте алерты по-человечески. Не «на каждую ошибку», а на новое issue и на всплеск частоты. Маршрутизируйте по владельцам кода (ownership rules), чтобы алерт летел тому, кто трогал этот файл.
-
Приглушите шум сразу. Отфильтруйте заведомый мусор (обрывы соединений ботов, расширения браузера) через
ignoreErrors/beforeSend, иначе через неделю на Sentry перестанут смотреть.
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 — «вот конкретное исключение, вот стек и вот кого оно задело». Три угла, которые вместе дают полную картину прод-инцидента.