From 7449e2ae0ea178794373a5dad9f065d8896be0a1 Mon Sep 17 00:00:00 2001 From: Gal Hubara Agam <96368689+galagam@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:22:16 +0200 Subject: [PATCH 1/2] [fix][5889686] AutoCast: Fix logger Previously relied on quantization logger, which caused logs to be suppressed when onnx.autocast was used directly Instead: - Inherit format and level if called from onnx.quantization - Configure independent format and level if called from onnx.autocast Signed-off-by: Gal Hubara Agam <96368689+galagam@users.noreply.github.com> --- modelopt/onnx/autocast/logging_config.py | 43 +++++++++++++++++------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/modelopt/onnx/autocast/logging_config.py b/modelopt/onnx/autocast/logging_config.py index f65f041c0..0c12ec59d 100644 --- a/modelopt/onnx/autocast/logging_config.py +++ b/modelopt/onnx/autocast/logging_config.py @@ -22,26 +22,41 @@ import logging import os +import sys -# Create a parent logger for all AutoCast components -logger = logging.getLogger("autocast") +# Create a logger for all AutoCast components as a child of modelopt.onnx +# This ensures autocast inherits log level and format when called from quantization +logger = logging.getLogger("modelopt.onnx.autocast") def configure_logging(level=logging.INFO, log_file=None): """Configure logging for all AutoCast components. Args: - level: The logging level to use (default: logging.INFO). + level: The logging level to use. Can be a string (e.g., "DEBUG", "INFO") or + a logging constant (e.g., logging.DEBUG). Default: logging.INFO. log_file: Optional path to a log file. If provided, logs will be written to this file in addition to stdout (default: None). """ - # Set level for the parent logger and all child loggers + # Check if parent logger (modelopt.onnx) already has handlers configured + parent_logger = logging.getLogger("modelopt.onnx") + parent_has_handlers = len(parent_logger.handlers) > 0 + + # If parent is configured and no explicit level provided, inherit parent's level + if parent_has_handlers and level == logging.INFO: + level = parent_logger.level + + # Set level for the autocast logger (accepts both string and int) logger.setLevel(level) # Remove any existing handlers to ensure clean configuration for handler in logger.handlers[:]: logger.removeHandler(handler) + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(message)s" + ) + # Add file handler if log_file is specified if log_file: try: @@ -50,9 +65,6 @@ def configure_logging(level=logging.INFO, log_file=None): if log_dir: os.makedirs(log_dir, exist_ok=True) - formatter = logging.Formatter( - "%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(message)s" - ) file_handler = logging.FileHandler(log_file) file_handler.setFormatter(formatter) logger.addHandler(file_handler) @@ -60,14 +72,21 @@ def configure_logging(level=logging.INFO, log_file=None): except Exception as e: logging.error(f"Failed to setup file logging to {log_file}: {e!s}") - # Allow log messages to propagate to the root logger for testing compatibility - # This enables pytest's caplog fixture to capture logs while still maintaining - # our custom formatting through the handlers above - logger.propagate = True + if parent_has_handlers: + # Parent logger is configured (called from quantization/other onnx modules) + # Propagate to parent to use its handlers and format + logger.propagate = True + else: + # Standalone mode (called directly via python3 -m modelopt.onnx.autocast) + # Add our own console handler with autocast-specific format + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setFormatter(formatter) + logger.addHandler(console_handler) + logger.propagate = False # Ensure all child loggers inherit the level setting for name in logging.root.manager.loggerDict: - if name.startswith("autocast"): + if name.startswith("modelopt.onnx.autocast"): logging.getLogger(name).setLevel(level) From f5bfb89700409bab266a6d12b6d0b996b528d0e8 Mon Sep 17 00:00:00 2001 From: Gal Hubara Agam <96368689+galagam@users.noreply.github.com> Date: Sun, 15 Feb 2026 08:57:45 +0200 Subject: [PATCH 2/2] refactor - readability and pytests support Signed-off-by: Gal Hubara Agam <96368689+galagam@users.noreply.github.com> --- modelopt/onnx/autocast/logging_config.py | 26 ++++++++++++++++++------ modelopt/onnx/logging_config.py | 6 ++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/modelopt/onnx/autocast/logging_config.py b/modelopt/onnx/autocast/logging_config.py index 0c12ec59d..21f9f65c5 100644 --- a/modelopt/onnx/autocast/logging_config.py +++ b/modelopt/onnx/autocast/logging_config.py @@ -29,12 +29,15 @@ logger = logging.getLogger("modelopt.onnx.autocast") -def configure_logging(level=logging.INFO, log_file=None): +def configure_logging(level=None, log_file=None): """Configure logging for all AutoCast components. + If logging level is provided, it will be used regardless of parent logger log level. + Otherwise, inherits from parent logger if exists, or fallback to default: logging.INFO. + Args: level: The logging level to use. Can be a string (e.g., "DEBUG", "INFO") or - a logging constant (e.g., logging.DEBUG). Default: logging.INFO. + a logging constant (e.g., logging.DEBUG) default: None. log_file: Optional path to a log file. If provided, logs will be written to this file in addition to stdout (default: None). """ @@ -42,13 +45,23 @@ def configure_logging(level=logging.INFO, log_file=None): parent_logger = logging.getLogger("modelopt.onnx") parent_has_handlers = len(parent_logger.handlers) > 0 - # If parent is configured and no explicit level provided, inherit parent's level - if parent_has_handlers and level == logging.INFO: - level = parent_logger.level + # Determine the logging level to use + if level is None: + # No explicit level provided - inherit from parent or use default + if parent_has_handlers: + level = parent_logger.level + else: + level = logging.INFO + # else: use the provided level as-is # Set level for the autocast logger (accepts both string and int) logger.setLevel(level) + # If parent has handlers (standalone mode), also update parent's level + # so the parent's console handler respects the autocast log level + if parent_has_handlers: + parent_logger.setLevel(level) + # Remove any existing handlers to ensure clean configuration for handler in logger.handlers[:]: logger.removeHandler(handler) @@ -82,7 +95,8 @@ def configure_logging(level=logging.INFO, log_file=None): console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) logger.addHandler(console_handler) - logger.propagate = False + # Always propagate to support pytest's caplog fixture in tests + logger.propagate = True # Ensure all child loggers inherit the level setting for name in logging.root.manager.loggerDict: diff --git a/modelopt/onnx/logging_config.py b/modelopt/onnx/logging_config.py index fd0c306a6..99468b87f 100644 --- a/modelopt/onnx/logging_config.py +++ b/modelopt/onnx/logging_config.py @@ -64,8 +64,10 @@ def configure_logging(level=logging.INFO, log_file=None): console_handler.setFormatter(formatter) logger.addHandler(console_handler) - # Prevent log messages from propagating to the root logger - logger.propagate = False + # Allow log messages to propagate to the root logger for testing compatibility + # This enables pytest's caplog fixture to capture logs while still maintaining + # our custom formatting through the handlers above + logger.propagate = True # Ensure all child loggers inherit the level setting for name in logging.root.manager.loggerDict: