From fc464afaf5975a376f3092e53b1c21801e6247bd Mon Sep 17 00:00:00 2001 From: hermes Date: Mon, 22 Jun 2026 09:47:47 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20Structlog-Integration=20f=C3=BCr=20stru?= =?UTF-8?q?kturiertes=20Logging=20(closes=20#4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/logging_config.py | 40 ++++++++++++++++++++++++++++++++++++++++ tests/test_logging.py | 25 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/logging_config.py create mode 100644 tests/test_logging.py diff --git a/src/logging_config.py b/src/logging_config.py new file mode 100644 index 0000000..d616c74 --- /dev/null +++ b/src/logging_config.py @@ -0,0 +1,40 @@ +"""Logging-Konfiguration mit structlog für strukturierte Logs.""" + +from __future__ import annotations + +from typing import cast + +import structlog + + +def setup_logging() -> None: + """Konfiguriert strukturiertes Logging mit structlog.""" + structlog.configure( + processors=[ + structlog.stdlib.filter_by_level, + structlog.stdlib.add_logger_name, + structlog.stdlib.add_log_level, + structlog.stdlib.PositionalArgumentsFormatter(), + structlog.processors.TimeStamper(fmt="iso"), + structlog.processors.StackInfoRenderer(), + structlog.processors.format_exc_info, + structlog.processors.UnicodeDecoder(), + structlog.dev.ConsoleRenderer(), + ], + context_class=dict, + logger_factory=structlog.stdlib.LoggerFactory(), + wrapper_class=structlog.stdlib.BoundLogger, + cache_logger_on_first_use=True, + ) + + +def get_logger(name: str) -> structlog.stdlib.BoundLogger: + """Erstellt einen benannten Logger. + + Args: + name: Logger-Name (üblicherweise __name__). + + Returns: + Konfigurierter structlog-Logger. + """ + return cast(structlog.stdlib.BoundLogger, structlog.get_logger(name)) diff --git a/tests/test_logging.py b/tests/test_logging.py new file mode 100644 index 0000000..90770f9 --- /dev/null +++ b/tests/test_logging.py @@ -0,0 +1,25 @@ +"""Tests für Logging-Konfiguration.""" + +import structlog + +from src.logging_config import get_logger, setup_logging + + +class TestLoggingConfig: + """Tests für logging_config.""" + + def test_setup_logging_laeuft_ohne_fehler_durch(self) -> None: + """setup_logging() läuft ohne Fehler.""" + setup_logging() # Sollte keine Exception werfen + + def test_get_logger_gibt_bound_logger_zurueck(self) -> None: + """get_logger(__name__) gibt Logger-ähnliches Objekt zurück.""" + logger = get_logger("test_logger") + # Structlog gibt BoundLoggerLazyProxy zurück (lazy evaluation) + assert hasattr(logger, "info") + assert hasattr(logger, "warning") + + def test_logger_info_produziert_keinen_fehler(self) -> None: + """Logger.info() produziert keinen Fehler.""" + logger = get_logger("test_logger") + logger.info("test message") # Sollte keine Exception werfen