Source code for radical.edge.logging_config

"""
Logging configuration for radical.edge

This module sets up standard Python logging with:
- Uvicorn-style colored output
- Support for correlation IDs in request context
- Structured log format

Import this module early in your application to configure logging.
"""

import logging
import sys
import copy
import contextvars
from typing import Optional


# Context variable for request correlation ID
correlation_id: contextvars.ContextVar[Optional[str]] = contextvars.ContextVar(
    'correlation_id', default=None
)


[docs] def set_correlation_id(req_id: str) -> None: """Set the correlation ID for the current async context.""" correlation_id.set(req_id)
[docs] def get_correlation_id() -> Optional[str]: """Get the correlation ID for the current async context.""" return correlation_id.get()
[docs] def clear_correlation_id() -> None: """Clear the correlation ID for the current async context.""" correlation_id.set(None)
[docs] class ColoredFormatter(logging.Formatter): """ Log formatter with Uvicorn-style coloring and correlation ID support. """ def __init__(self, fmt: Optional[str] = None, datefmt: Optional[str] = None, style: str = '%', use_colors: Optional[bool] = None): super().__init__(fmt, datefmt, style) if use_colors is None: use_colors = sys.stdout.isatty() self.use_colors = use_colors self.COLORS = { logging.DEBUG: "\033[36m", # Cyan logging.INFO: "\033[32m", # Green logging.WARNING: "\033[33m", # Yellow logging.ERROR: "\033[31m", # Red logging.CRITICAL: "\033[31;1m", # Bold Red } self.RESET = "\033[0m" self.DIM = "\033[2m"
[docs] def format(self, record: logging.LogRecord) -> str: record = copy.copy(record) # Add correlation ID if available req_id = correlation_id.get() if req_id: # Truncate for readability short_id = req_id[:8] if len(req_id) > 8 else req_id if self.use_colors: record.msg = f"{self.DIM}[{short_id}]{self.RESET} {record.msg}" else: record.msg = f"[{short_id}] {record.msg}" if not self.use_colors: return super().format(record) levelname = record.levelname if record.levelno in self.COLORS: # Match Uvicorn: "INFO: " (Colored, with colon, padded to 9) levelname_with_sep = f"{levelname}:" padded_levelname = f"{levelname_with_sep:<9}" record.levelname = (f"{self.COLORS[record.levelno]}" f"{padded_levelname}{self.RESET}") return super().format(record)
[docs] def configure_logging(level: int = logging.INFO, format_string: Optional[str] = None) -> None: """ Configure logging for radical.edge. Args: level: Logging level (default: logging.INFO). format_string: Custom format string (optional). """ if format_string is None: format_string = '%(levelname)s %(message)s' handler = logging.StreamHandler(sys.stdout) handler.setFormatter(ColoredFormatter(fmt=format_string)) logging.basicConfig(force=True, level=level, handlers=[handler]) logging.getLogger("radical.edge").setLevel(level)
# Auto-configure on import with INFO level configure_logging()