Skip to main content
Glama
bitgeese

Sequential Questioning MCP Server

by bitgeese
monitoring.py5.63 kB
import time import functools from typing import Callable, Any, Dict, Optional import json from datetime import datetime from app.core.logging import app_logger class Metrics: """Simple metrics collection for the application.""" _instance = None def __new__(cls): """Singleton pattern to ensure only one metrics instance.""" if cls._instance is None: cls._instance = super(Metrics, cls).__new__(cls) cls._instance._initialize() return cls._instance def _initialize(self): """Initialize metrics storage.""" self.metrics = { "requests": 0, "errors": 0, "response_times": [], "endpoints": {}, "start_time": time.time() } def track_request(self, endpoint: str, response_time: float, status_code: int): """Track a request to an endpoint. Args: endpoint: The endpoint that was called response_time: The time taken to respond in milliseconds status_code: The HTTP status code returned """ self.metrics["requests"] += 1 self.metrics["response_times"].append(response_time) # Track by endpoint if endpoint not in self.metrics["endpoints"]: self.metrics["endpoints"][endpoint] = { "requests": 0, "errors": 0, "response_times": [], } self.metrics["endpoints"][endpoint]["requests"] += 1 self.metrics["endpoints"][endpoint]["response_times"].append(response_time) # Track errors if status_code >= 400: self.metrics["errors"] += 1 self.metrics["endpoints"][endpoint]["errors"] += 1 def get_metrics(self) -> Dict[str, Any]: """Get current metrics with calculated statistics. Returns: Dictionary of metrics """ uptime = time.time() - self.metrics["start_time"] avg_response_time = sum(self.metrics["response_times"]) / len(self.metrics["response_times"]) if self.metrics["response_times"] else 0 result = { "uptime_seconds": uptime, "total_requests": self.metrics["requests"], "total_errors": self.metrics["errors"], "error_rate": (self.metrics["errors"] / self.metrics["requests"]) if self.metrics["requests"] > 0 else 0, "avg_response_time_ms": avg_response_time, "endpoints": {} } # Add endpoint statistics for endpoint, data in self.metrics["endpoints"].items(): avg_endpoint_time = sum(data["response_times"]) / len(data["response_times"]) if data["response_times"] else 0 result["endpoints"][endpoint] = { "requests": data["requests"], "errors": data["errors"], "error_rate": (data["errors"] / data["requests"]) if data["requests"] > 0 else 0, "avg_response_time_ms": avg_endpoint_time } return result def reset_metrics(self): """Reset all metrics.""" self._initialize() # Create metrics instance metrics = Metrics() def measure_time(func: Callable) -> Callable: """Decorator to measure function execution time. Args: func: The function to measure Returns: Wrapped function that logs execution time """ @functools.wraps(func) async def wrapper(*args, **kwargs): start_time = time.time() try: result = await func(*args, **kwargs) return result finally: end_time = time.time() execution_time = (end_time - start_time) * 1000 # Convert to ms app_logger.debug(f"Function {func.__name__} took {execution_time:.2f}ms to execute") return wrapper def log_request(endpoint: str, log_inputs: bool = False) -> Callable: """Decorator to log API requests. Args: endpoint: Name of the endpoint log_inputs: Whether to log the input parameters Returns: Wrapped function that logs request details """ def decorator(func: Callable) -> Callable: @functools.wraps(func) async def wrapper(*args, **kwargs): start_time = time.time() status_code = 200 # Log request inputs if enabled if log_inputs: # Safely convert args/kwargs to string representation args_str = str(args) if args else "" kwargs_str = json.dumps({k: str(v) for k, v in kwargs.items()}) if kwargs else "" app_logger.info(f"Request to {endpoint}: args={args_str}, kwargs={kwargs_str}") else: app_logger.info(f"Request to {endpoint}") try: result = await func(*args, **kwargs) return result except Exception as e: status_code = 500 app_logger.exception(f"Error in {endpoint}: {str(e)}") raise finally: end_time = time.time() response_time = (end_time - start_time) * 1000 # Convert to ms # Track in metrics metrics.track_request(endpoint, response_time, status_code) app_logger.info(f"Response from {endpoint}: status={status_code}, time={response_time:.2f}ms") return wrapper return decorator

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/bitgeese/sequential-questioning'

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