Skip to content

fix(observe): preserve current span observation type#1688

Open
fengjikui wants to merge 1 commit into
langfuse:mainfrom
fengjikui:fix-observe-update-current-span-type
Open

fix(observe): preserve current span observation type#1688
fengjikui wants to merge 1 commit into
langfuse:mainfrom
fengjikui:fix-observe-update-current-span-type

Conversation

@fengjikui
Copy link
Copy Markdown

@fengjikui fengjikui commented Jun 7, 2026

Summary

  • Preserve the active observation type when update_current_span() wraps the current OTEL span for updates.
  • Add a regression test for @observe(as_type="guardrail", capture_output=False) followed by update_current_span(output=...).

Fixes #1676.

Verification

  • uv run --frozen pytest tests/unit/test_observe.py::test_observe_capture_output_false_preserves_as_type_after_current_span_update -q
  • uv run --frozen pytest tests/unit/test_observe.py -q
  • uv run --frozen pytest tests/unit/test_otel.py::TestBasicSpans::test_update_current_span_name tests/unit/test_otel.py::TestBasicSpans::test_update_current_generation_name -q
  • uv run --frozen ruff check langfuse/_client/client.py tests/unit/test_observe.py
  • uv run --frozen ruff format --check langfuse/_client/client.py tests/unit/test_observe.py
  • uv run --frozen mypy langfuse --no-error-summary

Greptile Summary

This PR fixes a bug where update_current_span() always wrapped the active OTEL span as a LangfuseSpan, losing the original observation type (e.g., "guardrail") set by @observe(as_type=...). The fix reads the OBSERVATION_TYPE attribute from the current OTEL span and dispatches to _get_span_class() before constructing the wrapper — consistent with the pattern already used in set_current_trace_io and set_current_trace_as_public.

  • langfuse/_client/client.py: update_current_span now reads LangfuseOtelSpanAttributes.OBSERVATION_TYPE from the active span's attributes and uses _get_span_class() to select the correct wrapper class instead of hardcoding LangfuseSpan.
  • tests/unit/test_observe.py: Adds a regression test verifying that a @observe(as_type=\"guardrail\", capture_output=False) span retains its type after update_current_span(output=...) is called.

Confidence Score: 5/5

Safe to merge — the change is a targeted, one-line logical fix that matches the existing pattern used by two other methods in the same class.

The fix reads the existing OBSERVATION_TYPE attribute before constructing the wrapper span, exactly mirroring set_current_trace_io and set_current_trace_as_public which already did this correctly. The _get_span_class method has a safe fallback to LangfuseSpan for unknown types. The added regression test directly covers the reported bug scenario.

No files require special attention.

Sequence Diagram

sequenceDiagram
    participant U as User Code
    participant D as @observe(as_type=guardrail)
    participant C as Langfuse Client
    participant OS as OTEL Span

    U->>D: call decorated function
    D->>OS: "start span, set OBSERVATION_TYPE=guardrail"
    U->>C: "update_current_span(output=...)"
    C->>OS: _get_current_otel_span()
    OS-->>C: current_otel_span
    C->>OS: attributes.get(OBSERVATION_TYPE, span)
    OS-->>C: guardrail
    C->>C: _get_span_class(guardrail) to LangfuseGuardrail
    C->>C: "LangfuseGuardrail(otel_span=current_otel_span)"
    C->>OS: "span.update(output=...)"
    Note over OS: OBSERVATION_TYPE preserved as guardrail
    D->>OS: "end span (capture_output=False)"
Loading

Reviews (1): Last reviewed commit: "fix(observe): preserve current span obse..." | Re-trigger Greptile

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jun 7, 2026

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@observe(as_type=…, capture_output=False) silently downgrades observation to type=span

2 participants