Source code for yt_framework.utils.logging
"""Colored console formatter and helpers used by pipeline startup."""
import logging
import sys
from typing import ClassVar
[docs]
def setup_logging(
level: int = logging.INFO,
name: str | None = None,
use_colors: bool = True, # noqa: FBT001,FBT002
) -> logging.Logger:
"""Configure logging with consistent formatting.
Args:
level: Logging level (default: INFO)
name: Logger name (default: root logger)
use_colors: Whether to use colored output
Returns:
Configured logger instance
"""
logger = logging.getLogger(name)
logger.setLevel(level)
# If this is a child logger (name is provided), disable propagation
# to prevent duplicate messages from propagating to root logger
if name is not None:
logger.propagate = False
# Remove existing handlers
logger.handlers.clear()
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(level)
# Formatter with timestamp
if use_colors and sys.stdout.isatty():
formatter = ColoredFormatter(
"%(asctime)s | %(levelname)s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
else:
formatter = logging.Formatter(
"%(asctime)s | %(levelname)-8s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
return logger
[docs]
def log_operation(logger: logging.Logger, message: str) -> None:
"""Log an operation start message with → prefix.
Args:
logger: Logger instance
message: Operation description
"""
logger.info(" → %s", message)
[docs]
def log_success(logger: logging.Logger, message: str) -> None:
"""Log a success/completion message with ✓ prefix.
Args:
logger: Logger instance
message: Success message
"""
logger.info(" ✓ %s", message)
[docs]
def log_config(
logger: logging.Logger,
config_dict: dict[str, object],
title: str = "Configuration",
) -> None:
"""Log configuration in a readable format.
Automatically masks sensitive values (keys containing 'secret' or 'key')
by showing only the last 4 characters.
Args:
logger: Logger instance
config_dict: Configuration dictionary to log
title: Title for the configuration section
Returns:
None
Example:
>>> config = {"api_key": "secret12345", "mode": "dev"}
>>> log_config(logger, config)
[Configuration]
api_key: ***2345
mode: dev
"""
log_header(logger, title)
for key, value in config_dict.items():
# Mask sensitive data
if "secret" in key.lower() or "key" in key.lower():
display = "***" + str(value)[-4:] if value else "(not set)"
else:
display = value
logger.info(" %s: %s", key, display)