133 lines
3.8 KiB
Python
133 lines
3.8 KiB
Python
"""Logging configuration for the TradingAgents framework.
|
|
|
|
This module provides structured logging setup for consistent log formatting
|
|
across all framework components.
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
|
|
def setup_logging(
|
|
level: str = "INFO",
|
|
log_file: Path | None = None,
|
|
name: str = "tradingagents",
|
|
) -> logging.Logger:
|
|
"""Configure logging for the trading agents framework.
|
|
|
|
Args:
|
|
level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL).
|
|
log_file: Optional file path for log output.
|
|
name: Logger name, defaults to 'tradingagents'.
|
|
|
|
Returns:
|
|
Configured logger instance.
|
|
|
|
Example:
|
|
>>> logger = setup_logging("DEBUG", Path("logs/trading.log"))
|
|
>>> logger.info("Starting trading analysis")
|
|
"""
|
|
logger = logging.getLogger(name)
|
|
logger.setLevel(getattr(logging, level.upper()))
|
|
|
|
# Remove existing handlers to avoid duplicates
|
|
logger.handlers = []
|
|
|
|
formatter = logging.Formatter(
|
|
"%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
datefmt="%Y-%m-%d %H:%M:%S",
|
|
)
|
|
|
|
# Console handler
|
|
console_handler = logging.StreamHandler(sys.stdout)
|
|
console_handler.setFormatter(formatter)
|
|
logger.addHandler(console_handler)
|
|
|
|
# File handler (optional)
|
|
if log_file:
|
|
log_file = Path(log_file)
|
|
log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
file_handler = logging.FileHandler(log_file)
|
|
file_handler.setFormatter(formatter)
|
|
logger.addHandler(file_handler)
|
|
|
|
return logger
|
|
|
|
|
|
def get_logger(name: str) -> logging.Logger:
|
|
"""Get a logger with the given name.
|
|
|
|
Args:
|
|
name: Logger name (typically __name__ of the module).
|
|
|
|
Returns:
|
|
Logger instance.
|
|
|
|
Example:
|
|
>>> logger = get_logger(__name__)
|
|
>>> logger.info("Module loaded")
|
|
"""
|
|
return logging.getLogger(name)
|
|
|
|
|
|
class TradingAgentsLogger:
|
|
"""Context manager for logging trading operations.
|
|
|
|
Provides structured logging with timing information for operations.
|
|
|
|
Example:
|
|
>>> with TradingAgentsLogger("market_analysis", "AAPL") as log:
|
|
... # Perform analysis
|
|
... log.info("Fetching market data")
|
|
"""
|
|
|
|
def __init__(self, operation: str, symbol: str | None = None):
|
|
"""Initialize the logger context.
|
|
|
|
Args:
|
|
operation: Name of the operation being logged.
|
|
symbol: Optional trading symbol being analyzed.
|
|
"""
|
|
self.operation = operation
|
|
self.symbol = symbol
|
|
self.logger = get_logger(f"tradingagents.{operation}")
|
|
self.start_time: datetime | None = None
|
|
|
|
def __enter__(self) -> "TradingAgentsLogger":
|
|
"""Enter the logging context."""
|
|
self.start_time = datetime.now(timezone.utc)
|
|
msg = f"Starting {self.operation}"
|
|
if self.symbol:
|
|
msg += f" for {self.symbol}"
|
|
self.logger.info(msg)
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
"""Exit the logging context."""
|
|
if self.start_time:
|
|
duration = (datetime.now(timezone.utc) - self.start_time).total_seconds()
|
|
if exc_type:
|
|
self.logger.error(
|
|
f"{self.operation} failed after {duration:.2f}s: {exc_val}"
|
|
)
|
|
else:
|
|
self.logger.info(f"{self.operation} completed in {duration:.2f}s")
|
|
|
|
def info(self, message: str):
|
|
"""Log an info message."""
|
|
self.logger.info(message)
|
|
|
|
def warning(self, message: str):
|
|
"""Log a warning message."""
|
|
self.logger.warning(message)
|
|
|
|
def error(self, message: str):
|
|
"""Log an error message."""
|
|
self.logger.error(message)
|
|
|
|
def debug(self, message: str):
|
|
"""Log a debug message."""
|
|
self.logger.debug(message)
|