Skip to main content
Glama
logging_config.py3.97 kB
# Copyright (c) 2024 Rajesh # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """Logging configuration for docx-mcp server.""" import json import logging import logging.handlers import sys from datetime import datetime, timezone from pathlib import Path from typing import Any from .config import config class JSONFormatter(logging.Formatter): """Format logs as JSON for structured logging.""" def format(self, record: logging.LogRecord) -> str: """Format log record as JSON.""" log_obj: dict[str, Any] = { "timestamp": datetime.now(timezone.utc).isoformat(), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if record.exc_info: log_obj["exception"] = self.formatException(record.exc_info) # Include custom fields if present if hasattr(record, "tool"): log_obj["tool"] = record.tool if hasattr(record, "filepath"): log_obj["filepath"] = record.filepath if hasattr(record, "duration_ms"): log_obj["duration_ms"] = record.duration_ms return json.dumps(log_obj) def setup_logging() -> None: """Configure logging for the server.""" log_level = getattr(logging, config.log_level.upper(), logging.INFO) # Create logs directory in user's home or temp directory # Use ~/Library/Logs/docx-mcp on macOS if possible try: logs_dir = Path.home() / "Library" / "Logs" / "docx-mcp" logs_dir.mkdir(parents=True, exist_ok=True) except (OSError, PermissionError): # Fall back to temp directory import tempfile logs_dir = Path(tempfile.gettempdir()) / "docx-mcp-logs" logs_dir.mkdir(exist_ok=True) # Root logger configuration root_logger = logging.getLogger() root_logger.setLevel(log_level) # Console handler (standard format) console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(log_level) console_formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) console_handler.setFormatter(console_formatter) root_logger.addHandler(console_handler) # File handler (JSON format) log_file = logs_dir / f"docx_mcp_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" file_handler = logging.handlers.RotatingFileHandler( log_file, maxBytes=10485760, # 10MB backupCount=5, ) file_handler.setLevel(log_level) file_formatter = JSONFormatter() file_handler.setFormatter(file_formatter) root_logger.addHandler(file_handler) # Set lower log level for noisy libraries logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("asyncio").setLevel(logging.WARNING) def get_logger(name: str) -> logging.Logger: """Get a logger instance.""" return logging.getLogger(name)

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/Andrew82106/LLM_Docx_Agent_MCP'

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