Logging System
Overview
Elevator Saga uses a unified logging system with colored output and multiple log levels. The logging system provides consistent, filterable output across all components.
Log Levels
The logger supports four log levels with distinct colors:
DEBUG - Gray/Bright Black - Detailed debugging information
INFO - Cyan - General informational messages
WARNING - Yellow - Warning messages
ERROR - Red - Error messages
Configuration
Environment Variable
The default log level is controlled by the ELEVATOR_LOG_LEVEL environment variable:
# Set log level to DEBUG (default)
export ELEVATOR_LOG_LEVEL=DEBUG
# Set log level to INFO (less verbose)
export ELEVATOR_LOG_LEVEL=INFO
# Set log level to WARNING (only warnings and errors)
export ELEVATOR_LOG_LEVEL=WARNING
# Set log level to ERROR (only errors)
export ELEVATOR_LOG_LEVEL=ERROR
If not set, the default is DEBUG mode.
Programmatic Control
You can also control the log level programmatically:
from elevator_saga.utils.logger import LogLevel, set_log_level
# Set to INFO level
set_log_level(LogLevel.INFO)
# Set to DEBUG level
set_log_level(LogLevel.DEBUG)
Basic Usage
Simple Logging
from elevator_saga.utils.logger import debug, info, warning, error
# Simple messages
info("Server started successfully")
warning("Connection timeout")
error("Failed to load configuration")
debug("Processing tick 42")
With Prefix
Add a prefix to identify the source of the log message:
# Server logs
info("Client registered", prefix="SERVER")
debug("Algorithm client processed tick 42", prefix="SERVER")
# Client logs
info("API Client initialized", prefix="CLIENT")
warning("Command ignored", prefix="CLIENT")
# Controller logs
info("启动 MyController 算法", prefix="CONTROLLER")
error("模拟运行错误", prefix="CONTROLLER")
Advanced Usage
Custom Logger
Create a custom logger instance with specific settings:
from elevator_saga.utils.logger import get_logger, LogLevel
# Get a custom logger
logger = get_logger("MyComponent", min_level=LogLevel.WARNING)
logger.info("This will not appear (level too low)")
logger.warning("This will appear")
logger.error("This will appear")
Color Output
The logger automatically detects if output is to a TTY (terminal) and enables colors. When redirecting to files or pipes, colors are automatically disabled for clean output.
Log Format
All log messages follow a consistent format:
LEVEL [PREFIX] message
Examples:
DEBUG [SERVER] Algorithm client registered: abc-123
INFO [SERVER] Loading traffic from test_case_01.json
WARNING [SERVER] GUI client: timeout waiting for tick 42
ERROR [CLIENT] Reset failed: Connection refused
INFO [CONTROLLER] 启动 MyController 算法
Component Prefixes
Standard prefixes used throughout the system:
SERVER - Simulator server logs
CLIENT - API client logs
CONTROLLER - Controller/algorithm logs
You can use any prefix that makes sense for your component.
API Reference
Functions
- debug(message: str, prefix: str | None = None) None
Log a DEBUG level message.
- Parameters:
message – The message to log
prefix – Optional prefix to identify the source
- info(message: str, prefix: str | None = None) None
Log an INFO level message.
- Parameters:
message – The message to log
prefix – Optional prefix to identify the source
- warning(message: str, prefix: str | None = None) None
Log a WARNING level message.
- Parameters:
message – The message to log
prefix – Optional prefix to identify the source
- error(message: str, prefix: str | None = None) None
Log an ERROR level message.
- Parameters:
message – The message to log
prefix – Optional prefix to identify the source
Classes
- class LogLevel
Enumeration of available log levels.
- DEBUG = 0
Debug level - most verbose
- INFO = 1
Info level - general information
- WARNING = 2
Warning level - warnings only
- ERROR = 3
Error level - errors only
Best Practices
Use appropriate levels:
DEBUG for detailed state changes and internal operations
INFO for significant events (startup, completion, etc.)
WARNING for unexpected but recoverable situations
ERROR for failures and exceptions
Use prefixes consistently:
Always use the same prefix for the same component
Use uppercase for standard prefixes (SERVER, CLIENT, CONTROLLER)
Keep messages concise:
One log message per event
Include relevant context (IDs, values, etc.)
Avoid multi-line messages
Set appropriate default level:
Use DEBUG for development
Use INFO for production
Use WARNING for minimal logging
Avoid logging in tight loops:
Excessive logging can impact performance
Consider conditional logging or sampling
Examples
Server Startup
from elevator_saga.utils.logger import info, debug
info("Elevator simulation server (Async) running on http://127.0.0.1:8000", prefix="SERVER")
info("Using Quart (async Flask) for better concurrency", prefix="SERVER")
debug("Found 5 traffic files: ['test01.json', 'test02.json', ...]", prefix="SERVER")
Client Operations
from elevator_saga.utils.logger import info, warning, error
info("Client registered successfully with ID: xyz-789", prefix="CLIENT")
warning("Client type 'gui' cannot send control commands", prefix="CLIENT")
error("Reset failed: Connection refused", prefix="CLIENT")
Controller Logic
from elevator_saga.utils.logger import info, debug
info("启动 MyController 算法", prefix="CONTROLLER")
debug("Updated traffic info - max_tick: 1000", prefix="CONTROLLER")
info("停止 MyController 算法", prefix="CONTROLLER")