Skip to content

Commit 81bd053

Browse files
authored
feat(client): allow updating span/generation name (#1255)
1 parent 60947d5 commit 81bd053

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

langfuse/_client/client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,7 @@ def _get_current_otel_span(self) -> Optional[otel_trace_api.Span]:
773773
def update_current_generation(
774774
self,
775775
*,
776+
name: Optional[str] = None,
776777
input: Optional[Any] = None,
777778
output: Optional[Any] = None,
778779
metadata: Optional[Any] = None,
@@ -793,6 +794,7 @@ def update_current_generation(
793794
details that become available during or after model generation.
794795
795796
Args:
797+
name: The generation name
796798
input: Updated input data for the model
797799
output: Output from the model (e.g., completions)
798800
metadata: Additional metadata to associate with the generation
@@ -835,6 +837,9 @@ def update_current_generation(
835837
otel_span=current_otel_span, langfuse_client=self
836838
)
837839

840+
if name:
841+
current_otel_span.update_name(name)
842+
838843
generation.update(
839844
input=input,
840845
output=output,
@@ -853,6 +858,7 @@ def update_current_generation(
853858
def update_current_span(
854859
self,
855860
*,
861+
name: Optional[str] = None,
856862
input: Optional[Any] = None,
857863
output: Optional[Any] = None,
858864
metadata: Optional[Any] = None,
@@ -867,6 +873,7 @@ def update_current_span(
867873
that become available during execution.
868874
869875
Args:
876+
name: The span name
870877
input: Updated input data for the operation
871878
output: Output data from the operation
872879
metadata: Additional metadata to associate with the span
@@ -905,6 +912,9 @@ def update_current_span(
905912
environment=self._environment,
906913
)
907914

915+
if name:
916+
current_otel_span.update_name(name)
917+
908918
span.update(
909919
input=input,
910920
output=output,

langfuse/_client/span.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ def __init__(
561561
def update(
562562
self,
563563
*,
564+
name: Optional[str] = None,
564565
input: Optional[Any] = None,
565566
output: Optional[Any] = None,
566567
metadata: Optional[Any] = None,
@@ -575,6 +576,7 @@ def update(
575576
during execution, such as outputs, metadata, or status changes.
576577
577578
Args:
579+
name: Span name
578580
input: Updated input data for the operation
579581
output: Output data from the operation
580582
metadata: Additional metadata to associate with the span
@@ -607,6 +609,9 @@ def update(
607609
data=metadata, field="metadata", span=self._otel_span
608610
)
609611

612+
if name:
613+
self._otel_span.update_name(name)
614+
610615
attributes = create_span_attributes(
611616
input=processed_input,
612617
output=processed_output,
@@ -1048,6 +1053,7 @@ def __init__(
10481053
def update(
10491054
self,
10501055
*,
1056+
name: Optional[str] = None,
10511057
input: Optional[Any] = None,
10521058
output: Optional[Any] = None,
10531059
metadata: Optional[Any] = None,
@@ -1069,6 +1075,7 @@ def update(
10691075
token usage statistics, or cost details.
10701076
10711077
Args:
1078+
name: The generation name
10721079
input: Updated input data for the model
10731080
output: Output from the model (e.g., completions)
10741081
metadata: Additional metadata to associate with the generation
@@ -1123,6 +1130,9 @@ def update(
11231130
data=metadata, field="metadata", span=self._otel_span
11241131
)
11251132

1133+
if name:
1134+
self._otel_span.update_name(name)
1135+
11261136
attributes = create_generation_attributes(
11271137
input=processed_input,
11281138
output=processed_output,

tests/test_otel.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,23 @@ def test_span_hierarchy(self, langfuse_client, memory_exporter):
309309
# All spans should have the same trace ID
310310
assert len(set(s["trace_id"] for s in spans)) == 1
311311

312+
def test_update_current_span_name(self, langfuse_client, memory_exporter):
313+
"""Test updating current span name via update_current_span method."""
314+
# Create a span using context manager
315+
with langfuse_client.start_as_current_span(name="original-current-span"):
316+
# Update the current span name
317+
langfuse_client.update_current_span(name="updated-current-span")
318+
319+
# Verify the span name was updated
320+
spans = self.get_spans_by_name(memory_exporter, "updated-current-span")
321+
assert len(spans) == 1, "Expected one span with updated name"
322+
323+
# Also verify no spans exist with the original name
324+
original_spans = self.get_spans_by_name(
325+
memory_exporter, "original-current-span"
326+
)
327+
assert len(original_spans) == 0, "Expected no spans with original name"
328+
312329
def test_span_attributes(self, langfuse_client, memory_exporter):
313330
"""Test that span attributes are correctly set and updated."""
314331
# Create a span with attributes
@@ -360,6 +377,23 @@ def test_span_attributes(self, langfuse_client, memory_exporter):
360377
== "Test status"
361378
)
362379

380+
def test_span_name_update(self, langfuse_client, memory_exporter):
381+
"""Test updating span name via update method."""
382+
# Create a span with initial name
383+
span = langfuse_client.start_span(name="original-span-name")
384+
385+
# Update the span name
386+
span.update(name="updated-span-name")
387+
span.end()
388+
389+
# Verify the span name was updated
390+
spans = self.get_spans_by_name(memory_exporter, "updated-span-name")
391+
assert len(spans) == 1, "Expected one span with updated name"
392+
393+
# Also verify no spans exist with the original name
394+
original_spans = self.get_spans_by_name(memory_exporter, "original-span-name")
395+
assert len(original_spans) == 0, "Expected no spans with original name"
396+
363397
def test_generation_span(self, langfuse_client, memory_exporter):
364398
"""Test creating a generation span with model-specific attributes."""
365399
# Create a generation
@@ -394,6 +428,27 @@ def test_generation_span(self, langfuse_client, memory_exporter):
394428
)
395429
assert usage == {"input": 10, "output": 5, "total": 15}
396430

431+
def test_generation_name_update(self, langfuse_client, memory_exporter):
432+
"""Test updating generation name via update method."""
433+
# Create a generation with initial name
434+
generation = langfuse_client.start_generation(
435+
name="original-generation-name", model="gpt-4"
436+
)
437+
438+
# Update the generation name
439+
generation.update(name="updated-generation-name")
440+
generation.end()
441+
442+
# Verify the generation name was updated
443+
spans = self.get_spans_by_name(memory_exporter, "updated-generation-name")
444+
assert len(spans) == 1, "Expected one generation with updated name"
445+
446+
# Also verify no spans exist with the original name
447+
original_spans = self.get_spans_by_name(
448+
memory_exporter, "original-generation-name"
449+
)
450+
assert len(original_spans) == 0, "Expected no generations with original name"
451+
397452
def test_trace_update(self, langfuse_client, memory_exporter):
398453
"""Test updating trace level attributes."""
399454
# Create a span and update trace attributes
@@ -514,6 +569,25 @@ def test_complex_scenario(self, langfuse_client, memory_exporter):
514569
assert llm_input == {"prompt": "Summarize this text"}
515570
assert llm_output == {"text": "This is a summary"}
516571

572+
def test_update_current_generation_name(self, langfuse_client, memory_exporter):
573+
"""Test updating current generation name via update_current_generation method."""
574+
# Create a generation using context manager
575+
with langfuse_client.start_as_current_generation(
576+
name="original-current-generation", model="gpt-4"
577+
):
578+
# Update the current generation name
579+
langfuse_client.update_current_generation(name="updated-current-generation")
580+
581+
# Verify the generation name was updated
582+
spans = self.get_spans_by_name(memory_exporter, "updated-current-generation")
583+
assert len(spans) == 1, "Expected one generation with updated name"
584+
585+
# Also verify no spans exist with the original name
586+
original_spans = self.get_spans_by_name(
587+
memory_exporter, "original-current-generation"
588+
)
589+
assert len(original_spans) == 0, "Expected no generations with original name"
590+
517591
def test_custom_trace_id(self, langfuse_client, memory_exporter):
518592
"""Test setting a custom trace ID."""
519593
# Create a custom trace ID

0 commit comments

Comments
 (0)