From 60de8af1363be0eb54a53d095ceda8aca7be9eb5 Mon Sep 17 00:00:00 2001 From: Yucheng Zhu Date: Tue, 1 Sep 2026 12:51:16 -0700 Subject: [PATCH] fix(langfuse): seed hyphen-only trace ids --- litellm/integrations/langfuse/langfuse_sdk.py | 14 ++++++++------ .../integrations/langfuse/test_langfuse_sdk.py | 4 ++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/litellm/integrations/langfuse/langfuse_sdk.py b/litellm/integrations/langfuse/langfuse_sdk.py index 7cd1d288f4b..3cad3b14547 100644 --- a/litellm/integrations/langfuse/langfuse_sdk.py +++ b/litellm/integrations/langfuse/langfuse_sdk.py @@ -56,20 +56,22 @@ def to_unix_nanos(value: datetime | float | None) -> int | None: def resolve_trace_id(trace_id: object | None) -> str: """Map a caller's trace id onto the 32 lowercase hex characters v4 requires.""" - normalized: Final = "" if trace_id is None else str(trace_id).lower().replace("-", "") + serialized: Final = "" if trace_id is None else str(trace_id) + normalized: Final = serialized.lower().replace("-", "") if _TRACE_ID_PATTERN.fullmatch(normalized): return normalized - return Langfuse.create_trace_id(seed=str(trace_id)) if normalized else Langfuse.create_trace_id() + return Langfuse.create_trace_id(seed=serialized) if serialized else Langfuse.create_trace_id() def resolve_observation_id(observation_id: object | None) -> str | None: """Map a caller's parent observation id onto v4's 16 lowercase hex characters.""" - normalized: Final = "" if observation_id is None else str(observation_id).lower().replace("-", "") - if not normalized: - return None + serialized: Final = "" if observation_id is None else str(observation_id) + normalized: Final = serialized.lower().replace("-", "") if _OBSERVATION_ID_PATTERN.fullmatch(normalized): return normalized - return sha256(normalized.encode("utf-8")).digest()[:8].hex() + if not serialized: + return None + return sha256(serialized.encode("utf-8")).digest()[:8].hex() def open_trace_context( diff --git a/tests/test_litellm/integrations/langfuse/test_langfuse_sdk.py b/tests/test_litellm/integrations/langfuse/test_langfuse_sdk.py index 9cf2a6cb142..629240d83a1 100644 --- a/tests/test_litellm/integrations/langfuse/test_langfuse_sdk.py +++ b/tests/test_litellm/integrations/langfuse/test_langfuse_sdk.py @@ -267,6 +267,10 @@ def test_non_string_observation_id_is_normalized(supplied): assert resolved == resolve_observation_id(supplied) +def test_hyphen_only_trace_ids_are_deterministic(): + assert resolve_trace_id("---") == resolve_trace_id("---") + + def test_trace_id_with_trailing_newline_is_hashed(): supplied = "a" * 32 + "\n"