Skip to main content
Glama
logging_config.py5.03 kB
""" Central logging configuration for Promptheus. Provides structured logging setup with support for JSON formatting and environment-driven configuration. """ from __future__ import annotations import json import logging import os from logging import Handler from typing import Optional from promptheus.constants import PROMPTHEUS_DEBUG_ENV class JsonFormatter(logging.Formatter): """Simple JSON formatter for structured logs.""" def format(self, record: logging.LogRecord) -> str: payload = { "time": self.formatTime(record, self.datefmt), "level": record.levelname, "name": record.name, "message": record.getMessage(), } # Include extra fields from structured logging # These are fields added via logger.info(..., extra={...}) for key, value in record.__dict__.items(): if key not in { "name", "msg", "args", "created", "filename", "funcName", "levelname", "levelno", "lineno", "module", "msecs", "message", "pathname", "process", "processName", "relativeCreated", "thread", "threadName", "exc_info", "exc_text", "stack_info", "taskName", "getMessage", "asctime" }: payload[key] = value if record.exc_info: payload["exception"] = self.formatException(record.exc_info) if record.stack_info: payload["stack"] = record.stack_info return json.dumps(payload, ensure_ascii=False) class StructuredFormatter(logging.Formatter): """Formatter that includes structured logging fields in standard format.""" def format(self, record: logging.LogRecord) -> str: # Format the base message base_msg = super().format(record) # Collect extra fields extra_fields = [] for key, value in record.__dict__.items(): if key not in { "name", "msg", "args", "created", "filename", "funcName", "levelname", "levelno", "lineno", "module", "msecs", "message", "pathname", "process", "processName", "relativeCreated", "thread", "threadName", "exc_info", "exc_text", "stack_info", "taskName", "getMessage", "asctime" }: extra_fields.append(f"{key}={value}") # Append extra fields if present if extra_fields: return f"{base_msg} | {' '.join(extra_fields)}" return base_msg def setup_logging(default_level: int = logging.WARNING) -> None: """ Configure root logging based on environment flags. By default, logging is suppressed for end users (only WARNING and above). Logs only go to console if PROMPTHEUS_DEBUG is enabled or a log file is specified. Environment variables: - PROMPTHEUS_DEBUG: enable DEBUG level logging to console - PROMPTHEUS_LOG_LEVEL: override log level (INFO, WARNING, etc.) - PROMPTHEUS_LOG_FORMAT: "json" for JSON, otherwise format string - PROMPTHEUS_LOG_FILE: path to a log file (optional) - PROMPTHEUS_USER_ACTION_LOG_FILE: path to a separate log file for user actions (optional) """ debug_flag = os.getenv(PROMPTHEUS_DEBUG_ENV, "").lower() is_debug = debug_flag in {"1", "true", "yes", "on"} # Default to WARNING for production, DEBUG if explicitly enabled level = logging.DEBUG if is_debug else default_level env_level = os.getenv("PROMPTHEUS_LOG_LEVEL") if env_level: try: level = getattr(logging, env_level.upper()) except AttributeError: pass raw_format = os.getenv("PROMPTHEUS_LOG_FORMAT", "%(asctime)s %(levelname)s [%(name)s] %(message)s") use_json = raw_format.lower() == "json" log_file = os.getenv("PROMPTHEUS_LOG_FILE") # Only add handlers if debug mode is on OR log file is specified # This prevents ugly logging to console for normal users if not logging.getLogger().handlers: handlers: Optional[list[Handler]] = None if log_file: # Log to file handlers = [logging.FileHandler(log_file)] elif is_debug: # Log to console only if debug is explicitly enabled handlers = [logging.StreamHandler()] else: # No console logging for normal users - use NullHandler handlers = [logging.NullHandler()] logging.basicConfig(level=level, handlers=handlers) for handler in logging.getLogger().handlers: if use_json: handler.setFormatter(JsonFormatter()) else: handler.setFormatter(StructuredFormatter(raw_format)) else: logging.getLogger().setLevel(level) for handler in logging.getLogger().handlers: handler.setLevel(level) if use_json: handler.setFormatter(JsonFormatter()) else: handler.setFormatter(StructuredFormatter(raw_format))

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/abhichandra21/Promptheus'

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