fix(langfuse_otel): prevent empty proxy request spans from being sent to Langfuse

fix(langfuse_otel): prevent empty proxy request spans from being sent to Langfuse
This commit is contained in:
mubashir1osmani
2026-02-14 14:22:32 -05:00
committed by GitHub
2 changed files with 45 additions and 0 deletions
@@ -1,6 +1,7 @@
import base64
import json # <--- NEW
import os
from datetime import datetime
from typing import TYPE_CHECKING, Any, Optional, Union
from litellm._logging import verbose_logger
@@ -392,6 +393,22 @@ class LangfuseOtelLogger(OpenTelemetry):
return dynamic_headers
def create_litellm_proxy_request_started_span(
self,
start_time: datetime,
headers: dict,
) -> Optional[Span]:
"""
Override to prevent creating empty proxy request spans.
Langfuse should only receive spans for actual LLM calls, not for
internal proxy operations (auth, postgres, proxy_pre_call, etc.).
By returning None, we prevent the parent span from being created,
which in turn prevents empty traces from being sent to Langfuse.
"""
return None
async def async_service_success_hook(self, *args, **kwargs):
"""
Langfuse should not receive service success logs.
+28
View File
@@ -1,6 +1,7 @@
import os
import sys
import unittest
from datetime import datetime
from unittest.mock import patch, AsyncMock, MagicMock
# Add the project root to sys.path
@@ -41,6 +42,33 @@ class TestServiceLoggerOTEL(unittest.IsolatedAsyncioTestCase):
"LangfuseOtelLogger.async_service_failure_hook",
)
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_tracing")
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_metrics")
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_logs")
async def test_langfuse_otel_does_not_create_proxy_request_span(
self, mock_logs, mock_metrics, mock_tracing
):
"""
Test that LangfuseOtelLogger returns None for create_litellm_proxy_request_started_span.
This prevents empty proxy request spans from being sent to Langfuse when
requests don't result in actual LLM calls (e.g., auth failures, health checks).
"""
logger = LangfuseOtelLogger()
# Verify the method is overridden
self.assertEqual(
logger.create_litellm_proxy_request_started_span.__qualname__,
"LangfuseOtelLogger.create_litellm_proxy_request_started_span",
)
# Verify it returns None
result = logger.create_litellm_proxy_request_started_span(
start_time=datetime.now(),
headers={"Authorization": "Bearer test"},
)
self.assertIsNone(result)
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_tracing")
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_metrics")
@patch("litellm.integrations.opentelemetry.OpenTelemetry._init_logs")