feat: логирование вебхука до БД + файловый лог с ротацией
All checks were successful
CI / test (push) Successful in 47s
All checks were successful
CI / test (push) Successful in 47s
- Каждый входящий POST /ingress/grafana: INFO-строка (status, кол-во алертов, первые лейблы) и DEBUG-блок с полным JSON телом (до 8КБ) — видно даже если БД упала с 500 - LOG_FILE в .env / env: RotatingFileHandler 10MB×5 файлов - LOG_LEVEL=debug теперь показывает полные тела вебхуков - basicConfig уровень DEBUG (uvicorn.access / asyncio приглушены) Made-with: Cursor
This commit is contained in:
@ -82,6 +82,42 @@ def service_hint_from_grafana_body(body: dict, header_service: str | None) -> st
|
||||
return None
|
||||
|
||||
|
||||
def _log_incoming_webhook(body: object, raw: bytes, path_slug: str | None) -> None:
|
||||
"""Логирует каждый входящий вебхук: краткое резюме INFO + полное тело DEBUG."""
|
||||
slug_tag = f"[/{path_slug}]" if path_slug else "[/]"
|
||||
raw_len = len(raw)
|
||||
|
||||
if not isinstance(body, dict):
|
||||
logger.info("grafana webhook %s raw=%dB (non-dict body)", slug_tag, raw_len)
|
||||
logger.debug("grafana webhook %s raw body: %s", slug_tag, raw[:4000].decode(errors="replace"))
|
||||
return
|
||||
|
||||
alerts = body.get("alerts") or []
|
||||
n_alerts = len(alerts) if isinstance(alerts, list) else 0
|
||||
status = body.get("status", "?")
|
||||
title = str(body.get("title") or body.get("ruleName") or "")[:120]
|
||||
first_labels: dict = {}
|
||||
if isinstance(alerts, list) and alerts and isinstance(alerts[0], dict):
|
||||
first_labels = alerts[0].get("labels") or {}
|
||||
|
||||
logger.info(
|
||||
"grafana webhook %s status=%s alerts=%d title=%r labels=%s raw=%dB",
|
||||
slug_tag,
|
||||
status,
|
||||
n_alerts,
|
||||
title,
|
||||
json.dumps(first_labels, ensure_ascii=False)[:300],
|
||||
raw_len,
|
||||
)
|
||||
try:
|
||||
pretty = json.dumps(body, ensure_ascii=False, indent=2)
|
||||
if len(pretty) > 8000:
|
||||
pretty = pretty[:8000] + "\n…(обрезано)"
|
||||
except Exception:
|
||||
pretty = raw[:8000].decode(errors="replace")
|
||||
logger.debug("grafana webhook %s full body:\n%s", slug_tag, pretty)
|
||||
|
||||
|
||||
async def _grafana_webhook_impl(
|
||||
request: Request,
|
||||
pool,
|
||||
@ -98,6 +134,10 @@ async def _grafana_webhook_impl(
|
||||
body = json.loads(raw.decode() or "{}")
|
||||
except json.JSONDecodeError:
|
||||
body = {}
|
||||
|
||||
# Логируем входящий вебхук ДО любой обработки — чтобы видеть при любой ошибке
|
||||
_log_incoming_webhook(body, raw, path_slug)
|
||||
|
||||
if not isinstance(body, dict):
|
||||
body = {}
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user