"""Complete observability setup orchestration.""" from typing import Any from .logging import configure_logging from .opentelemetry_setup import init_opentelemetry from .prometheus import get_business_metrics, init_prometheus_metrics def setup_observability( settings_or_app: Any, service_name: str | None = None, service_version: str = "1.0.0", log_level: str = "INFO", otlp_endpoint: str | None = None, ) -> dict[str, Any]: """Setup complete observability stack for a service""" # Handle both settings object and individual parameters if hasattr(settings_or_app, "service_name"): # Called with settings object settings = settings_or_app service_name = settings.service_name service_version = getattr(settings, "service_version", "1.0.0") log_level = getattr(settings, "log_level", "INFO") otlp_endpoint = getattr(settings, "otel_exporter_endpoint", None) app = None else: # Called with app object app = settings_or_app if not service_name: raise ValueError("service_name is required when passing app object") # Configure logging configure_logging(service_name or "unknown", log_level) # Initialize OpenTelemetry tracer, meter = init_opentelemetry( service_name or "unknown", service_version, otlp_endpoint ) # Get business metrics business_metrics = get_business_metrics(service_name or "unknown") # If app is provided, set up Prometheus and add to app state if app: # Initialize Prometheus metrics instrumentator = init_prometheus_metrics(app, service_name or "unknown") # Add to app state app.state.tracer = tracer app.state.meter = meter app.state.metrics = business_metrics app.state.instrumentator = instrumentator return { "tracer": tracer, "meter": meter, "metrics": business_metrics, "instrumentator": instrumentator, } # Just return the observability components return {"tracer": tracer, "meter": meter, "metrics": business_metrics}