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 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-03-10 13:33:31 +01:00
Ursprung 22f817c42c
Commit 8a84b7c306
2 geänderte Dateien mit 50 neuen und 8 gelöschten Zeilen

Datei anzeigen

@@ -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": [

Datei anzeigen

@@ -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(