mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-08 02:24:54 +00:00
fix(otel): auto-infer otlp_http exporter when endpoint is configured (#20438)
When OpenTelemetry is configured via the UI, only OTEL_ENDPOINT and OTEL_HEADERS are set, but OTEL_EXPORTER is not specified. This caused the exporter to default to "console", meaning traces were printed to stdout instead of being sent to the configured endpoint. This fix adds logic in OpenTelemetryConfig.__post_init__ to automatically infer "otlp_http" as the exporter when an endpoint is specified but the exporter is still the default "console". Fixes issue reported by Elastic team where traces weren't being sent to their OTEL endpoint when configured through the LiteLLM UI.
This commit is contained in:
@@ -72,6 +72,13 @@ class OpenTelemetryConfig:
|
||||
model_id: Optional[str] = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
# If endpoint is specified but exporter is still the default "console",
|
||||
# automatically infer "otlp_http" to send traces to the endpoint.
|
||||
# This fixes an issue where UI-configured OTEL settings would default
|
||||
# to console output instead of sending traces to the configured endpoint.
|
||||
if self.endpoint and isinstance(self.exporter, str) and self.exporter == "console":
|
||||
self.exporter = "otlp_http"
|
||||
|
||||
if not self.service_name:
|
||||
self.service_name = os.getenv("OTEL_SERVICE_NAME", "litellm")
|
||||
if not self.deployment_environment:
|
||||
|
||||
@@ -274,6 +274,26 @@ class TestOpenTelemetry(unittest.TestCase):
|
||||
self.assertEqual(config.deployment_environment, "production")
|
||||
self.assertEqual(config.model_id, "custom-service")
|
||||
|
||||
@patch.dict(os.environ, {}, clear=True)
|
||||
def test_open_telemetry_config_auto_infer_otlp_http_when_endpoint_set(self):
|
||||
"""When endpoint is set but exporter is default 'console', auto-infer 'otlp_http'.
|
||||
|
||||
This fixes an issue where UI-configured OTEL settings would default to console
|
||||
output instead of sending traces to the configured endpoint.
|
||||
See: https://github.com/BerriAI/litellm/issues/XXXX
|
||||
"""
|
||||
# When endpoint is specified without explicit exporter, should auto-infer otlp_http
|
||||
config = OpenTelemetryConfig(endpoint="https://otel-collector.example.com:443")
|
||||
self.assertEqual(config.exporter, "otlp_http")
|
||||
|
||||
# When exporter is explicitly set to something other than console, should not override
|
||||
config_grpc = OpenTelemetryConfig(exporter="grpc", endpoint="https://otel-collector.example.com:443")
|
||||
self.assertEqual(config_grpc.exporter, "grpc")
|
||||
|
||||
# When no endpoint is set, should keep console as default
|
||||
config_no_endpoint = OpenTelemetryConfig()
|
||||
self.assertEqual(config_no_endpoint.exporter, "console")
|
||||
|
||||
def wait_for_spans(self, exporter: InMemorySpanExporter, prefix: str):
|
||||
"""Poll until we see at least one span with an attribute key starting with `prefix`."""
|
||||
deadline = time.time() + self.POLL_TIMEOUT
|
||||
|
||||
Reference in New Issue
Block a user