import time import threading from contextlib import contextmanager from functools import wraps from prometheus_client import Counter, Histogram, Summary, start_http_server, Gauge from flask import current_app, g, request, Flask class EveAIMetrics: """ Central class for Prometheus metrics infrastructure. This class initializes the Prometheus HTTP server and provides shared functionality for metrics across components. Component-specific metrics should be defined in their respective modules. """ def __init__(self, app: Flask = None): self.app = app self._metrics_server_started = False if app is not None: self.init_app(app) def init_app(self, app: Flask): """Initialize metrics with Flask app and start Prometheus server""" self.app = app self._start_metrics_server() def _start_metrics_server(self): """Start the Prometheus metrics HTTP server if not already running""" if not self._metrics_server_started: try: metrics_port = self.app.config.get('PROMETHEUS_PORT', 8000) start_http_server(metrics_port) self.app.logger.info(f"Prometheus metrics server started on port {metrics_port}") self._metrics_server_started = True except Exception as e: self.app.logger.error(f"Failed to start metrics server: {e}") @staticmethod def get_standard_buckets(): """ Return the standard duration buckets for histogram metrics. Components should use these for consistency across the system. """ return [0.1, 0.5, 1, 2.5, 5, 10, 15, 30, 60, 120, 240, 360, float('inf')] @staticmethod def sanitize_label_values(labels_dict): """ Convert all label values to strings as required by Prometheus. Args: labels_dict: Dictionary of label name to label value Returns: Dictionary with all values converted to strings """ return {k: str(v) if v is not None else "" for k, v in labels_dict.items()}