Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions langfuse/_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1548,6 +1548,7 @@ def update_current_span(
langfuse_client=self,
environment=self._environment,
release=self._release,
set_observation_type=False,
)

if name:
Expand Down Expand Up @@ -1604,6 +1605,7 @@ def set_current_trace_io(
langfuse_client=self,
environment=self._environment,
release=self._release,
set_observation_type=False,
)

span.set_trace_io(
Expand Down Expand Up @@ -1638,6 +1640,7 @@ def set_current_trace_as_public(self) -> None:
otel_span=current_otel_span,
langfuse_client=self,
environment=self._environment,
set_observation_type=False,
)

span.set_trace_as_public()
Expand Down
26 changes: 23 additions & 3 deletions langfuse/_client/span.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def __init__(
usage_details: Optional[Dict[str, int]] = None,
cost_details: Optional[Dict[str, float]] = None,
prompt: Optional[PromptClient] = None,
set_observation_type: bool = True,
):
"""Initialize a new Langfuse span wrapper.

Expand All @@ -120,11 +121,15 @@ def __init__(
usage_details: Token usage information (e.g., prompt_tokens, completion_tokens)
cost_details: Cost information for the model call
prompt: Associated prompt template from Langfuse prompt management
set_observation_type: Whether to write the Langfuse observation type to
the wrapped OpenTelemetry span
"""
self._otel_span = otel_span
self._otel_span.set_attribute(
LangfuseOtelSpanAttributes.OBSERVATION_TYPE, as_type
)
self._set_observation_type = set_observation_type
if self._set_observation_type:
self._otel_span.set_attribute(
LangfuseOtelSpanAttributes.OBSERVATION_TYPE, as_type
)
self._langfuse_client = langfuse_client
self._observation_type = as_type

Expand Down Expand Up @@ -727,6 +732,9 @@ def update(
),
)

if not self._set_observation_type:
attributes.pop(LangfuseOtelSpanAttributes.OBSERVATION_TYPE, None)

self._otel_span.set_attributes(attributes=attributes)
# Set OTEL span status if level is ERROR
self._set_otel_span_status_if_error(level=level, status_message=status_message)
Expand Down Expand Up @@ -1286,6 +1294,7 @@ def __init__(
version: Optional[str] = None,
level: Optional[SpanLevel] = None,
status_message: Optional[str] = None,
set_observation_type: bool = True,
):
"""Initialize a new LangfuseSpan.

Expand All @@ -1300,6 +1309,8 @@ def __init__(
version: Version identifier for the code or component
level: Importance level of the span (info, warning, error)
status_message: Optional status message for the span
set_observation_type: Whether to write the Langfuse observation type to
the wrapped OpenTelemetry span
"""
super().__init__(
otel_span=otel_span,
Expand All @@ -1313,6 +1324,7 @@ def __init__(
version=version,
level=level,
status_message=status_message,
set_observation_type=set_observation_type,
)


Expand Down Expand Up @@ -1343,6 +1355,7 @@ def __init__(
usage_details: Optional[Dict[str, int]] = None,
cost_details: Optional[Dict[str, float]] = None,
prompt: Optional[PromptClient] = None,
set_observation_type: bool = True,
):
"""Initialize a new LangfuseGeneration span.

Expand All @@ -1363,6 +1376,8 @@ def __init__(
usage_details: Token usage information (e.g., prompt_tokens, completion_tokens)
cost_details: Cost information for the model call
prompt: Associated prompt template from Langfuse prompt management
set_observation_type: Whether to write the Langfuse observation type to
the wrapped OpenTelemetry span
"""
super().__init__(
as_type="generation",
Expand All @@ -1382,6 +1397,7 @@ def __init__(
usage_details=usage_details,
cost_details=cost_details,
prompt=prompt,
set_observation_type=set_observation_type,
)


Expand All @@ -1401,6 +1417,7 @@ def __init__(
version: Optional[str] = None,
level: Optional[SpanLevel] = None,
status_message: Optional[str] = None,
set_observation_type: bool = True,
):
"""Initialize a new LangfuseEvent span.

Expand All @@ -1415,6 +1432,8 @@ def __init__(
version: Version identifier for the model or component
level: Importance level of the generation (info, warning, error)
status_message: Optional status message for the generation
set_observation_type: Whether to write the Langfuse observation type to
the wrapped OpenTelemetry span
"""
super().__init__(
otel_span=otel_span,
Expand All @@ -1428,6 +1447,7 @@ def __init__(
version=version,
level=level,
status_message=status_message,
set_observation_type=set_observation_type,
)

def update(
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/test_otel.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,19 @@ def test_update_current_span_name(self, langfuse_client, memory_exporter):
)
assert len(original_spans) == 0, "Expected no spans with original name"

def test_update_current_span_preserves_third_party_observation_type(
self, langfuse_client, tracer_provider
):
tracer = tracer_provider.get_tracer("openinference.instrumentation.agno")

with tracer.start_as_current_span("third-party-agent") as span:
span.set_attribute("openinference.span.kind", "AGENT")

langfuse_client.update_current_span(metadata={"user_id": "u1"})

assert LangfuseOtelSpanAttributes.OBSERVATION_TYPE not in span.attributes
assert span.attributes["langfuse.observation.metadata.user_id"] == "u1"

def test_span_attributes(self, langfuse_client, memory_exporter):
"""Test that span attributes are correctly set and updated."""
# Create a span with attributes
Expand Down