diff --git a/litellm/integrations/langfuse/langfuse.py b/litellm/integrations/langfuse/langfuse.py index cdeff86b4bd..81855c76854 100644 --- a/litellm/integrations/langfuse/langfuse.py +++ b/litellm/integrations/langfuse/langfuse.py @@ -3,6 +3,7 @@ import os import traceback from datetime import datetime +from hashlib import sha256 from importlib.metadata import version as package_version from typing import ( TYPE_CHECKING, @@ -845,9 +846,16 @@ class LangFuseLogger: else self.Langfuse.create_trace_id(seed=trace_id) ) normalized_parent_id = parent_observation_id.lower().replace("-", "") if parent_observation_id else "" - return ( - {"trace_id": resolved_trace_id, "parent_span_id": normalized_parent_id} + resolved_parent_id = ( + normalized_parent_id if self._is_valid_langfuse_id(normalized_parent_id, 16) + else sha256(normalized_parent_id.encode("utf-8")).digest()[:8].hex() + if normalized_parent_id + else None + ) + return ( + {"trace_id": resolved_trace_id, "parent_span_id": resolved_parent_id} + if resolved_parent_id else {"trace_id": resolved_trace_id} ) diff --git a/tests/test_litellm/integrations/test_langfuse.py b/tests/test_litellm/integrations/test_langfuse.py index b3958496c96..4a96dfb4829 100644 --- a/tests/test_litellm/integrations/test_langfuse.py +++ b/tests/test_litellm/integrations/test_langfuse.py @@ -3,6 +3,7 @@ import os import sys import types import unittest +from hashlib import sha256 from typing import Optional from unittest.mock import MagicMock, patch @@ -235,6 +236,21 @@ class TestLangfuseUsageDetails(unittest.TestCase): } self.mock_langfuse_client.create_trace_id.assert_called_once_with(seed="external-trace-id") + parent_observation_id = "550E8400-E29B-41D4-A716-446655440000" + context = self.logger._create_langfuse_trace_context( + trace_id="a" * 32, + parent_observation_id=parent_observation_id, + ) + + assert context == { + "trace_id": "a" * 32, + "parent_span_id": sha256( + parent_observation_id.lower().replace("-", "").encode("utf-8") + ) + .digest()[:8] + .hex(), + } + def test_langfuse_usage_details_optional_fields(self): """Test that LangfuseUsageDetails fields are properly defined as Optional""" # Create an instance with None values for optional fields