logging_config.py•2.71 kB
"""Logging Configuration for Terminal Control MCP Server
Provides standardized logging setup for debugging and monitoring.
"""
import logging
import logging.handlers
import sys
from pathlib import Path
from typing import Optional
def setup_logging(
level: str = "INFO",
log_file: Optional[str] = None,
enable_console: bool = True,
max_bytes: int = 10 * 1024 * 1024, # 10MB
backup_count: int = 3,
) -> logging.Logger:
"""Setup logging configuration for the Terminal Control MCP server
Args:
level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_file: Optional path to log file. If None, only console logging is used
enable_console: Whether to enable console logging
max_bytes: Maximum size of log file before rotation
backup_count: Number of backup log files to keep
Returns:
Root logger instance
"""
# Convert string level to logging constant
numeric_level = getattr(logging, level.upper(), logging.INFO)
# Create root logger
root_logger = logging.getLogger()
root_logger.setLevel(numeric_level)
# Clear any existing handlers
root_logger.handlers.clear()
# Create formatter
formatter = logging.Formatter(
fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
# Console handler
if enable_console:
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(numeric_level)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
# File handler with rotation
if log_file:
log_path = Path(log_file)
log_path.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.handlers.RotatingFileHandler(
filename=log_file,
maxBytes=max_bytes,
backupCount=backup_count,
encoding="utf-8",
)
file_handler.setLevel(numeric_level)
file_handler.setFormatter(formatter)
root_logger.addHandler(file_handler)
# Set specific logger levels for dependencies
logging.getLogger("fastmcp").setLevel(logging.WARNING)
logging.getLogger("asyncio").setLevel(logging.WARNING)
# Log startup message
logger = logging.getLogger(__name__)
logger.info(f"Logging initialized at {level} level")
if log_file:
logger.info(f"Log file: {log_file}")
return root_logger
def get_logger(name: str) -> logging.Logger:
"""Get a logger instance for a specific module
Args:
name: Logger name (usually __name__)
Returns:
Logger instance
"""
return logging.getLogger(name)