aidial_sdk/telemetry/init.py (95 lines of code) (raw):
import logging
from fastapi import FastAPI
from opentelemetry._logs import set_logger_provider
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
OTLPMetricExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter,
)
from opentelemetry.exporter.prometheus import PrometheusMetricReader
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from opentelemetry.instrumentation.system_metrics import (
SystemMetricsInstrumentor,
)
from opentelemetry.instrumentation.urllib import URLLibInstrumentor
from opentelemetry.metrics import set_meter_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics._internal.export import (
PeriodicExportingMetricReader,
)
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import set_tracer_provider
from prometheus_client import start_http_server
from aidial_sdk.telemetry.types import TelemetryConfig
def init_telemetry(
app: FastAPI,
config: TelemetryConfig,
):
resource = Resource.create(
attributes=(
{SERVICE_NAME: config.service_name} if config.service_name else None
)
)
if config.tracing is not None:
tracer_provider = TracerProvider(resource=resource)
if config.tracing.otlp_export:
tracer_provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
set_tracer_provider(tracer_provider)
try:
from opentelemetry.instrumentation.requests import (
RequestsInstrumentor,
)
RequestsInstrumentor().instrument()
except ImportError:
pass
try:
from opentelemetry.instrumentation.aiohttp_client import (
AioHttpClientInstrumentor,
)
AioHttpClientInstrumentor().instrument()
except ImportError:
pass
URLLibInstrumentor().instrument()
try:
from opentelemetry.instrumentation.httpx import (
HTTPXClientInstrumentor,
)
HTTPXClientInstrumentor().instrument()
except ImportError:
pass
if config.tracing.logging:
# Setting the root logger format in order to include
# tracing information: span_id, trace_id
LoggingInstrumentor().instrument(set_logging_format=True)
if config.logs is not None:
# Adding a handler to the root logger which exports the logs to OTLP
provider = LoggerProvider(resource=resource)
if config.logs.otlp_export:
provider.add_log_record_processor(
BatchLogRecordProcessor(OTLPLogExporter())
)
set_logger_provider(provider)
handler = LoggingHandler(level=config.logs.level)
logging.getLogger().addHandler(handler)
if config.metrics is not None:
metric_readers = []
if config.metrics.prometheus_export:
metric_readers.append(PrometheusMetricReader())
if config.metrics.otlp_export:
metric_readers.append(
PeriodicExportingMetricReader(OTLPMetricExporter())
)
set_meter_provider(
MeterProvider(resource=resource, metric_readers=metric_readers)
)
SystemMetricsInstrumentor().instrument()
if config.metrics.prometheus_export:
start_http_server(port=config.metrics.port)
if config.tracing is not None or config.metrics is not None:
# FastAPI instrumentor reports both metrics and traces
FastAPIInstrumentor.instrument_app(app)