В разработке логи нужны для отладки, в проде — для расследования инцидентов. Бот, у которого нет нормального логирования, превращается в чёрный ящик: пользователь жалуется, но воспроизвести нельзя, потому что нет следов. Хорошая система логов и алертов экономит часы при разборе проблем и сокращает простои. У бота в MAX нет UI на стороне сервера, нет HTTP-ответа, нет консоли разработчика у пользователя — вся диагностика идёт через логи, трекер ошибок и метрики. В этой статье разберём, как поставить наблюдаемость с нуля: структурные логи, корреляционные ID, Sentry с фильтрацией ПДн, Prometheus, дашборды Grafana, алерты и on-call процесс.
Зачем структурированные логи
Текстовая строка INFO: user 123 pressed button удобна глазами, но в проде с тысячами апдейтов в минуту это бесполезный шум. Структурный JSON-лог решает три задачи.
Поиск. JSON с полями event, user_id, chat_id позволяет в Loki или Kibana за секунду собрать все события одного пользователя или когорты. С текстом — регулярки на гигабайтах данных.
Фильтрация и агрегация. Сколько раз за час падал handler process_payment? Это запрос count by (event) where event="payment_failed", а не grep + wc + ручной разбор.
Алерты. Если поле level=ERROR приходит чаще порога — отправить дежурному. На текстовых логах такой алерт не написать: кто-то закоммитит print("ERROR in test") и сломает счётчик.
Структурные логи — это контракт между разработчиком и системой мониторинга. Один раз договорились о схеме полей — дальше алерты и дашборды работают сами.
Уровни: когда что писать
Стандартные уровни (DEBUG, INFO, WARNING, ERROR, CRITICAL) — это договор о шуме. У каждого своя аудитория и свой ретеншн.
- DEBUG — подробности для разбора инцидента: каждое API-сообщение от MAX, состояние FSM, тело апдейта. В проде по умолчанию выключен, включается выборочно для одного пользователя или хендлера.
- INFO — бизнес-события: новый пользователь, оформление заказа, успешный платёж, прохождение квиза. Это «история бизнеса», которую захочется поднять через год для аналитики.
- WARNING — что-то пошло не так, но бот выкрутился: ретрай оплаты, фоллбек на дефолтный ответ, превышен soft-лимит, медленный ответ внешнего API.
- ERROR — исключения и неожиданное поведение, требующее реакции. Каждый ERROR — потенциальный пост-мортем.
- CRITICAL — отказ ключевых компонентов: упал Redis, недоступен MAX Bot API, не отвечает база. Будит дежурного ночью.
Главная ошибка — лить INFO как DEBUG. Если в INFO попадает «вошёл в middleware», «вышел из middleware», «отправил запрос», аналитика превращается в кашу, а бюджет хранения уходит в трубу.
Сравнение библиотек логирования (Python)
| Библиотека | Структурные логи | JSON из коробки | Контекстные переменные | Производительность |
|---|---|---|---|---|
logging (stdlib) | Нет, через формат-строки | Через python-json-logger | Нет, нужен contextvars руками | Базовая |
structlog | Да, нативно | Через JSONRenderer | Да, bind_contextvars | Высокая |
loguru | Через extra={...} | Через serialize=True | Через contextualize | Средняя |
Для бота в MAX рекомендуем structlog: спроектирован под структурные логи, имеет хорошую интеграцию с contextvars и нормально дружит со стандартным logging (можно перенаправить логи MAX-SDK через стандартный модуль).
Конфигурация structlog
Минимальный продакшен-конфиг:
import logging
import structlog
from structlog.contextvars import merge_contextvars
logging.basicConfig(format="%(message)s", level=logging.INFO)
structlog.configure(
processors=[
merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.JSONRenderer(),
],
wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
logger_factory=structlog.PrintLoggerFactory(),
cache_logger_on_first_use=True,
)
log = structlog.get_logger()
log.info("bot_started", version="1.4.2", env="prod", platform="max")
На выходе — однострочный JSON, готовый для Loki или Yandex Cloud Logging. merge_contextvars подмешивает в каждое сообщение поля, выставленные через bind_contextvars(user_id=...) — так передаётся trace_id через все слои без явного аргумента.
Корреляционные ID
Один пользовательский апдейт может проходить через несколько сервисов: бот в MAX → CRM → платёжка → бот. Без сквозного request_id или trace_id собрать всю цепочку в одно расследование невозможно.
При получении апдейта генерируем UUID и пробрасываем в каждый исходящий вызов через заголовок X-Request-Id. Все сервисы логируют его. В централизованном хранилище фильтруем по request_id и видим всю историю.
Минимальный набор полей в каждой записи лога:
trace_id— UUID на апдейт.update_id— числовой ID апдейта от MAX.user_id— числовой ID пользователя.chat_id— числовой ID чата (для групп отличается от user_id).commandилиhandler— какой handler обработал апдейт.bot_version— версия деплоя.
С такими полями вся история обработки апдейта поднимается одним фильтром trace_id="abc-123", а не разбором пяти сервисов руками. Полноценный distributed tracing (OpenTelemetry, Jaeger) — следующий уровень.
Что логировать, а что нет
Логируем:
- Каждый входящий апдейт от MAX (тип, user_id, chat_id).
- Каждый исходящий вызов API (метод, latency, статус).
- Каждый переход FSM.
- Каждое создание/изменение бизнес-сущности (заявка, заказ, платёж).
- Все ошибки со стектрейсом.
НЕ логируем:
- Полные тексты сообщений (особенно с ПДн).
- Пароли, токены, ключи в любых вариантах.
- Полные тела платёжных webhook (там номера карт, хоть и маскированные).
При сомнениях — логируйте маску («введён номер карты ***1234») вместо полного значения. Утечка через логи — частая причина инцидентов с ПДн.
Sentry: что это и зачем
Логи отвечают на «что происходило». Sentry (и аналоги — GlitchTip, Bugsnag, Rollbar) отвечает на «что сломалось и где». Это специализированный трекер ошибок: группирует одинаковые исключения по fingerprint, показывает стектрейс с переменными, ведёт счётчик «сколько пользователей затронуто», строит графики деградации, шлёт алерты в MAX-канал команды или Slack.
Минимальная интеграция:
- SDK инициализируется на старте.
- Любое необработанное исключение в обработчике летит в Sentry с трейсом.
- К каждому событию прикрепляются
user_id,update_id,command. - Алерты в MAX-канал команды на новые ошибки и регрессии.
Sentry init для бота в MAX
import logging
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
from sentry_sdk.integrations.asyncio import AsyncioIntegration
sentry_sdk.init(
dsn="https://example@o0.ingest.sentry.io/0",
environment="prod",
release="max-bot@1.4.2",
traces_sample_rate=0.2,
profiles_sample_rate=0.1,
send_default_pii=False,
integrations=[
LoggingIntegration(level=logging.INFO, event_level=logging.ERROR),
AsyncioIntegration(),
],
before_send=scrub_pii,
)
release в формате имя@версия нужен Sentry для функции «эта ошибка появилась в релизе X» — критично при поиске регрессий после деплоя. send_default_pii=False отключает автоматическое прикрепление IP и заголовков. before_send — функция-фильтр, через которую SDK прогоняет каждое событие перед отправкой.
Breadcrumbs в handler
Breadcrumbs — это «след» событий, который Sentry прикрепляет к ошибке. Когда что-то сломается, в карточке Sentry будут видны последние 50 действий: какой handler вошёл, какой запрос ушёл в БД, какой ответ пришёл от внешнего API.
from sentry_sdk import set_user, set_tag, add_breadcrumb, capture_exception
async def sentry_middleware(handler, event, data):
user = data.get("event_from_user")
if user:
set_user({"id": user.id})
set_tag("update_id", event.update_id)
set_tag("platform", "max")
add_breadcrumb(
category="max-bot",
message=f"handler:{handler.__name__}",
level="info",
)
try:
return await handler(event, data)
except Exception as exc:
capture_exception(exc)
raise
set_user привязывает событие к пользователю — в карточке Sentry будет «затронуто N пользователей», а не «N событий». set_tag добавляет фасет, по которому удобно фильтровать в UI.
Sensitive data scrubbing
Главная ошибка — логировать тело сообщений «для удобства». В чатах боту в MAX прилетают телефоны, паспорта, медицинские данные, банковские реквизиты. Эти данные не должны лежать в Loki, Sentry или Datadog. Это требование 152-ФЗ и GDPR, а ещё репутационный риск: утечка логов с ПДн = потенциально многомиллионный штраф.
Правила:
- Не логировать полный текст сообщения пользователя.
- Маскировать телефоны, email, карты:
+7***4567,i***@gmail.com,4242 **** **** 1234. - Не сохранять тело платёжных webhook, если в нём детали карты.
- Конфигурировать Sentry
before_sendдля удаления чувствительных полей. - Для медицинских и финансовых ботов — отдельный аудит логов раз в квартал.
Пример скрабера для Sentry:
import re
PHONE_RE = re.compile(r"(\+?\d{1,3})\d{6,10}(\d{2,4})")
EMAIL_RE = re.compile(r"([\w.-]+)@([\w.-]+)")
CARD_RE = re.compile(r"\b(\d{4})\d{8,12}(\d{4})\b")
def scrub_pii(event, hint):
def mask(s: str) -> str:
s = PHONE_RE.sub(r"\1***\2", s)
s = EMAIL_RE.sub(r"\1***@\2", s)
s = CARD_RE.sub(r"\1********\2", s)
return s
if msg := event.get("message"):
event["message"] = mask(msg)
for exc in event.get("exception", {}).get("values", []):
if exc_msg := exc.get("value"):
exc["value"] = mask(exc_msg)
return event
Если для отладки нужно тело сообщения — только в DEBUG и отдельным потоком, не уходящим в облако.
Sampling: errors 100%, traces 10-30%
Sentry берёт деньги за events. На активном боте легко улететь в десятки тысяч долларов в год, если отправлять каждый запрос как transaction.
- Errors — 100%. Каждое исключение должно дойти до Sentry.
- Traces (performance) — 10-30%. Достаточно, чтобы видеть p95/p99 латентности.
- Profiling — 5-10% от traces. Сэмплы профилировщика тяжёлые, держите долю низкой.
Можно настроить динамический sampler: 100% для редких хендлеров, 5% для горячих. SDK поддерживает traces_sampler, который получает контекст и возвращает долю.
Альтернативы Sentry
| Сервис | Модель | Плюсы | Минусы |
|---|---|---|---|
| Sentry Cloud | SaaS, freemium | Лучший UX, интеграции | Дорого на масштабе |
| GlitchTip | Self-hosted, OSS | API-совместим с Sentry, бесплатно | Нет profiling, slimmer UI |
| Sentry Self-hosted | OSS, on-prem | Полный функционал, контроль данных | Тяжёлая инсталляция (Postgres + Kafka + ClickHouse) |
| Bugsnag | SaaS | Хорошие release dashboards | Дороже Sentry |
| Rollbar | SaaS | RQL-запросы по событиям | Слабее интеграций |
Для бота в MAX в РФ-контуре оптимально: GlitchTip self-hosted, если важна цена и локализация ПДн, или Sentry Cloud, если важна скорость старта. Bugsnag и Rollbar не подходят под требования 152-ФЗ по локализации.
Логи в файл vs stdout
Старая школа — писать в файл с rotating handler:
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
"/var/log/max-bot.log",
maxBytes=50_000_000,
backupCount=10,
)
Современная (cloud-native) — писать в stdout, а сбор и ротацию делегировать Docker, systemd-journald или сборщику:
- Stateless контейнер, без mounted volume под логи.
- Стандартный pipeline:
docker logs,kubectl logs,journalctl -u max-bot.service. - Логи попадают в централизованное хранилище без участия приложения.
- Перезапуск контейнера не теряет логи (если есть сборщик).
Для Docker-деплоя — только stdout/stderr. Для сервера на metal или systemd — допустимо в файл, но проще оставить journald.
Сбор логов: куда отправлять
| Стек | Транспорт | Хранилище | UI | Когда выбирать |
|---|---|---|---|---|
| Loki + Promtail | gRPC | Object storage (S3) | Grafana | Дешёвое хранение, нет full-text search |
| ELK | Filebeat / Logstash | Elasticsearch | Kibana | Нужен полнотекстовый поиск |
| Datadog Logs | Agent | Cloud | Datadog | SaaS «всё в одном», дорого |
| Yandex Cloud Logging | Fluent Bit / SDK | Облако | Cloud Console | Деплой в Yandex Cloud, требования 152-ФЗ |
| Vector + ClickHouse | Vector | ClickHouse | Grafana / Metabase | High-throughput, контроль расходов |
Для бота в MAX на VPS в России — Loki + Promtail + Grafana или Yandex Cloud Logging. ELK перебор, Datadog слишком дорогой и не российский.
Метрики: что снимать
Логи и Sentry — для разбора инцидента после факта. Метрики — для проактивного мониторинга. Минимум для бота в MAX:
bot_updates_total— счётчик апдейтов по типу (message, callback, command).bot_handler_latency_seconds— гистограмма времени обработки.bot_api_call_duration_seconds— длительность вызовов MAX API.bot_external_api_duration_seconds— длительность вызовов внешних сервисов (CRM, банк, МИС).bot_errors_total— счётчик ошибок по типу.- Лаг long polling или время доставки webhook.
- Доля 429 (rate limit) от MAX.
Prometheus + Grafana — отраслевой стандарт. Алерт на «доля ошибок выше 1% за 5 минут» уведомит дежурного раньше, чем пользователь напишет в поддержку.
Prometheus metrics в боте
from prometheus_client import Counter, Histogram, start_http_server
UPDATES = Counter(
"bot_updates_total",
"Total updates received from MAX",
["handler", "status"],
)
LATENCY = Histogram(
"bot_handler_latency_seconds",
"Handler latency",
["handler"],
buckets=(0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10),
)
async def metrics_middleware(handler, event, data):
name = handler.__name__
with LATENCY.labels(handler=name).time():
try:
result = await handler(event, data)
UPDATES.labels(handler=name, status="ok").inc()
return result
except Exception:
UPDATES.labels(handler=name, status="error").inc()
raise
start_http_server(9090)
Prometheus периодически опрашивает :9090/metrics, складывает в TSDB, Grafana строит графики. Алертинг через Alertmanager: правило rate(bot_updates_total{status="error"}[5m]) > 0.01 шлёт алерт.
Health-checks
Liveness и readiness — два разных вопроса. Liveness отвечает «процесс жив», readiness — «процесс готов принимать трафик». В MAX-боте liveness проверяем эквивалентом getMe (запрос к MAX API на проверку токена), readiness — доступностью БД и Redis.
from aiohttp import web
async def healthz(request):
return web.Response(text="ok")
async def readyz(request):
try:
await max_client.get_me() # liveness MAX API
await db.execute("SELECT 1") # liveness БД
await redis.ping() # liveness Redis
return web.Response(text="ready")
except Exception as exc:
return web.Response(status=503, text=str(exc))
app = web.Application()
app.router.add_get("/healthz", healthz)
app.router.add_get("/readyz", readyz)
Kubernetes использует эти эндпоинты для рестартов и роутинга трафика. Docker Compose — для healthcheck-условий зависимостей.
Distributed tracing
Если бот ходит в несколько микросервисов (CRM, оплата, склад, ML-инференс), без distributed tracing невозможно понять, где тормозит запрос. Стандарт — OpenTelemetry: SDK инжектит traceparent в HTTP-заголовки, бэкенды его подхватывают, и в Jaeger / Tempo / Sentry виден полный span-tree от MAX-апдейта до ответа БД.
Минимум — настроить экспортёр OTLP в Tempo или Jaeger, обернуть HTTP-клиент в инструментацию (opentelemetry-instrumentation-aiohttp-client), и автоматически каждый запрос будет трассироваться. Sentry поддерживает OpenTelemetry как источник span-ов.
Алерты
Хороший алерт — это:
- Действенный — на него можно реагировать.
- Точный — не сработает на ровном месте.
- Срочный — требует внимания сейчас, а не «когда-то».
Базовый набор технических алертов:
- Бот не отвечает — нет успешных апдейтов от MAX более 5 минут.
- Ошибки в API MAX — 5xx или 429 чаще порога.
- Падение внешних интеграций — CRM/банк/МИС не отвечают.
- Нагрузка — очередь апдейтов растёт (long polling) или 5xx на webhook.
- Ошибки бизнес-логики — массовые исключения в одном сценарии.
Алерты идут в дежурный канал — отдельный чат в MAX, Slack или корпоративная почта. Главное — чтобы их видели, а не молча копили.
Алерты на бизнес-метрики
Технические алерты необходимы, но недостаточны. Бот может работать без ошибок и при этом не приносить деньги — например, поломалась интеграция с CRM, и лиды не доходят. Технически всё ОК, бизнес стоит.
Алерты на бизнес-метрики:
- Конверсия квиза упала ниже X% за час.
- Платежи не проходят более N минут подряд.
- Резко выросла доля брошенных корзин.
- Количество новых пользователей упало в два раза против скользящей средней.
- Среднее время до первого платежа выросло на N процентов.
Это пишется в Grafana или Yandex Cloud Monitoring как production alerts уровня бизнеса. Срабатывает реже технических, но каждое срабатывание — реальные деньги.
Дашборды для дежурного
Не «50 графиков», а 5–7 ключевых:
- Активные пользователи (5/30/60 минут).
- Error rate по сценариям.
- Latency p50/p95/p99 на обработку.
- API health (MAX, внешние интеграции).
- Очередь и нагрузка процессоров.
Дашборд должен открываться по ссылке за секунду, без логина и фильтров.
On-call процесс
Алерт без процесса — это просто шум в чате. Минимальный on-call процесс для команды из 2-5 разработчиков:
- Расписание дежурств: одна неделя на человека.
- Канал алертов в MAX или Slack, куда летят CRITICAL и ERROR с пороговыми условиями.
- Эскалация: если дежурный не отреагировал за 15 минут — уведомление лидеру.
- Runbook: на каждый частый алерт — короткая инструкция «что проверить, что сделать».
- Пост-мортем: после каждого инцидента — заметка в notion с timeline и action items.
Инструменты: PagerDuty (стандарт), OpsGenie (дешевле), Grafana OnCall (OSS) или собственный MAX-бот для дежурного, который пингует и эскалирует через 15 минут.
152-ФЗ и GDPR в логах
Логи — это «обработка персональных данных». Если в логе лежит user_id MAX, это уже ПДн (косвенный идентификатор). Если телефон, email, ФИО — прямые ПДн.
Требования:
- В уведомлении Роскомнадзора (152-ФЗ) указать, что логи — часть обработки ПДн.
- Логи не должны храниться дольше срока, нужного для целей обработки. Стандарт — 30-90 дней для оперативных, 1 год для аудита.
- Доступ к логам — только разработчикам, с журналированием доступа.
- При запросе пользователя «удалите мои данные» — удалить и логи. Технически: либо retention достаточно короткий, либо специальный pipeline зачистки по
user_id. - При трансграничной передаче (Sentry Cloud в США / ЕС) — отдельное уведомление РКН по ст. 12 152-ФЗ.
Безопасный путь — self-hosted Sentry или GlitchTip в российском контуре + Loki в Yandex Cloud, без выезда ПДн за границу.
Расследование инцидента
Сценарий: «у пользователя X не прошла оплата». Шаги:
- По
user_idищем последние апдейты в логах. - По
trace_idподнимаем всю цепочку. - Проверяем ответ платёжного сервиса.
- Сверяем с метриками: была ли деградация в этот момент.
- Если ошибка повторяется у других — разбор инцидента и патч.
Без структурных логов и trace_id это занимает часы. С ними — минуты.
Чек-лист перед продом
- Структурные JSON-логи с уровнями.
- Sentry с фильтром ПДн в
before_send. - trace_id во всех слоях через contextvars.
- Метрики латентности, ошибок и очередей в Prometheus.
- Health-чек
/healthzи/readyz. - Алерты в MAX-канал команды на критичные события.
- Алерты на бизнес-метрики (конверсия, платежи).
- Ретеншн логов 30-90 дней и архив холодных логов.
- Доступ к логам и Sentry — только разработчикам, с журналированием.
- Runbook на каждый частый алерт, расписание on-call.
Итого
Логи и алерты — основа эксплуатации бота в MAX. Структурное логирование с trace_id, Sentry с фильтром ПДн, метрики Prometheus, дашборды Grafana и осмысленный набор алертов закрывают большую часть инцидентов. Они становятся не блокером, а тематикой 5-минутного разбора. На старте можно обойтись простым stdout, но в проде эта инфраструктура окупается с первого же серьёзного бага. Скрабинг ПДн перед отправкой в облако — требование 152-ФЗ и GDPR, а не «приятное дополнение». Настройка занимает 1-3 дня, поддержка после — около часа в неделю на чистку шума и обновление дашбордов.
Частые вопросы
Что такое структурное логирование и зачем оно боту MAX?
Это формат логов как JSON с контекстными полями вместо текстовых строк. Текстовый лог «INFO: user pressed button» бесполезен в проде. Структурный JSON со всеми полями (level, timestamp, msg, user_id, from_state, to_state, trace_id) позволяет фильтровать, агрегировать, строить дашборды. Библиотеки: structlog, loguru (Python), pino, winston (Node), zerolog, zap (Go). Все умеют JSON-вывод с минимальным оверхедом. Без структуры в первом инциденте придётся грепать тысячи строк, и это дорого.
Как корректировать запросы между сервисами в боте MAX?
Через сквозной request_id или trace_id. Один пользовательский апдейт может проходить через несколько сервисов: бот → CRM → платёжка → бот. Без trace_id собрать всю цепочку невозможно. При получении апдейта от MAX генерируем UUID и пробрасываем в каждый исходящий вызов через заголовок X-Request-Id. Все сервисы логируют его. В централизованном хранилище фильтруем по trace_id и видим всю историю. Полноценный distributed tracing (OpenTelemetry, Jaeger) — следующий уровень, для большинства ботов хватает trace_id через contextvars.
Что нужно логировать в боте MAX, а что нельзя?
Логируем: каждый входящий апдейт от MAX (тип, user_id, chat_id), каждый исходящий вызов API (метод, latency, статус), каждый переход FSM, каждое создание/изменение бизнес-сущности (заявка, заказ, платёж), все ошибки со стектрейсом. Не логируем: полные тексты сообщений (особенно с ПДн), пароли, токены, ключи в любых вариантах, полные тела платёжных webhook (номера карт, хоть и маскированные). При сомнениях — логируйте маску (введён номер карты ***1234) вместо полного значения. Утечка через логи — частая причина инцидентов с ПДн.
Как настроить Sentry для бота в MAX?
Установить sentry-sdk, инициализировать на старте с DSN, environment, release в формате name@version, traces_sample_rate 0.1-0.3, send_default_pii False, before_send со скрабером ПДн. Подключить LoggingIntegration и AsyncioIntegration. В middleware бота на входе вызвать set_user из event.from_user, set_tag update_id, add_breadcrumb с именем хендлера. На исключении — capture_exception и raise дальше. release нужен Sentry для определения регрессий после деплоя. Errors отправляем 100%, traces 10-30% — иначе бюджет улетит на масштабе.
Где хранить логи бота MAX в продакшене?
Четыре варианта. Loki + Promtail + Grafana — лёгкое, индексирует по меткам, дешёвое в эксплуатации, рекомендуемый компромисс. ELK (Elasticsearch + Kibana) — мощное, но прожорливое по ресурсам, оправдано на больших объёмах с full-text search. Yandex Cloud Logging — управляемый сервис, не нужно держать стек, удобно для РФ-проектов и требований 152-ФЗ. Локальный stdout + ротация — минимальный вариант для маленьких ботов на старте. Для прода рекомендуется Loki или Yandex Cloud Logging. Datadog слишком дорогой и не российский.
Какие метрики и алерты нужны для бота MAX?
Минимум технических метрик: апдейты в секунду, латентность p50/p95/p99, доля ошибок на 1000 апдейтов, длина очереди задач, лаг long polling, доля 429 от MAX, количество вызовов MAX API по методу. Стек — Prometheus + Grafana с Alertmanager. Алерт на «доля ошибок выше 1% за 5 минут» уведомит дежурного раньше пользователя. Бизнес-метрики тоже критичны: конверсия квиза, доля прошедших платежей, новые пользователи в час. Бот может технически работать, но бизнес стоять — например, упала интеграция с CRM. Алерты на бизнес-метрики срабатывают реже, но всегда означают реальные деньги.
Какие альтернативы Sentry для self-hosted сценария?
GlitchTip — open-source трекер ошибок, API-совместим с Sentry SDK, ставится из docker-compose за 15 минут. Не имеет profiling и session replay, но для большинства MAX-ботов хватает. Sentry Self-hosted — полный функционал, но требует Postgres, Kafka, ClickHouse, Redis и минимум 8 ГБ RAM на сервер. Bugsnag и Rollbar — SaaS-альтернативы Sentry Cloud, не подходят для требований по локализации ПДн в 152-ФЗ. Для российских проектов оптимально GlitchTip в собственном контуре или Sentry Self-hosted на отдельной VM.