chore(otel/v2): drop bundled langtrace v1 endpoint fix

The langtrace v1 exporter host/header fix (https://app.langtrace.ai/api/trace +
x-api-key) and the shared endpoint-normalizer /api/trace carve-out are unrelated
to admin-owned OTEL v2 destinations; they change behavior on the legacy langtrace
v1 path. Moved to its own PR (#34865) so this PR only touches OTEL v2. The v2
langtrace preset and its normalizer in otel/plumbing/providers.py are unaffected.
This commit is contained in:
Yucheng Zhu 2026-07-27 17:37:34 -07:00
parent 1042b56d2f
commit b0484bae70
3 changed files with 3 additions and 58 deletions

View file

@ -3093,10 +3093,6 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger):
if signal_type == "traces" and "/v2/trace/otlp" in endpoint:
return endpoint
# Langtrace ingests traces at /api/trace (a complete path, not an OTLP base). Do not rewrite.
if signal_type == "traces" and endpoint.endswith("/api/trace"):
return endpoint
# Check if endpoint already ends with the correct signal path
target_path = f"/v1/{signal_type}"
if endpoint.endswith(target_path):

View file

@ -3992,9 +3992,9 @@ def _init_custom_logger_compatible_class(
otel_config = OpenTelemetryConfig(
exporter="otlp_http",
endpoint="https://app.langtrace.ai/api/trace",
endpoint="https://langtrace.ai/api/trace",
)
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = f"x-api-key={os.getenv('LANGTRACE_API_KEY')}"
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = f"api_key={os.getenv('LANGTRACE_API_KEY')}"
for callback in _in_memory_loggers:
if isinstance(callback, OpenTelemetry) and callback.callback_name == "langtrace":
return callback # type: ignore

View file

@ -1928,21 +1928,12 @@ class TestOpenTelemetryEndpointNormalization(unittest.TestCase):
"https://example.com/prefix/v2/trace/otlp",
"https://example.com/prefix/v2/trace/otlp",
),
(
"https://app.langtrace.ai/api/trace",
"https://app.langtrace.ai/api/trace",
),
(
"https://app.langtrace.ai/api/trace/",
"https://app.langtrace.ai/api/trace",
),
]
)
def test_normalize_traces_nonstandard_otlp_ingest_urls_unchanged(
self, input_url: str, expected: str
) -> None:
"""Vendor full-path ingest URLs (Splunk /v2/trace/otlp, Langtrace /api/trace)
must not get /v1/traces appended that 404s."""
"""Splunk-style /v2/trace/otlp endpoints must not get /v1/traces appended."""
otel = OpenTelemetry()
self.assertEqual(
otel._normalize_otel_endpoint(input_url, "traces"),
@ -5861,45 +5852,3 @@ class TestOpenTelemetryMetricAttributeFiltering(unittest.TestCase):
exporter="console", attributes=attributes
)
)
class LangtraceV1ConfigTest(unittest.TestCase):
def test_langtrace_uses_live_host_and_x_api_key_header(self):
"""Regression: litellm hardcoded the stale https://langtrace.ai/api/trace (now 404)
with header ``api_key=``. The live ingest is https://app.langtrace.ai/api/trace and
the auth header is ``x-api-key``. Pins both so the stale values can't return."""
import litellm
import litellm.litellm_core_utils.litellm_logging as ll
from litellm.integrations.opentelemetry import OpenTelemetry
from litellm.integrations.otel.model.config import is_otel_v2_enabled
saved = {
k: os.environ.get(k)
for k in (
"LANGTRACE_API_KEY",
"LITELLM_OTEL_V2",
"OTEL_EXPORTER_OTLP_TRACES_HEADERS",
)
}
try:
ll._in_memory_loggers.clear() # force a fresh build, not a cached logger
os.environ["LANGTRACE_API_KEY"] = "lt-test"
os.environ.pop("LITELLM_OTEL_V2", None)
is_otel_v2_enabled.cache_clear()
litellm.credential_list = []
logger = ll._init_custom_logger_compatible_class("langtrace", None, None)
assert isinstance(logger, OpenTelemetry)
self.assertEqual(
logger.config.endpoint, "https://app.langtrace.ai/api/trace"
)
self.assertEqual(
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"], "x-api-key=lt-test"
)
finally:
is_otel_v2_enabled.cache_clear()
ll._in_memory_loggers.clear()
for key, value in saved.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value