gendesign/backend/tests/test_app_logging.py
Light1YT eab7e3b9f3
All checks were successful
CI / changes (pull_request) Successful in 7s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m57s
CI / backend-tests (pull_request) Successful in 12m12s
fix(backend): emit app.* INFO logs to stdout on the API process (#1926)
App-level logs (logging.getLogger("app.*")) had no StreamHandler, so their
INFO was lost — `docker logs gendesign-backend-1` showed only uvicorn loggers.
Useful lines (e.g. "OSRM road-distance applied", RBAC, analyze) were invisible
when debugging on the VPS (only Sentry/GlitchTip received them as breadcrumbs).

main.py now attaches one StreamHandler to the root "app" logger at
APP_LOG_LEVEL (default INFO), idempotent (marker guard), propagate=True so the
Sentry LoggingIntegration on root still gets breadcrumbs/events and there's no
stdout double (root has no stdout handler). API process only — celery worker
(celery_app.py) untouched, since its loaders log per-sync and would be noisy.
Flood-safe on the API: the analyze hot path logs INFO per-request (parcels.py
has 3 logger.info), not per-row.

Adds tests/test_app_logging.py (handler present, level INFO, propagate intact).

Refs #1926
2026-06-27 07:43:49 +05:00

30 lines
1.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""#1926 observability: app-logger StreamHandler в main.py (логи app.* в stdout).
Без него INFO от `logging.getLogger("app.*")` терялся (в `docker logs` видны были
только uvicorn-логгеры), и полезные строки (OSRM road-distance applied, RBAC,
analyze) были невидимы при отладке на VPS.
"""
from __future__ import annotations
import logging
def test_app_logger_has_stdout_handler() -> None:
import app.main # noqa: F401 — module-level logging setup выполняется на импорте
app_logger = logging.getLogger("app")
# Уровень INFO (default APP_LOG_LEVEL).
assert app_logger.level == logging.INFO
# Ровно один маркированный StreamHandler — идемпотентность (повторный импорт
# не плодит дубли).
marked = [h for h in app_logger.handlers if getattr(h, "_gd_app_stream", False)]
assert len(marked) == 1
assert isinstance(marked[0], logging.StreamHandler)
# propagate=True → Sentry/GlitchTip LoggingIntegration (хендлер на root)
# продолжает получать breadcrumbs/events; stdout-дубля нет (у root своего
# stdout-хендлера нет).
assert app_logger.propagate is True