6.9 KiB
Logging Guidelines
- Status: Canonical
- Last reviewed: 2026-07-05
- Update when: Logging utilities, exception-handling policy, or silent-handler criteria change.
This document describes the logging conventions and best practices for ComfyUI-LLM-Session.
This is the canonical policy for current logging, exception-handling, and
silent-handler decisions. Historical audit records such as
error-handling-audit.md and
acceptable-silent-errors.md preserve past
review context, but should not override the rules in this document.
Log Levels
The project uses three log levels:
| Level | Description | When to Use |
|---|---|---|
minimal |
Only critical errors | Production environments, minimal console output |
timing |
Timing information + critical errors (default) | Normal development and usage |
debug |
Full debug output including tracebacks | Debugging issues, development |
Logging Utilities
Core Module: core.logging_utils
The core.logging_utils module provides common logging helpers:
from core.logging_utils import (
get_module_logger,
log_error_safely,
log_with_exception_info,
create_fallback_logger,
handle_exception_safely,
LOG_LEVEL_MINIMAL,
LOG_LEVEL_TIMING,
LOG_LEVEL_DEBUG,
)
Getting a Module Logger
# Create a logger for your module
log = get_module_logger("MyModuleName")
# Use the logger
log("Operation completed", LOG_LEVEL_TIMING)
log("Debug detail", LOG_LEVEL_DEBUG)
Logging Errors in Except Blocks
Recommended pattern:
from core.logging_utils import log_error_safely, LOG_LEVEL_MINIMAL
try:
# some operation
result = do_something()
except Exception as e:
log_error_safely("MyModule", e, "Failed to do something", LOG_LEVEL_MINIMAL)
return None # or appropriate fallback
Alternative pattern with fallback logger:
from core.logging_utils import create_fallback_logger, LOG_LEVEL_MINIMAL
# Create fallback logger at module level
_log_error = create_fallback_logger("MyModule", LOG_LEVEL_MINIMAL)
def my_function():
try:
# some operation
result = do_something()
except Exception as e:
_log_error(e, "Failed to do something")
return None
Logging with Full Exception Info
For debug-level logging with traceback information:
from core.logging_utils import log_with_exception_info, LOG_LEVEL_DEBUG
try:
# some operation
result = do_something()
except Exception:
log_with_exception_info("MyModule", "Failed to do something", level=LOG_LEVEL_DEBUG)
return None
Error Handling Patterns
Pattern 1: Fallback with Logging
Use when the operation has a safe fallback:
from core.logging_utils import log_error_safely, LOG_LEVEL_TIMING
def load_optional_config(path: str) -> dict:
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
log_error_safely("ConfigLoader", e, "Failed to load optional config", LOG_LEVEL_TIMING)
return {} # safe fallback
Pattern 2: Critical Error with Propagation
Use when the operation must succeed:
from core.logging_utils import log_error_safely, LOG_LEVEL_MINIMAL
def load_required_history(path: str) -> dict:
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
log_error_safely("HistoryLoader", e, "Failed to load required history", LOG_LEVEL_MINIMAL)
raise # re-raise for caller to handle
Pattern 3: Silent Error (Acceptable)
Use only for truly optional operations where logging would add noise:
def cleanup_temp_file(path: str) -> None:
try:
os.remove(path)
except Exception:
pass # Acceptable: temp file cleanup is best-effort
When Silence Is Acceptable
Silent errors (Pattern 3) should only be used when all of the following are true:
- Fallback behavior exists.
- Failure does not risk data corruption or data loss.
- Core functionality continues to work.
- Logging would add noise because the error is expected in normal operation.
- The issue can still be diagnosed through another path when needed.
Silent handlers should be reviewed when:
- Users report issues that may be related to these code paths.
- Debugging becomes difficult due to lack of visibility.
- Fallback behavior changes.
- The error becomes more frequent due to external changes.
When a silent handler remains intentional, keep the rationale documented in the nearest relevant policy, audit, or code comment.
Best Practices
DO:
- Use module-specific loggers for clear log attribution
- Include context in error messages (what operation was being attempted)
- Use appropriate log levels (minimal for errors, timing for info, debug for verbose)
- Log before falling back so users know when fallbacks are triggered
- Keep log messages concise but informative
DON'T:
- Don't use bare
except:- always useexcept Exception: - Don't log in loops without rate limiting
- Don't log sensitive information (API keys, personal data)
- Don't use print() directly - use logging utilities
- Don't silently swallow errors without documentation
Migration Guide
Replacing Existing Patterns
Old pattern:
def _simple_config_log(message: str, log_level: str) -> None:
try:
if str(log_level).strip().lower() != "minimal":
print(f"[LLM Session Simple] {message}")
except Exception:
pass
New pattern:
from core.logging_utils import get_module_logger, LOG_LEVEL_TIMING
log = get_module_logger("LLM Session Simple")
# Usage
log("Config loaded", LOG_LEVEL_TIMING)
Old pattern:
try:
# operation
except Exception:
pass # Silent failure
New pattern:
from core.logging_utils import log_error_safely, LOG_LEVEL_MINIMAL
try:
# operation
except Exception as e:
log_error_safely("MyModule", e, "operation description", LOG_LEVEL_MINIMAL)
# fallback or re-raise
Configuration
Setting Log Levels
from core.logging_utils import set_global_log_level, set_module_log_level
# Set global log level
set_global_log_level("debug")
# Set module-specific log level
set_module_log_level("MyModule", "minimal")
Log Level Hierarchy
Log levels follow this hierarchy (most verbose to least verbose):
debug- Shows all messagestiming- Shows timing + minimal messagesminimal- Shows only critical errors
File Locations
core/logging_utils.py- Logging utility implementationsdocs/logging-guidelines.md- This documentdocs/error-handling-audit.md- Historical 2026-03-22 audit of error handling locationsdocs/acceptable-silent-errors.md- Historical 2026-03-22 silent-error allowlist