mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
Three defects kept LiteLLM's OTel metrics from reaching an OTLP backend. OTEL_EXPORTER_OTLP_HEADERS is W3C Baggage encoded per the OTLP spec, so its values are percent-encoded. litellm split the string on "," and "=" and passed the raw value straight to the exporter, so a vendor that documents "Authorization=Basic%20<token>" got a literal "%20" on the wire and the backend rejected the credential. Grafana Cloud documents exactly that shape, which made its OTLP gateway unreachable. Header parsing now delegates to the OTel SDK's own W3C Baggage parser in liberal mode, so percent-encoded values decode and values that were never encoded keep working. It moves from model/utils.py to plumbing/providers.py because model/ is deliberately free of opentelemetry imports; providers.parse_headers was already the entry point every caller used. The OTLP metric exporters then overrode histogram temporality to delta. Prometheus and Mimir, which back Grafana Cloud's OTLP gateway, reject delta histograms outright: the gateway answers 400 "invalid temporality and type combination" and drops the entire batch, so every GenAI metric was silently lost while traces kept flowing. Backends that prefer delta still accept cumulative, so the SDK default is the compatible choice in both directions, and the enterprise billing exporter already relies on it. Three GenAI instruments also carried names no convention or backend defines, so nothing downstream could chart them. Time to first token and time per output token take their semconv names, gen_ai.server.time_to_first_token and gen_ai.server.time_per_output_token; the gen_ai.client.response.* spellings litellm used are not conventions at all. Cost has no semconv instrument, so it takes gen_ai.usage.cost, the name backends already query for spend. All three are listed verbatim in Grafana Cloud's AI Observability integration reference, so its prebuilt panels find them. Both engines now read the names from the shared Metric constants rather than repeating string literals, so v1 and v2 cannot drift. The renames are breaking for anyone charting the former names; the docs and the release changelog carry the migration note. |
||
|---|---|---|
| .. | ||
| test_otel_v2_baggage.py | ||
| test_otel_v2_components.py | ||
| test_otel_v2_config_baggage_parenting_guardrails.py | ||
| test_otel_v2_dynamic.py | ||
| test_otel_v2_emitter.py | ||
| test_otel_v2_logger.py | ||
| test_otel_v2_metrics.py | ||
| test_otel_v2_mount.py | ||
| test_otel_v2_multibackend.py | ||
| test_otel_v2_presets.py | ||
| test_otel_v2_sources_of_truth.py | ||
| test_otel_v2_vendor_mappers.py | ||
| test_runtime.py | ||