Skip to content

Commit b669e4d

Browse files
committed
push
1 parent 24444ff commit b669e4d

File tree

8 files changed

+590
-713
lines changed

8 files changed

+590
-713
lines changed

langfuse/_client/attributes.py

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import json
1414
from datetime import datetime
15-
from typing import Any, Dict, List, Literal, Optional, Union
15+
from typing import Any, Dict, Literal, Optional, Union
1616

1717
from langfuse._client.constants import (
1818
ObservationTypeGenerationLike,
@@ -74,28 +74,14 @@ class LangfuseOtelSpanAttributes:
7474

7575
def create_trace_attributes(
7676
*,
77-
name: Optional[str] = None,
78-
user_id: Optional[str] = None,
79-
session_id: Optional[str] = None,
80-
version: Optional[str] = None,
81-
release: Optional[str] = None,
8277
input: Optional[Any] = None,
8378
output: Optional[Any] = None,
84-
metadata: Optional[Any] = None,
85-
tags: Optional[List[str]] = None,
8679
public: Optional[bool] = None,
8780
) -> dict:
8881
attributes = {
89-
LangfuseOtelSpanAttributes.TRACE_NAME: name,
90-
LangfuseOtelSpanAttributes.TRACE_USER_ID: user_id,
91-
LangfuseOtelSpanAttributes.TRACE_SESSION_ID: session_id,
92-
LangfuseOtelSpanAttributes.VERSION: version,
93-
LangfuseOtelSpanAttributes.RELEASE: release,
9482
LangfuseOtelSpanAttributes.TRACE_INPUT: _serialize(input),
9583
LangfuseOtelSpanAttributes.TRACE_OUTPUT: _serialize(output),
96-
LangfuseOtelSpanAttributes.TRACE_TAGS: tags,
9784
LangfuseOtelSpanAttributes.TRACE_PUBLIC: public,
98-
**_flatten_and_serialize_metadata(metadata, "trace"),
9985
}
10086

10187
return {k: v for k, v in attributes.items() if v is not None}

langfuse/_client/client.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
_agnosticcontextmanager,
3636
)
3737
from packaging.version import Version
38+
from typing_extensions import deprecated
3839

3940
from langfuse._client.attributes import LangfuseOtelSpanAttributes, _serialize
4041
from langfuse._client.constants import (
@@ -1633,6 +1634,89 @@ def update_current_span(
16331634
status_message=status_message,
16341635
)
16351636

1637+
@deprecated(
1638+
"Trace-level input/output is deprecated. "
1639+
"For trace attributes (user_id, session_id, tags, etc.), use propagate_attributes() instead. "
1640+
"This method will be removed in a future major version."
1641+
)
1642+
def set_current_trace_io(
1643+
self,
1644+
*,
1645+
input: Optional[Any] = None,
1646+
output: Optional[Any] = None,
1647+
) -> None:
1648+
"""Set trace-level input and output for the current span's trace.
1649+
1650+
.. deprecated::
1651+
This is a legacy method for backward compatibility with Langfuse platform
1652+
features that still rely on trace-level input/output (e.g., legacy LLM-as-a-judge
1653+
evaluators). It will be removed in a future major version.
1654+
1655+
For setting other trace attributes (user_id, session_id, metadata, tags, version),
1656+
use :meth:`propagate_attributes` instead.
1657+
1658+
Args:
1659+
input: Input data to associate with the trace.
1660+
output: Output data to associate with the trace.
1661+
"""
1662+
if not self._tracing_enabled:
1663+
langfuse_logger.debug(
1664+
"Operation skipped: set_current_trace_io - Tracing is disabled or client is in no-op mode."
1665+
)
1666+
return
1667+
1668+
current_otel_span = self._get_current_otel_span()
1669+
1670+
if current_otel_span is not None and current_otel_span.is_recording():
1671+
existing_observation_type = current_otel_span.attributes.get( # type: ignore[attr-defined]
1672+
LangfuseOtelSpanAttributes.OBSERVATION_TYPE, "span"
1673+
)
1674+
# We need to preserve the class to keep the correct observation type
1675+
span_class = self._get_span_class(existing_observation_type)
1676+
span = span_class(
1677+
otel_span=current_otel_span,
1678+
langfuse_client=self,
1679+
environment=self._environment,
1680+
)
1681+
1682+
span.set_trace_io(
1683+
input=input,
1684+
output=output,
1685+
)
1686+
1687+
def publish_current_trace(self) -> None:
1688+
"""Make the current trace publicly accessible via its URL.
1689+
1690+
When a trace is published, anyone with the trace link can view the full trace
1691+
without needing to be logged in to Langfuse. This action cannot be undone
1692+
programmatically - once published, the entire trace becomes public.
1693+
1694+
This is a convenience method that publishes the trace from the currently
1695+
active span context. Use this when you want to make a trace public from
1696+
within a traced function without needing direct access to the span object.
1697+
"""
1698+
if not self._tracing_enabled:
1699+
langfuse_logger.debug(
1700+
"Operation skipped: publish_current_trace - Tracing is disabled or client is in no-op mode."
1701+
)
1702+
return
1703+
1704+
current_otel_span = self._get_current_otel_span()
1705+
1706+
if current_otel_span is not None and current_otel_span.is_recording():
1707+
existing_observation_type = current_otel_span.attributes.get( # type: ignore[attr-defined]
1708+
LangfuseOtelSpanAttributes.OBSERVATION_TYPE, "span"
1709+
)
1710+
# We need to preserve the class to keep the correct observation type
1711+
span_class = self._get_span_class(existing_observation_type)
1712+
span = span_class(
1713+
otel_span=current_otel_span,
1714+
langfuse_client=self,
1715+
environment=self._environment,
1716+
)
1717+
1718+
span.publish_trace()
1719+
16361720
def create_event(
16371721
self,
16381722
*,

langfuse/_client/span.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@
3737
if TYPE_CHECKING:
3838
from langfuse._client.client import Langfuse
3939

40+
from typing_extensions import deprecated
41+
4042
from langfuse._client.attributes import (
4143
LangfuseOtelSpanAttributes,
4244
create_generation_attributes,
4345
create_span_attributes,
46+
create_trace_attributes,
4447
)
4548
from langfuse._client.constants import (
4649
ObservationTypeGenerationLike,
@@ -207,6 +210,73 @@ def end(self, *, end_time: Optional[int] = None) -> "LangfuseObservationWrapper"
207210

208211
return self
209212

213+
@deprecated(
214+
"Trace-level input/output is deprecated. "
215+
"For trace attributes (user_id, session_id, tags, etc.), use propagate_attributes() instead. "
216+
"This method will be removed in a future major version."
217+
)
218+
def set_trace_io(
219+
self,
220+
*,
221+
input: Optional[Any] = None,
222+
output: Optional[Any] = None,
223+
) -> "LangfuseObservationWrapper":
224+
"""Set trace-level input and output for the trace this span belongs to.
225+
226+
.. deprecated::
227+
This is a legacy method for backward compatibility with Langfuse platform
228+
features that still rely on trace-level input/output (e.g., legacy LLM-as-a-judge
229+
evaluators). It will be removed in a future major version.
230+
231+
For setting other trace attributes (user_id, session_id, metadata, tags, version),
232+
use :meth:`Langfuse.propagate_attributes` instead.
233+
234+
Args:
235+
input: Input data to associate with the trace.
236+
output: Output data to associate with the trace.
237+
238+
Returns:
239+
The span instance for method chaining.
240+
"""
241+
if not self._otel_span.is_recording():
242+
return self
243+
244+
media_processed_input = self._process_media_and_apply_mask(
245+
data=input, field="input", span=self._otel_span
246+
)
247+
media_processed_output = self._process_media_and_apply_mask(
248+
data=output, field="output", span=self._otel_span
249+
)
250+
251+
attributes = create_trace_attributes(
252+
input=media_processed_input,
253+
output=media_processed_output,
254+
)
255+
256+
self._otel_span.set_attributes(attributes)
257+
258+
return self
259+
260+
def publish_trace(self) -> "LangfuseObservationWrapper":
261+
"""Make this trace publicly accessible via its URL.
262+
263+
When a trace is published, anyone with the trace link can view the full trace
264+
without needing to be logged in to Langfuse. This action cannot be undone
265+
programmatically - once any span in a trace is published, the entire trace
266+
becomes public.
267+
268+
Returns:
269+
The span instance for method chaining.
270+
"""
271+
if not self._otel_span.is_recording():
272+
return self
273+
274+
attributes = create_trace_attributes(public=True)
275+
276+
self._otel_span.set_attributes(attributes)
277+
278+
return self
279+
210280
@overload
211281
def score(
212282
self,

tests/test_batch_evaluation.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import pytest
1212

13-
from langfuse import get_client
13+
from langfuse import get_client, propagate_attributes
1414
from langfuse.batch_evaluation import (
1515
BatchEvaluationResult,
1616
BatchEvaluationResumeToken,
@@ -100,11 +100,11 @@ def test_batch_evaluation_with_filter(langfuse_client):
100100
with langfuse_client.start_as_current_span(
101101
name=f"filtered-trace-{create_uuid()}"
102102
) as span:
103-
span.update_trace(
104-
input="Filtered test",
105-
output="Filtered output",
106-
tags=[unique_tag],
107-
)
103+
with propagate_attributes(tags=[unique_tag]):
104+
span.set_trace_io(
105+
input="Filtered test",
106+
output="Filtered output",
107+
)
108108

109109
langfuse_client.flush()
110110
time.sleep(3)
@@ -728,11 +728,11 @@ def test_pagination_with_max_items(langfuse_client):
728728
with langfuse_client.start_as_current_span(
729729
name=f"pagination-test-{create_uuid()}"
730730
) as span:
731-
span.update_trace(
732-
input=f"Input {i}",
733-
output=f"Output {i}",
734-
tags=["pagination_test"],
735-
)
731+
with propagate_attributes(tags=["pagination_test"]):
732+
span.set_trace_io(
733+
input=f"Input {i}",
734+
output=f"Output {i}",
735+
)
736736

737737
langfuse_client.flush()
738738
time.sleep(3)
@@ -758,11 +758,11 @@ def test_has_more_items_flag(langfuse_client):
758758
batch_tag = f"batch-test-{create_uuid()}"
759759
for i in range(15):
760760
with langfuse_client.start_as_current_span(name=f"more-items-test-{i}") as span:
761-
span.update_trace(
762-
input=f"Input {i}",
763-
output=f"Output {i}",
764-
tags=[batch_tag],
765-
)
761+
with propagate_attributes(tags=[batch_tag]):
762+
span.set_trace_io(
763+
input=f"Input {i}",
764+
output=f"Output {i}",
765+
)
766766

767767
langfuse_client.flush()
768768
time.sleep(3)

0 commit comments

Comments
 (0)