"""Logging configuration for MCP Server."""
import logging
import sys
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Optional
def setup_logging(log_dir: str, log_level: str = "DEBUG") -> logging.Logger:
"""
Configure logging with console and file handlers.
Console: INFO+
File: DEBUG+ with rotation
Args:
log_dir: Directory for log files
log_level: Logging level (default: DEBUG)
Returns:
Logger: Configured root logger
"""
# Create log directory
log_path = Path(log_dir)
log_path.mkdir(parents=True, exist_ok=True)
# Root logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# Remove existing handlers
logger.handlers.clear()
# Console handler (INFO+)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
# File handler (DEBUG+) with rotation
log_file = log_path / "mcp_server.log"
file_handler = RotatingFileHandler(
log_file,
maxBytes=10 * 1024 * 1024, # 10MB
backupCount=5,
)
file_handler.setLevel(logging.DEBUG)
file_formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
logger.info(f"Logging configured. Console: INFO+, File: DEBUG+ -> {log_file}")
return logger
def artifact_path(log_dir: str, run_id: str, filename: str) -> Path:
"""
Generate path for artifact file.
Creates directory structure: {log_dir}/runs/{run_id}/
Args:
log_dir: Base log directory
run_id: Unique run identifier
filename: Artifact filename
Returns:
Path: Full path to artifact file
"""
artifact_dir = Path(log_dir) / "runs" / run_id
artifact_dir.mkdir(parents=True, exist_ok=True)
return artifact_dir / filename
def get_logger(name: Optional[str] = None) -> logging.Logger:
"""
Get a logger instance.
Args:
name: Logger name (typically __name__)
Returns:
Logger: Logger instance
"""
return logging.getLogger(name)