dropshop / src /utils /telemetry.py
github-actions[bot]
Automated deployment from GitHub Actions: a9d5a91de63ad7224bafe6039fb2b7479388fbf4
0a8c81b
Raw History Blame Contribute Delete
3.29 kB
import os
import logging
from opentelemetry import trace, metrics
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
def parse_headers(header_str: str) -> dict:
"""Parse comma-separated headers into a dictionary, e.g. Authorization=Basic XYZ"""
if not header_str:
return {}
headers = {}
for pair in header_str.split(','):
if '=' in pair:
key, val = pair.split('=', 1)
headers[key.strip()] = val.strip()
return headers
def setup_telemetry():
"""Initialize OpenTelemetry Tracing, Metrics, and Logging"""
service_name = os.getenv("OTEL_SERVICE_NAME", "vlta-dropshopping-engine")
endpoint = os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
header_str = os.getenv("OTEL_EXPORTER_OTLP_HEADERS", "")
headers = parse_headers(header_str)
# Common Resource attributes
resource = Resource.create({"service.name": service_name})
if not endpoint:
# If no endpoint configured, just use basic stdout logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
return
# 1. Tracing Setup
trace_exporter = OTLPSpanExporter(
endpoint=f"{endpoint}/v1/traces",
headers=headers
)
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(BatchSpanProcessor(trace_exporter))
trace.set_tracer_provider(tracer_provider)
# 2. Metrics Setup
metric_exporter = OTLPMetricExporter(
endpoint=f"{endpoint}/v1/metrics",
headers=headers
)
metric_reader = PeriodicExportingMetricReader(metric_exporter)
meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(meter_provider)
# 3. Logging Setup (Injects Trace_ID into logs automatically)
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s] - %(message)s")
LoggingInstrumentor().instrument(set_logging_format=True)
# 4. Global Auto-Instrumentations (Catches outgoing API calls like LLMs & DB Queries)
HTTPXClientInstrumentor().instrument()
RequestsInstrumentor().instrument()
try:
# Automatically tracks any SQLAlchemy Engines created
SQLAlchemyInstrumentor().instrument()
except Exception as e:
logging.getLogger(__name__).warning(f"Could not instrument SQLAlchemy: {e}")
logging.getLogger(__name__).info("OpenTelemetry initialization complete. Connected to OTLP Endpoint.")