fix(logging): replace structlog with stdlib logging to prevent broken pipe crashes

structlog fails with BrokenPipeError when stdout is redirected (e.g., background
processes, Docker logs). Replace all structlog.get_logger() calls with
logging.getLogger() and convert keyword-style log calls to %-format strings.

Also removes stale Docs/tasks.md (2028 lines) and updates Robot Framework
tests to match current API behavior.
This commit is contained in:
2026-06-21 20:14:31 +02:00
parent be3e180137
commit 572aa0fc78
18 changed files with 299 additions and 2254 deletions

View File

@@ -14,17 +14,16 @@ Key Features:
from __future__ import annotations
import asyncio
import logging
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional
import structlog
from src.server.services.websocket_service import WebSocketService
logger = structlog.get_logger(__name__)
logger = logging.getLogger(__name__)
class LoadingStatus(str, Enum):
@@ -121,8 +120,8 @@ class BackgroundLoaderService:
self._shutdown = False
logger.info(
"BackgroundLoaderService initialized",
extra={"max_concurrent_loads": max_concurrent_loads}
"BackgroundLoaderService initialized max_concurrent_loads=%s",
max_concurrent_loads
)
async def start(self) -> None:
@@ -140,8 +139,8 @@ class BackgroundLoaderService:
self.worker_tasks.append(worker)
logger.info(
"Background workers started",
extra={"num_workers": len(self.worker_tasks)}
"Background workers started num_workers=%s",
len(self.worker_tasks)
)
async def stop(self) -> None:
@@ -164,8 +163,8 @@ class BackgroundLoaderService:
for i, result in enumerate(results):
if isinstance(result, Exception) and not isinstance(result, asyncio.CancelledError):
logger.error(
f"Worker {i} stopped with exception",
extra={"exception": str(result)}
"Worker %s stopped with exception exception=%s",
i, str(result)
)
self.worker_tasks = []
@@ -202,10 +201,15 @@ class BackgroundLoaderService:
self.active_tasks[key] = task
await self.task_queue.put(task)
logger.info("Added loading task for series: %s", key)
import logging
_task_logger = logging.getLogger(__name__)
_task_logger.info("Added loading task for series: %s", key)
# Broadcast initial status
await self._broadcast_status(task)
try:
await self._broadcast_status(task)
except Exception as e:
_task_logger.warning("Failed to broadcast initial status: %s", e)
async def check_missing_data(
self,
@@ -288,7 +292,8 @@ class BackgroundLoaderService:
)
logger.info(
f"Worker {worker_id} processing loading task for series: {task.key}"
"Worker %s processing loading task for series: %s",
worker_id, task.key
)
# Process the task
@@ -304,7 +309,10 @@ class BackgroundLoaderService:
logger.info("Worker %s task cancelled", worker_id)
break
except Exception as e:
logger.exception("Error in background worker %s: %s", worker_id, e)
logger.error(
"Error in background worker %s: %s",
worker_id, str(e)
)
# Continue processing other tasks
continue