""" Manager Logger for centralized logging operations. This module provides a centralized logging interface for the collector management system with configurable log levels and error sanitization. """ from typing import Optional, Any class ManagerLogger: """Centralized logger wrapper for collector management operations.""" def __init__(self, logger=None, log_errors_only: bool = False): """ Initialize the manager logger. Args: logger: Logger instance. If None, no logging will be performed. log_errors_only: If True and logger is provided, only log error-level messages """ self.logger = logger self.log_errors_only = log_errors_only def _sanitize_error(self, message: str) -> str: """ Sanitize error message to prevent leaking internal details. Args: message: Original error message Returns: Sanitized error message """ # Remove sensitive patterns that might leak internal information sensitive_patterns = [ 'password=', 'token=', 'key=', 'secret=', 'auth=', 'api_key=', 'api_secret=', 'access_token=', 'refresh_token=' ] sanitized = message for pattern in sensitive_patterns: if pattern.lower() in sanitized.lower(): # Replace the value part after = with [REDACTED] parts = sanitized.split(pattern) if len(parts) > 1: # Find the end of the value (space, comma, or end of string) value_part = parts[1] end_chars = [' ', ',', ')', ']', '}', '\n', '\t'] end_idx = len(value_part) for char in end_chars: char_idx = value_part.find(char) if char_idx != -1 and char_idx < end_idx: end_idx = char_idx # Replace the value with [REDACTED] sanitized = parts[0] + pattern + '[REDACTED]' + value_part[end_idx:] return sanitized def log_debug(self, message: str) -> None: """Log debug message if logger is available and not in errors-only mode.""" if self.logger and not self.log_errors_only: self.logger.debug(message) def log_info(self, message: str) -> None: """Log info message if logger is available and not in errors-only mode.""" if self.logger and not self.log_errors_only: self.logger.info(message) def log_warning(self, message: str) -> None: """Log warning message if logger is available and not in errors-only mode.""" if self.logger and not self.log_errors_only: self.logger.warning(message) def log_error(self, message: str, exc_info: bool = False) -> None: """ Log error message if logger is available (always logs errors regardless of log_errors_only). Args: message: Error message to log exc_info: Whether to include exception info """ if self.logger: sanitized_message = self._sanitize_error(message) self.logger.error(sanitized_message, exc_info=exc_info) def log_critical(self, message: str, exc_info: bool = False) -> None: """ Log critical message if logger is available (always logs critical regardless of log_errors_only). Args: message: Critical message to log exc_info: Whether to include exception info """ if self.logger: sanitized_message = self._sanitize_error(message) self.logger.critical(sanitized_message, exc_info=exc_info) def is_enabled(self) -> bool: """Check if logging is enabled.""" return self.logger is not None def is_debug_enabled(self) -> bool: """Check if debug logging is enabled.""" return self.logger is not None and not self.log_errors_only def set_logger(self, logger) -> None: """Set or update the logger instance.""" self.logger = logger def set_errors_only(self, errors_only: bool) -> None: """Set or update the errors-only mode.""" self.log_errors_only = errors_only def get_logger_info(self) -> dict: """ Get information about the logger configuration. Returns: Dictionary with logger configuration details """ return { 'logger_available': self.logger is not None, 'logger_name': getattr(self.logger, 'name', None) if self.logger else None, 'log_errors_only': self.log_errors_only, 'debug_enabled': self.is_debug_enabled() }