""" Demeter Server — Logging Configuration Sets up structured logging with optional Loki integration. Falls back to console-only logging if Loki is unreachable. """ from __future__ import annotations import logging import sys from typing import Optional def setup_logging(loki_url: Optional[str] = None, debug: bool = False) -> None: """ Configure logging for the Demeter server. Args: loki_url: Loki push endpoint (e.g., "http://localhost:3100/loki/api/v1/push"). If None, logs go to console only. debug: Enable DEBUG level logging. """ level = logging.DEBUG if debug else logging.INFO # Root logger root = logging.getLogger() root.setLevel(level) # Console handler console = logging.StreamHandler(sys.stdout) console.setLevel(level) fmt = logging.Formatter( "[%(asctime)s] %(levelname)-8s %(name)s — %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) console.setFormatter(fmt) root.addHandler(console) # Loki handler (optional) if loki_url: try: import logging_loki loki_handler = logging_loki.LokiHandler( url=loki_url, tags={"app": "demeter-server"}, version="1", ) loki_handler.setLevel(level) root.addHandler(loki_handler) logging.getLogger(__name__).info("Loki logging enabled at %s", loki_url) except ImportError: logging.getLogger(__name__).warning( "python-logging-loki not installed, Loki logging disabled" ) except Exception as e: logging.getLogger(__name__).warning( "Failed to connect to Loki at %s: %s", loki_url, e ) # Quiet noisy libraries logging.getLogger("aiocoap").setLevel(logging.WARNING) logging.getLogger("uvicorn.access").setLevel(logging.WARNING)