[AAI-235] Add OTLP v4 header and v2 reads#95
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Langfuse Cloud “Fast Preview” OTLP export headers (ingestion v4 + SDK identification) and introduces new flat read APIs on the Ruby SDK client for observations, metrics, and scores, aligning the SDK with the current v2/v3 query surfaces.
Changes:
- OTLP exporter now sends
x-langfuse-ingestion-version: 4plus SDK identification headers on every span export. - New
Langfuse::ReadApimixed intoApiClientand delegated fromClient:list_observations,query_metrics,list_scores. - Adds specs and API reference documentation for the new read methods and OTLP header behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/langfuse/read_api_spec.rb | Adds request/param-mapping and error-handling coverage for the new read endpoints and client delegation. |
| spec/langfuse/otel_setup_spec.rb | Verifies OTLP header construction now includes ingestion version and SDK identification. |
| lib/langfuse/read_api.rb | Implements v2/v3 read methods and query param mapping helpers. |
| lib/langfuse/otel_setup.rb | Updates OTLP exporter to use a unified header builder emitting v4 ingestion + SDK headers. |
| lib/langfuse/client.rb | Delegates new read methods on the flat Client API surface. |
| lib/langfuse/api_client.rb | Mixes in ReadApi so reads share existing HTTP transport and error handling. |
| lib/langfuse.rb | Ensures ReadApi is required as part of the gem load. |
| docs/API_REFERENCE.md | Documents list_observations, query_metrics, and list_scores. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def validate_bounded_observation_read!(trace_id, from_start_time, to_start_time) | ||
| return if trace_id | ||
| return if from_start_time && to_start_time | ||
|
|
||
| raise ArgumentError, | ||
| "from_start_time and to_start_time are required unless trace_id is provided" | ||
| end |
There was a problem hiding this comment.
Fixed in c4a2d4d with a present? check covering trace_id and both time bounds; specs added.
| # @param type [String, nil] Filter by observation type (e.g. "GENERATION", "SPAN") | ||
| # @param level [String, nil] Filter by level (e.g. "DEFAULT", "ERROR") | ||
| # @param parent_observation_id [String, nil] Filter by parent observation ID | ||
| # @param environment [String, Array<String>, nil] Filter by environment(s) |
There was a problem hiding this comment.
Fixed in c4a2d4d — environment is now documented as String only, consistent with list_traces. Multi-environment filtering can go through the structured filter param.
| | `type` | String | No | Filter by observation type (e.g. `"GENERATION"`, `"SPAN"`) | | ||
| | `level` | String | No | Filter by level (e.g. `"DEFAULT"`, `"ERROR"`) | | ||
| | `parent_observation_id` | String | No | Filter by parent observation ID | | ||
| | `environment` | String, Array<String> | No | Filter by environment(s) | |
There was a problem hiding this comment.
Fixed in c4a2d4d — docs now list environment as String.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c4a2d4d. Configure here.

TL;DRSend the Langfuse Fast Preview OTLP headers (
x-langfuse-ingestion-version: 4plus SDK identification) on every span export, and add flatlist_observations,query_metrics, andlist_scoresread methods backed by the current v2/v3 endpoints.WhyLangfuse requires direct OpenTelemetry exporters to send
x-langfuse-ingestion-version: 4for real-time Fast Preview processing; without it data can be delayed on the new UI and v2 read surfaces. The SDK also had no way to read observations, metrics, or scores through the current API generation — only legacy/api/public/tracesreads, which remain unchanged.OtelSetupnow sends Basic auth, ingestion version,x-langfuse-sdk-name,x-langfuse-sdk-version, andx-langfuse-public-keyfrom one header builder.ReadApimodule (mixed intoApiClient, delegated fromClient):list_observations→GET /api/public/v2/observations(Cloud-only, cursor pagination, fulldata/metaenvelope preserved; unbounded reads withouttrace_idraiseArgumentError)query_metrics→GET /api/public/v2/metrics(Hash queries JSON-encoded; pre-encoded strings pass through)list_scores→GET /api/public/v3/scores(polymorphic values preserved)Live-validated against Langfuse Cloud: OTLP export with the new headers round-trips,
list_scoresreturns one page with a cursor, and v2 endpoints surface the API's v4-write-mode guidance verbatim on a project not yet in v4 write mode.ChecklistCloses AAI-235
Note
Medium Risk
Changes affect all OTLP trace ingestion (behavior/timing on Cloud) and introduce new HTTP read surfaces; observation listing enforces bounds client-side to avoid unbounded scans.
Overview
OTLP exports now send Langfuse Fast Preview headers on every span export:
x-langfuse-ingestion-version: 4plus SDK name, version, and public key (in addition to Basic auth), so ingested traces show up promptly on the new UI and v2 read surfaces.Read APIs are added via a new
ReadApimodule onApiClientand delegated fromClient:list_observations(Cloud v2, cursor pagination, bounded reads unlesstrace_idis set),query_metrics(Cloud v2), andlist_scores(v3, polymorphic values). There is no fallback to legacy trace endpoints—errors from missing v2 routes surface as-is.API_REFERENCE.mddocuments the new methods.Specs cover header building, query param mapping, validation, and client delegation.
Reviewed by Cursor Bugbot for commit 91ba75d. Bugbot is set up for automated code reviews on this repo. Configure here.