From c937c8173ff2530353e254be98cef38cf46b94f9 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Thu, 8 Oct 2026 16:41:40 +0400 Subject: [PATCH] =?UTF-8?q?fix(logger):=20=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20setup=5Flogger=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=B5=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup_logger() с diagnose=False существовал, но не вызывался: работал обработчик loguru по умолчанию (diagnose=True), и трейсбек любого залогированного исключения содержал значения локальных переменных. Теперь src/app.py вызывает setup_logger при импорте, как tabular-parser. Регрессионный тест в отдельном процессе: исключение с локальной переменной логируется с трейсбеком, но без её значения. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2 --- api/src/app.py | 8 +++++++- api/tests/test_app.py | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/api/src/app.py b/api/src/app.py index 8f72817..6b42fc4 100644 --- a/api/src/app.py +++ b/api/src/app.py @@ -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 diff --git a/api/tests/test_app.py b/api/tests/test_app.py index c739343..3436cc6 100644 --- a/api/tests/test_app.py +++ b/api/tests/test_app.py @@ -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 -- 2.47.2