File size: 2,941 Bytes
674fb4e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | """
OpenTelemetry instrumentation for observability
Provides tracing, metrics, and structured logging
"""
import logging
from typing import Optional
from opentelemetry import trace, metrics
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader, ConsoleMetricExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from ..config import settings
# Configure logging
logging.basicConfig(
level=getattr(logging, settings.log_level.upper()),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def setup_observability(app=None):
"""
Setup OpenTelemetry observability
Args:
app: FastAPI application instance (optional)
"""
if not settings.enable_tracing:
logger.info("Tracing disabled")
return
# Create resource
resource = Resource.create({
"service.name": settings.app_name,
"service.version": settings.app_version,
"deployment.environment": settings.environment
})
# Setup tracing without polluting console stdout
if settings.enable_tracing:
tracer_provider = TracerProvider(resource=resource)
# Removed ConsoleSpanExporter to absolutely ensure no stdout flooding
trace.set_tracer_provider(tracer_provider)
# Instrument FastAPI if provided
if app:
FastAPIInstrumentor.instrument_app(app)
logger.info("Tracing enabled (Silently)")
# Setup metrics
if settings.enable_metrics:
# Removed ConsoleMetricExporter to prevent massive JSON stdout dumps
meter_provider = MeterProvider(
resource=resource,
metric_readers=[]
)
metrics.set_meter_provider(meter_provider)
logger.info("Metrics enabled (Silently)")
def get_tracer(name: str):
"""Get tracer for instrumentation"""
return trace.get_tracer(name)
def get_meter(name: str):
"""Get meter for metrics"""
return metrics.get_meter(name)
# Create global tracer and meter
tracer = get_tracer(__name__)
meter = get_meter(__name__)
# Create metrics
ingestion_counter = meter.create_counter(
"documents_ingested",
description="Number of documents ingested",
unit="1"
)
query_counter = meter.create_counter(
"queries_executed",
description="Number of queries executed",
unit="1"
)
query_duration = meter.create_histogram(
"query_duration_seconds",
description="Query execution time in seconds",
unit="s"
)
entity_counter = meter.create_counter(
"entities_extracted",
description="Number of entities extracted",
unit="1"
)
|