Skip to content

docs: document propagate_attributes scope, trace.list lightweight views, and ingestion latency#1764

Draft
jannikmaierhoefer wants to merge 1 commit into
mainfrom
claude/langfuse-python-docs-gaps-6eba63
Draft

docs: document propagate_attributes scope, trace.list lightweight views, and ingestion latency#1764
jannikmaierhoefer wants to merge 1 commit into
mainfrom
claude/langfuse-python-docs-gaps-6eba63

Conversation

@jannikmaierhoefer

Copy link
Copy Markdown
Member

What changed

Docstring-only changes closing three documentation gaps that agent-behavior testing showed cause real debugging sessions. No behavior changes. Companion docs PR: langfuse/langfuse-docs#3316.

1. propagate_attributes scope semantics (langfuse/_client/propagation.py)

  • New "Scope — exactly which spans receive the attributes" section: the currently active span at context entry + every span started while the context is active; spans started earlier (notably detached roots from start_observation(), which never become the active span) are not retroactively stamped.
  • New "Where the attributes land" section: user.id/session.id OTel attributes on each covered exported span; after ingestion they surface as trace-level fields (api.trace.get(trace_id).session_id). Observation API objects expose no session_id/user_id fields, so asserting on fetched child observations always fails — a repeated source of confusion.
  • New examples: where attributes land in exported spans, and the detached-root ordering anti-pattern with two correct alternatives.
  • Verified against span_processor.on_start and the 132 tests in tests/unit/test_propagate_attributes.py (attributes do propagate to all child spans; the "root only" folk belief comes from the API surface, not the SDK).

2. trace.list returns lightweight views (langfuse/api/trace/client.py)

  • list (sync + async): documents that observations/scores on TraceWithDetails are ID strings, not full objects; trace-level aggregates are included; point to trace.get / observations.get_many for per-observation usage/cost.
  • get (sync + async): documents full-detail return type and the 404-until-ingested behavior.

3. Ingestion latency (langfuse/_client/client.py)

  • flush(): guarantees delivery, not read visibility; reads right after flush may raise langfuse.api.NotFoundError (typically visible within ~15-30s, no fixed SLA) — retry with bounded backoff.
  • create_score() and get_dataset_run(): same async-ingestion visibility notes.

Drive-by fix (pre-existing docstring bug)

Docstring examples called langfuse.propagate_attributes(...), but the Langfuse client has no such method (hasattr(Langfuse, "propagate_attributes") is False) — following the documented examples raised AttributeError. Examples now import and use the module-level function; two :meth: cross-references in client.py/span.py corrected to :func:.

Reviewer notes

  • ⚠️ langfuse/api/trace/client.py is Fern-generated — the added notes will be lost on the next API-spec regen unless the same text is upstreamed into the OpenAPI endpoint descriptions in langfuse/langfuse. Flagging rather than deciding: happy to drop that file from this PR if you prefer upstream-only.
  • The Python 404 exception is langfuse.api.NotFoundError; there is no LangfuseNotFoundError in this SDK.
  • Considered and recommended against adding a wait_for_trace()/retry-kwarg helper for now: trace presence ≠ trace completeness (observations arrive incrementally), so a naive helper would trade a loud 404 for silently incomplete usage/cost reads. The docs PR ships a bounded-backoff snippet instead.
  • Checks run: ruff check + ruff format --check, mypy on edited files, pytest tests/unit/test_propagate_attributes.py tests/unit/test_otel.py (197 passed, 2 skipped).

🤖 Generated with Claude Code

…t views, and ingestion latency

Docstring-only changes, no behavior changes:

- propagate_attributes: document exactly which spans receive the attributes
  (currently active span at context entry + every span started while the
  context is active), where they land in exported spans (user.id/session.id
  OTel attributes per span; trace-level fields after ingestion; Observation
  API objects expose no session_id/user_id), and the detached-root ordering
  pitfall with correct alternatives.
- api.trace.list/get: note that list returns lightweight TraceWithDetails
  views (observations/scores are ID strings) and that get may 404 with
  langfuse.api.NotFoundError until async ingestion completes; recommend
  bounded retries. Note: these files are Fern-generated, so this text should
  also be upstreamed to the OpenAPI spec descriptions to survive regens.
- flush()/create_score()/get_dataset_run(): clarify that flush guarantees
  delivery, not read visibility (typically 15-30s, no SLA).
- Fix pre-existing docstring bug: examples called
  langfuse.propagate_attributes(...), but the client has no such method —
  use the module-level function; fix two :meth: cross-references to :func:.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant