fix(langfuse_otel): clean up review feedback

This commit is contained in:
Asaf Vertman 2026-04-16 11:55:56 +03:00
parent cf5a22a9d5
commit 316ab4938b
3 changed files with 44 additions and 18 deletions

View file

@ -8,7 +8,6 @@ from litellm._logging import verbose_logger
from litellm.integrations.arize import _utils
from litellm.integrations.langfuse.langfuse_otel_attributes import (
LangfuseLLMObsOTELAttributes,
get_langfuse_observation_input_by_type,
)
from litellm.integrations.opentelemetry import OpenTelemetry, OpenTelemetryConfig
from litellm.types.integrations.langfuse_otel import (
@ -244,14 +243,6 @@ class LangfuseOtelLogger(OpenTelemetry):
metadata = LangfuseOtelLogger._extract_langfuse_metadata(kwargs)
LangfuseOtelLogger._set_metadata_attributes(span=span, metadata=metadata)
input_payload = get_langfuse_observation_input_by_type(kwargs)
if input_payload is not None:
safe_set_attribute(
span,
LangfuseSpanAttributes.OBSERVATION_INPUT.value,
safe_dumps(input_payload),
)
LangfuseOtelLogger._set_observation_output(span=span, response_obj=response_obj)
@staticmethod

View file

@ -128,7 +128,9 @@ def get_langfuse_observation_input_by_type(
return prompt
prompt: dict[str, Any] = {}
if "messages" in kwargs:
# Preserve explicit empty chat message lists without serializing `null`
# when callers pass `messages=None`.
if messages is not None:
prompt["messages"] = messages
for key in ("functions", "tools"):
value = optional_params.get(key)

View file

@ -257,21 +257,14 @@ class TestLangfuseOtelIntegration:
],
)
kwargs = {
"messages": [{"role": "user", "content": "What's the weather in Tokyo?"}],
}
with patch(
"litellm.integrations.arize._utils.safe_set_attribute"
) as mock_safe_set_attribute:
LangfuseOtelLogger._set_langfuse_specific_attributes(
MagicMock(), kwargs, response_obj
MagicMock(), {}, response_obj
)
expect_output = {
LangfuseSpanAttributes.OBSERVATION_INPUT.value: [
{"role": "user", "content": "What's the weather in Tokyo?"}
],
LangfuseSpanAttributes.OBSERVATION_OUTPUT.value: {
"role": "assistant",
"content": "The weather in Tokyo is sunny.",
@ -572,6 +565,46 @@ class TestLangfuseOtelResponsesAPI:
in actual_attributes["langfuse.observation.input"]
)
def test_langfuse_observation_input_skips_null_messages(self):
"""Explicit null messages should not serialize as `{\"messages\": null}`."""
kwargs = {
"messages": None,
"optional_params": {
"tools": [{"type": "function", "name": "list_applications"}]
},
}
from litellm.integrations.langfuse.langfuse_otel_attributes import (
get_langfuse_observation_input_by_type,
)
assert get_langfuse_observation_input_by_type(kwargs) == {
"tools": [{"type": "function", "name": "list_applications"}]
}
def test_langfuse_specific_attributes_do_not_rewrite_observation_input(self):
"""Observation input should be owned by set_messages, not rewritten later."""
from litellm.types.integrations.langfuse_otel import LangfuseSpanAttributes
kwargs = {
"input": [{"role": "user", "content": "hello"}],
"optional_params": {"instructions": "Reply briefly."},
"litellm_params": {"metadata": {"generation_name": "gen-name"}},
}
with patch(
"litellm.integrations.arize._utils.safe_set_attribute"
) as mock_safe_set_attribute:
LangfuseOtelLogger._set_langfuse_specific_attributes(
MagicMock(), kwargs, None
)
actual_keys = [
call.args[1] for call in mock_safe_set_attribute.call_args_list
]
assert LangfuseSpanAttributes.GENERATION_NAME.value in actual_keys
assert LangfuseSpanAttributes.OBSERVATION_INPUT.value not in actual_keys
def test_responses_api_metadata_extraction(self):
"""Test that metadata is correctly extracted from ResponsesAPI kwargs."""
# Clean up any existing module mocks