From 8a84b7c306b1d2619fbd5ee4d0bfdda62a89e480 Mon Sep 17 00:00:00 2001 From: claude-dev Date: Tue, 10 Mar 2026 13:33:31 +0100 Subject: [PATCH] Add DEV_MODE with comprehensive logging for error diagnosis - DEV_MODE flag in config.py (env var, default true for dev server) - Log rotation: 5 MB max, 5 backups (RotatingFileHandler) - DEBUG level in dev mode, INFO in production - HTTP request logging middleware (dev mode only, skips static files) - External library log levels suppressed (httpx, httpcore, uvicorn) - Customer version: set DEV_MODE=false to disable verbose logging Co-Authored-By: Claude Opus 4.6 --- src/config.py | 4 ++++ src/main.py | 54 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/config.py b/src/config.py index 7c34e70..8be54cc 100644 --- a/src/config.py +++ b/src/config.py @@ -28,6 +28,10 @@ CLAUDE_MODEL_FAST = "claude-haiku-4-5-20251001" # Für einfache Aufgaben (Feed- # Ausgabesprache (Lagebilder, Faktenchecks, Zusammenfassungen) OUTPUT_LANGUAGE = "Deutsch" +# Dev-Modus: ausfuehrliches Logging (DEBUG-Level, HTTP-Request-Log) +# In Kundenversion auf False setzen oder Env-Variable entfernen +DEV_MODE = os.environ.get("DEV_MODE", "true").lower() == "true" + # RSS-Feeds (Fallback, primär aus DB geladen) RSS_FEEDS = { "deutsch": [ diff --git a/src/main.py b/src/main.py index 3ada9fc..144d178 100644 --- a/src/main.py +++ b/src/main.py @@ -15,7 +15,7 @@ from fastapi.responses import FileResponse, RedirectResponse from apscheduler.schedulers.asyncio import AsyncIOScheduler from starlette.middleware.base import BaseHTTPMiddleware -from config import STATIC_DIR, LOG_DIR, DATA_DIR, TIMEZONE +from config import STATIC_DIR, LOG_DIR, DATA_DIR, TIMEZONE, DEV_MODE from database import init_db, get_db from auth import decode_token from agents.orchestrator import orchestrator @@ -25,15 +25,33 @@ from services.fact_consolidation import consolidate_fact_checks # Logging os.makedirs(LOG_DIR, exist_ok=True) -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s [%(name)s] %(levelname)s: %(message)s", - handlers=[ - logging.StreamHandler(sys.stdout), - logging.FileHandler(os.path.join(LOG_DIR, "osint-monitor.log")), - ], +from logging.handlers import RotatingFileHandler +import time as _time + +_log_level = logging.DEBUG if DEV_MODE else logging.INFO +_file_handler = RotatingFileHandler( + os.path.join(LOG_DIR, "osint-monitor.log"), + maxBytes=5 * 1024 * 1024, # 5 MB + backupCount=5, + encoding="utf-8", ) +_file_handler.setLevel(_log_level) +_console_handler = logging.StreamHandler(sys.stdout) +_console_handler.setLevel(_log_level) + +logging.basicConfig( + level=_log_level, + format="%(asctime)s [%(name)s] %(levelname)s: %(message)s", + handlers=[_console_handler, _file_handler], +) +# Externe Bibliotheken nicht auf DEBUG setzen +logging.getLogger("httpx").setLevel(logging.WARNING) +logging.getLogger("httpcore").setLevel(logging.WARNING) +logging.getLogger("uvicorn.access").setLevel(logging.WARNING) +logging.getLogger("apscheduler").setLevel(logging.INFO) + logger = logging.getLogger("osint") +logger.info(f"Monitor gestartet (DEV_MODE={DEV_MODE}, Log-Level={logging.getLevelName(_log_level)})") class WebSocketManager: @@ -255,6 +273,24 @@ app = FastAPI( ) +# Request-Logging Middleware (nur im Dev-Modus) +if DEV_MODE: + _req_logger = logging.getLogger("osint.http") + + class RequestLoggingMiddleware(BaseHTTPMiddleware): + async def dispatch(self, request: Request, call_next): + start = _time.monotonic() + response = await call_next(request) + duration = (_time.monotonic() - start) * 1000 + # Statische Dateien und WebSocket-Upgrades nicht loggen + path = request.url.path + if not path.startswith(("/static/", "/favicon")) and "websocket" not in str(request.headers.get("upgrade", "")): + _req_logger.debug( + f"{request.method} {path} -> {response.status_code} ({duration:.0f}ms)" + ) + return response + + # Security-Headers Middleware class SecurityHeadersMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): @@ -275,6 +311,8 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware): app.add_middleware(SecurityHeadersMiddleware) +if DEV_MODE: + app.add_middleware(RequestLoggingMiddleware) # CORS app.add_middleware(