Перейти к основному содержимому

Observability

Logs

import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
log = logging.getLogger("mybot")

Что логировать

✅ Логировать
  • event.id, event.type, delivery_id
  • user_id, channel_id (только IDs, не sensitive)
  • latency: ms на обработку
  • HTTP status исходящих вызовов
  • Exception trace
❌ Не логировать
  • Raw webhook body (может содержать content сообщений с sensitive)
  • Bot token / webhook secret (даже маскированные)
  • Email / IP пользователей
  • Полный content сообщений

Структурированные логи

JSON в production — для лёгкой агрегации в вашей системе сбора логов:

import structlog

log = structlog.get_logger()

log.info(
"handler_completed",
event_id=event.id,
event_type=event.type,
user_id=event.author_user_id,
latency_ms=int((time.time() - start) * 1000),
)

Метрики

Счётчики и гистограммы для стандартного /metrics endpoint:

# Counter / Histogram из вашей библиотеки сбора метрик
from metrics import Counter, Histogram

events_total = Counter(
"mybot_events_total",
"Webhook events received",
["type"],
)
event_duration = Histogram(
"mybot_event_duration_seconds",
"Webhook handler duration",
["type"],
)

@bot.on("message.created")
async def handler(event):
events_total.labels(type=event.type).inc()
with event_duration.labels(type=event.type).time():
await do_stuff(event)

Подключите экспортёр метрик вашего ASGI-приложения, чтобы отдавать стандартный /metrics endpoint:

# Подключите ваш экспортёр метрик к ASGI-приложению бота
# и выставьте endpoint /metrics
setup_metrics(bot.app, endpoint="/metrics")

GET /metrics отдаёт метрики в стандартном текстовом формате.

Платформенные метрики

Отдельных метрик по ботам (вида reasonspace_bot_*) платформа пока не экспозит. На стороне платформы есть только стандартный /metrics endpoint с обычными HTTP-метриками (latency, статус-коды, throughput) — без разбивки по конкретному боту, scope или webhook-доставкам. Не стройте дашборды и алерты на сериях reasonspace_bot_api_requests_total, ..._webhook_delivery_total, ..._oauth_token_issued_total и подобных — их в коде нет.

Что реально доступно для observability на стороне платформы — это лог-события доставки webhook'ов (структурированные записи в логах API). По ним команда платформы отслеживает здоровье доставки:

Лог-событиеКогда
bot_webhook_queue_full_dropочередь доставки переполнена, событие отброшено
bot_webhook_url_unsafeURL webhook'а не прошёл SSRF-проверку, доставка пропущена
bot_webhook_delivery_network_failсетевая ошибка при попытке доставки
bot_webhook_goneendpoint вернул 410 Gone (засчитывается как неуспешная доставка; авто-отвязка по 410 — в roadmap, пока не реализована)
bot_webhook_auto_suspended5 неуспешных доставок подряд → suspend на 24 часа

Собственные метрики на success rate доставки и автоматические уведомления владельцу (например, при success rate < 90%) — в roadmap, пока не реализованы. Для своего бота собирайте метрики сами (см. раздел Метрики выше).

Alerts

Базовый набор для production-бота:

AlertThresholdAction
Bot API success rate< 90% за 5 минутPage on-call
Event handler latencyp99 > 5sSlow, проверить queue
Webhook 4xx rate> 5%Возможно неверная подпись
Memory usage> 80%Memleak в handler?
Voice sessions stuck> 30 минутЗомби-процессы

Tracing

OpenTelemetry для distributed tracing — если у вас бот → internal API → DB:

from opentelemetry import trace
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor

HTTPXClientInstrumentor().instrument() # auto-trace всех HTTP requests

tracer = trace.get_tracer("mybot")

@bot.on("message.created")
async def handler(event):
with tracer.start_as_current_span("handle_message") as span:
span.set_attribute("event.id", str(event.id))
await do_stuff(event)

Dashboard-шаблоны

Grafana JSON-templates для bot-side мониторинга — планируется. Сейчас рекомендуется собирать свои.