mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-10 03:28:53 +00:00
fix(langfuse_otel): keep trace tags off joined traces entirely
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
8f0788486f
commit
ee059cb13c
2 changed files with 15 additions and 18 deletions
|
|
@ -154,9 +154,7 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
return _extract_output_items(response_obj) or _extract_choices_output(response_obj)
|
||||
|
||||
@staticmethod
|
||||
def _trace_tags(
|
||||
kwargs: Mapping[str, object], metadata: Mapping[str, object], derive_defaults: bool = True
|
||||
) -> tuple[str, ...]:
|
||||
def _trace_tags(kwargs: Mapping[str, object], metadata: Mapping[str, object]) -> tuple[str, ...]:
|
||||
"""Order-preserving dedupe of caller tags, request tags and langfuse_default_tags expansions."""
|
||||
import litellm
|
||||
|
||||
|
|
@ -184,16 +182,15 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
|
||||
expanded: Final = tuple(_default_tag(key) for key in default_tags) if isinstance(default_tags, list) else ()
|
||||
candidates: Final = (
|
||||
(caller_tags,)
|
||||
if isinstance(caller_tags, str)
|
||||
else tuple(tag for tag in caller_tags if isinstance(tag, str))
|
||||
if isinstance(caller_tags, list)
|
||||
else ()
|
||||
) + (
|
||||
(tuple(tag for tag in request_tags if isinstance(tag, str)) if isinstance(request_tags, list) else ())
|
||||
(
|
||||
(caller_tags,)
|
||||
if isinstance(caller_tags, str)
|
||||
else tuple(tag for tag in caller_tags if isinstance(tag, str))
|
||||
if isinstance(caller_tags, list)
|
||||
else ()
|
||||
)
|
||||
+ (tuple(tag for tag in request_tags if isinstance(tag, str)) if isinstance(request_tags, list) else ())
|
||||
+ tuple(tag for tag in expanded if tag is not None)
|
||||
if derive_defaults
|
||||
else ()
|
||||
)
|
||||
return tuple(dict.fromkeys(candidates))
|
||||
|
||||
|
|
@ -232,9 +229,10 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
f"litellm-{kwargs.get('call_type') or 'completion'}",
|
||||
)
|
||||
|
||||
tags: Final = LangfuseOtelLogger._trace_tags(kwargs, metadata, derive_defaults=not joins_existing_trace)
|
||||
if tags:
|
||||
safe_set_attribute(span, LangfuseSpanAttributes.TAGS.value, json.dumps(list(tags)))
|
||||
if not joins_existing_trace:
|
||||
tags: Final = LangfuseOtelLogger._trace_tags(kwargs, metadata)
|
||||
if tags:
|
||||
safe_set_attribute(span, LangfuseSpanAttributes.TAGS.value, json.dumps(list(tags)))
|
||||
|
||||
input_json: Final = safe_dumps(kwargs.get("messages")) if kwargs.get("messages") else None
|
||||
if input_json is not None:
|
||||
|
|
|
|||
|
|
@ -219,7 +219,6 @@ class TestLangfuseOtelIntegration:
|
|||
LangfuseSpanAttributes.TRACE_USER_ID.value: "user-123",
|
||||
LangfuseSpanAttributes.SESSION_ID.value: "sess-456",
|
||||
# Lists / dicts should be JSON strings
|
||||
LangfuseSpanAttributes.TAGS.value: json.dumps(["tagA", "tagB"]),
|
||||
LangfuseSpanAttributes.TRACE_NAME.value: "trace-name",
|
||||
LangfuseSpanAttributes.TRACE_ID.value: "traceid", # stripped dashes
|
||||
LangfuseSpanAttributes.TRACE_METADATA.value: json.dumps({"k": "v"}),
|
||||
|
|
@ -1033,7 +1032,7 @@ class TestDerivedTraceFields:
|
|||
"messages": [{"role": "user", "content": "hi"}],
|
||||
"cache_hit": True,
|
||||
"litellm_params": {
|
||||
"metadata": {"existing_trace_id": "abc123", "tags": ["mine"]},
|
||||
"metadata": {"existing_trace_id": "abc123", "tags": ["experiment"]},
|
||||
},
|
||||
"standard_logging_object": {"request_tags": ["injected"]},
|
||||
},
|
||||
|
|
@ -1043,9 +1042,9 @@ class TestDerivedTraceFields:
|
|||
assert attributes["langfuse.trace.existing_id"] == "abc123"
|
||||
assert "langfuse.trace.input" not in attributes
|
||||
assert "langfuse.trace.output" not in attributes
|
||||
assert "langfuse.trace.tags" not in attributes
|
||||
assert "langfuse.observation.input" in attributes
|
||||
assert "langfuse.observation.output" in attributes
|
||||
assert json.loads(attributes["langfuse.trace.tags"]) == ["mine"]
|
||||
|
||||
def test_responses_api_output_mirrors_observation_output_items(self):
|
||||
from openai.types.responses import ResponseFunctionToolCall
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue