fix(logger): вызывать setup_logger при импорте приложения (#63)

setup_logger() с diagnose=False существовал, но не вызывался: работал
обработчик loguru по умолчанию (diagnose=True), и трейсбек любого
залогированного исключения содержал значения локальных переменных.
Теперь src/app.py вызывает setup_logger при импорте, как tabular-parser.

Регрессионный тест в отдельном процессе: исключение с локальной
переменной логируется с трейсбеком, но без её значения.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
This commit is contained in:
Andrey Epifancev 2026-10-08 16:41:40 +04:00
parent d8bf5b22dc
commit c937c8173f
2 changed files with 55 additions and 1 deletions

View File

@ -13,7 +13,8 @@ middleware не подключается), healthcheck (uptime, version, nats: o
`recognition.result` (ack и результаты сервисов) обрабатывает inbox `handle_message` того же модуля с фабрикой сессий
приложения (inbox меняет задание и статус файла; маппинг результата в доменные таблицы — отдельный цикл, Срез 2c D-1).
Остановка: фоновые задачи обмена → NATS → S3 → SMB → пул соединений БД; каждый шаг независим — ошибка одного
логируется и не отменяет остальные.
логируется и не отменяет остальные. Логгер настраивает `setup_logger` при импорте модуля: без значений локальных
переменных в трейсбеках (#63).
"""
import asyncio
@ -41,6 +42,7 @@ from src.api.router import API_PREFIX, build_api_router
from src.core.clients import S3Storage
from src.core.config import Settings, get_settings
from src.core.exception_handlers import register_exception_handlers
from src.core.logger import setup_logger
from src.core.nats import MessageHandler, NatsConnection
from src.db.db import async_session_maker, engine, session_transaction
from src.services.recognition_exchange import ExchangeTasks, handle_message
@ -51,6 +53,10 @@ settings = get_settings()
VERSION = settings.VERSION
UP_TIME = datetime.now(UTC)
# Свой обработчик loguru вместо стандартного: diagnose=False — значения локальных переменных не попадают в
# трейсбеки (#63)
setup_logger(level="DEBUG" if settings.DEBUG else "INFO")
# --- РАИСА: защищённый API (только вне DEBUG) ---------------------------------------------------
protected_middleware_available = False

View File

@ -5,8 +5,11 @@
import asyncio
import importlib
import subprocess
import sys
import threading
from http import HTTPStatus
from pathlib import Path
from types import SimpleNamespace
from typing import Any
@ -701,3 +704,48 @@ async def test_forwarded_for_only_from_trusted_proxy(tmp_path: Any, trusted: str
def test_forwarded_allow_ips_default_is_loopback() -> None:
assert Settings.model_fields["FORWARDED_ALLOW_IPS"].default == "127.0.0.1"
# --- Логгер: значения локальных переменных не попадают в лог (#63) ----------------------------------------------------
_LOG_EXCEPTION_SCRIPT = """
import importlib
import os
import sys
from loguru import logger
sys.path.insert(0, os.getcwd())
importlib.import_module("src.app")
def fail():
secret = "local-secret-value"
raise ValueError("boom" if secret else "")
try:
fail()
except ValueError:
logger.exception("ошибка")
logger.complete()
"""
def test_app_import_logs_exceptions_without_local_values(tmp_path: Path) -> None:
"""Импорт приложения настраивает loguru через setup_logger (diagnose=False): трейсбек есть, значений локальных
переменных в нём нет. Отдельный процесс — тесты перенастраивают обработчики loguru, здесь нужен чистый импорт.
Скрипт — файлом: без исходника (`python -c`) loguru не аннотирует строки и тест прошёл бы и с diagnose=True."""
script = tmp_path / "log_exception.py"
script.write_text(_LOG_EXCEPTION_SCRIPT)
result = subprocess.run(
[sys.executable, str(script)],
cwd=Path(__file__).resolve().parents[1],
capture_output=True,
text=True,
timeout=60,
check=True,
)
output = result.stdout + result.stderr
assert "ValueError: boom" in output
assert "local-secret-value" not in output