Skip to content

Commit c08055d

Browse files
committed
don't update events
1 parent 37c284b commit c08055d

2 files changed

Lines changed: 60 additions & 6 deletions

File tree

langfuse/_client/span.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,36 @@ def __init__(
15701570
status_message=status_message,
15711571
)
15721572

1573+
def update(
1574+
self,
1575+
*,
1576+
name: Optional[str] = None,
1577+
input: Optional[Any] = None,
1578+
output: Optional[Any] = None,
1579+
metadata: Optional[Any] = None,
1580+
version: Optional[str] = None,
1581+
level: Optional[SpanLevel] = None,
1582+
status_message: Optional[str] = None,
1583+
completion_start_time: Optional[datetime] = None,
1584+
model: Optional[str] = None,
1585+
model_parameters: Optional[Dict[str, MapValue]] = None,
1586+
usage_details: Optional[Dict[str, int]] = None,
1587+
cost_details: Optional[Dict[str, float]] = None,
1588+
prompt: Optional[PromptClient] = None,
1589+
**kwargs: Any,
1590+
) -> "LangfuseObservationWrapper":
1591+
"""Update is not allowed for LangfuseEvent because events cannot be updated.
1592+
1593+
This method logs a warning and returns self without making changes.
1594+
1595+
Returns:
1596+
self: Returns the unchanged LangfuseEvent instance
1597+
"""
1598+
langfuse_logger.warning(
1599+
"Attempted to update LangfuseEvent observation. Events cannot be updated after creation."
1600+
)
1601+
return self
1602+
15731603

15741604
class LangfuseAgent(LangfuseObservationWrapper):
15751605
"""Specialized span for agent observations in agentic workflows."""

tests/test_otel.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -628,12 +628,6 @@ def test_start_as_current_observation_types(self, langfuse_client, memory_export
628628
LangfuseOtelSpanAttributes.OBSERVATION_TYPE
629629
)
630630

631-
# Debug: print all attributes for this span
632-
print(
633-
f"Span {expected_name} attributes: {list(span_data['attributes'].keys())}"
634-
)
635-
print(f"Expected: {expected_otel_type}, Actual: {actual_type}")
636-
637631
assert (
638632
actual_type == expected_otel_type
639633
), f"Expected observation type {expected_otel_type}, got {actual_type}"
@@ -3036,3 +3030,33 @@ def test_different_seeds_produce_different_ids(self, langfuse_client):
30363030

30373031
# All observation IDs should be unique
30383032
assert len(set(observation_ids)) == len(seeds)
3033+
3034+
def test_langfuse_event_update_immutability(self, langfuse_client, memory_exporter, caplog):
3035+
"""Test that LangfuseEvent.update() logs a warning and does nothing."""
3036+
import logging
3037+
3038+
parent_span = langfuse_client.start_span(name="parent-span")
3039+
3040+
event = parent_span.start_observation(
3041+
name="test-event",
3042+
as_type="event",
3043+
input={"original": "input"},
3044+
)
3045+
3046+
# Try to update the event and capture warning logs
3047+
with caplog.at_level(logging.WARNING, logger='langfuse._client.span'):
3048+
result = event.update(
3049+
name="updated_name",
3050+
input={"updated": "input"},
3051+
output={"updated": "output"},
3052+
metadata={"updated": "metadata"}
3053+
)
3054+
3055+
# Verify warning was logged
3056+
assert "Attempted to update LangfuseEvent observation" in caplog.text
3057+
assert "Events are immutable and cannot be updated after creation" in caplog.text
3058+
3059+
# Verify the method returned self unchanged
3060+
assert result is event
3061+
3062+
parent_span.end()

0 commit comments

Comments
 (0)