Skip to main content
Glama
norandom

RAGFlow Claude MCP Server

by norandom
logging_config.py4.8 kB
""" Logging configuration for RAGFlow MCP Server. This module provides structured logging configuration with appropriate formatting and levels for better observability and debugging. """ import logging import sys from typing import Optional import json from datetime import datetime class StructuredFormatter(logging.Formatter): """ Custom formatter that outputs structured JSON logs for better parsing. """ def format(self, record: logging.LogRecord) -> str: # Create base log entry log_entry = { "timestamp": datetime.utcnow().isoformat() + "Z", "level": record.levelname, "logger": record.name, "message": record.getMessage(), "module": record.module, "function": record.funcName, "line": record.lineno } # Add exception info if present if record.exc_info: log_entry["exception"] = self.formatException(record.exc_info) # Add extra fields if present if hasattr(record, "extra_fields"): log_entry.update(record.extra_fields) return json.dumps(log_entry, ensure_ascii=False) class HumanReadableFormatter(logging.Formatter): """ Formatter for human-readable console output. """ def __init__(self): super().__init__( fmt="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) def setup_logging( level: str = "INFO", structured: bool = False, log_file: Optional[str] = None ) -> None: """ Set up logging configuration for the application. Args: level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) structured: Whether to use structured JSON logging log_file: Optional path to log file """ # 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 existing handlers root_logger.handlers.clear() # Choose formatter if structured: formatter = StructuredFormatter() else: formatter = HumanReadableFormatter() # Console handler - use stderr to avoid interfering with MCP protocol on stdout console_handler = logging.StreamHandler(sys.stderr) console_handler.setLevel(numeric_level) console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) # File handler if specified if log_file: file_handler = logging.FileHandler(log_file) file_handler.setLevel(numeric_level) # Always use structured format for file logs file_handler.setFormatter(StructuredFormatter()) root_logger.addHandler(file_handler) # Set up specific logger for our application app_logger = logging.getLogger("ragflow-mcp") app_logger.setLevel(numeric_level) # Reduce noise from external libraries logging.getLogger("aiohttp").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("httpx").setLevel(logging.WARNING) def get_logger(name: str) -> logging.Logger: """ Get a logger instance with the given name. Args: name: Logger name Returns: Logger instance """ return logging.getLogger(f"ragflow-mcp.{name}") def log_with_context( logger: logging.Logger, level: int, message: str, **context ) -> None: """ Log a message with additional context fields. Args: logger: Logger instance level: Log level message: Log message **context: Additional context fields """ # Create a log record with extra fields if context: extra = {"extra_fields": context} logger.log(level, message, extra=extra) else: logger.log(level, message) # Convenience functions for common log levels with context def log_info(logger: logging.Logger, message: str, **context) -> None: """Log info message with context.""" log_with_context(logger, logging.INFO, message, **context) def log_warning(logger: logging.Logger, message: str, **context) -> None: """Log warning message with context.""" log_with_context(logger, logging.WARNING, message, **context) def log_error(logger: logging.Logger, message: str, **context) -> None: """Log error message with context.""" log_with_context(logger, logging.ERROR, message, **context) def log_debug(logger: logging.Logger, message: str, **context) -> None: """Log debug message with context.""" log_with_context(logger, logging.DEBUG, message, **context)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/norandom/ragflow-claude-desktop-local-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server