015 add tracing
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
"""Centralized runtime OpenTelemetry tracing bootstrap."""
|
||||
|
||||
from fastapi import FastAPI
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
||||
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
|
||||
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
||||
from opentelemetry.instrumentation.redis import RedisInstrumentor
|
||||
from opentelemetry.sdk.resources import Resource
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
||||
|
||||
from app.config import ObservabilityConfig
|
||||
|
||||
_HTTPX_INSTRUMENTOR = HTTPXClientInstrumentor()
|
||||
_REDIS_INSTRUMENTOR = RedisInstrumentor()
|
||||
_TRACER_PROVIDER: TracerProvider | None = None
|
||||
|
||||
|
||||
def configure_tracing(app: FastAPI, observability: ObservabilityConfig) -> None:
|
||||
if not observability.enabled:
|
||||
return
|
||||
|
||||
tracer_provider = _get_or_create_tracer_provider(observability)
|
||||
_instrument_fastapi_app(app, tracer_provider=tracer_provider)
|
||||
_instrument_httpx(tracer_provider=tracer_provider)
|
||||
_instrument_redis(tracer_provider=tracer_provider)
|
||||
|
||||
|
||||
def _get_or_create_tracer_provider(observability: ObservabilityConfig) -> TracerProvider:
|
||||
global _TRACER_PROVIDER
|
||||
|
||||
if _TRACER_PROVIDER is not None:
|
||||
return _TRACER_PROVIDER
|
||||
|
||||
tracer_provider = _build_tracer_provider(observability)
|
||||
trace.set_tracer_provider(tracer_provider)
|
||||
_TRACER_PROVIDER = tracer_provider
|
||||
return tracer_provider
|
||||
|
||||
|
||||
def _build_tracer_provider(observability: ObservabilityConfig) -> TracerProvider:
|
||||
exporter = _build_span_exporter(observability)
|
||||
tracer_provider = TracerProvider(resource=_build_resource(observability))
|
||||
tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
|
||||
return tracer_provider
|
||||
|
||||
|
||||
def _build_span_exporter(observability: ObservabilityConfig) -> OTLPSpanExporter:
|
||||
return OTLPSpanExporter(
|
||||
endpoint=observability.otlp_endpoint,
|
||||
insecure=observability.otlp_insecure,
|
||||
)
|
||||
|
||||
|
||||
def _build_resource(observability: ObservabilityConfig) -> Resource:
|
||||
return Resource.create({"service.name": observability.service_name})
|
||||
|
||||
|
||||
def _instrument_fastapi_app(app: FastAPI, *, tracer_provider: TracerProvider) -> None:
|
||||
if getattr(app, "_is_instrumented_by_opentelemetry", False):
|
||||
return
|
||||
FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer_provider)
|
||||
|
||||
|
||||
def _instrument_httpx(*, tracer_provider: TracerProvider) -> None:
|
||||
if _HTTPX_INSTRUMENTOR.is_instrumented_by_opentelemetry:
|
||||
return
|
||||
_HTTPX_INSTRUMENTOR.instrument(tracer_provider=tracer_provider)
|
||||
|
||||
|
||||
def _instrument_redis(*, tracer_provider: TracerProvider) -> None:
|
||||
if _REDIS_INSTRUMENTOR.is_instrumented_by_opentelemetry:
|
||||
return
|
||||
_REDIS_INSTRUMENTOR.instrument(tracer_provider=tracer_provider)
|
||||
Reference in New Issue
Block a user