diff --git a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py index eb76594ea..37c64527a 100644 --- a/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py +++ b/libraries/microsoft-agents-activity/microsoft_agents/activity/config/_configure_logging.py @@ -20,6 +20,44 @@ } +class ColorFormatter(logging.Formatter): + """Logging formatter that can add ANSI color based on severity.""" + + MAGENTA = "\033[1;35m" + RED = "\033[1;31m" + YELLOW = "\033[1;33m" + GREEN = "\033[1;32m" + BLUE = "\033[1;34m" + RESET = "\033[0m" + + FMT = ( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + ) + + def __init__( + self, + use_colors: bool = True, + ) -> None: + super().__init__(fmt=self.FMT) + self._plain_formatter = logging.Formatter(fmt=self.FMT) + if not use_colors: + self._formatters: dict[int, logging.Formatter] = {} + return + self._formatters = { + logging.CRITICAL: logging.Formatter( + f"{self.MAGENTA}{self.FMT}{self.RESET}" + ), + logging.ERROR: logging.Formatter(f"{self.RED}{self.FMT}{self.RESET}"), + logging.WARNING: logging.Formatter(f"{self.YELLOW}{self.FMT}{self.RESET}"), + logging.INFO: logging.Formatter(f"{self.GREEN}{self.FMT}{self.RESET}"), + logging.DEBUG: logging.Formatter(f"{self.BLUE}{self.FMT}{self.RESET}"), + } + + def format(self, record: logging.LogRecord) -> str: + formatter = self._formatters.get(record.levelno) + return (formatter or self._plain_formatter).format(record) + + def _configure_logging(logging_config: dict): """Configures logging based on the provided logging configuration dictionary. @@ -31,9 +69,7 @@ def _configure_logging(logging_config: dict): console_handler = logging.StreamHandler() console_handler.setFormatter( - logging.Formatter( - "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" - ) + ColorFormatter(use_colors=console_handler.stream.isatty()) ) for key in log_levels: @@ -50,6 +86,7 @@ def _configure_logging(logging_config: dict): else: logger = logging.getLogger(namespace) + logger.propagate = False # Prevent log messages from being propagated logger.handlers.clear() # Remove existing handlers to prevent duplicates logger.addHandler(console_handler) logger.setLevel(level)