Explore Observations in Langfuse Cloud Fast Preview (v4)
How to think about the new model
In v4, every operation your application performs — LLM calls, tool executions, retrievals, agent steps — is a first-class row in a single observations table. Think of it like a spreadsheet where each row is one operation, and you can slice by any column. The trace is just one column (trace_id) that groups related operations together, the same way session_id or user_id groups things.
This is more powerful than the old two-table model: instead of opening a trace and then scanning its children to find what went wrong, you can directly query across all operations. Find every GPT-4 call over $0.10, every retrieval that took more than 2 seconds, or every tool call that errored — without knowing which trace they belong to.
You will notice more rows in the table than before — that's expected. Each row is now one operation, not one trace. The key is to use filters and saved views to focus on what matters. Most users start with "root observations only" or "generations only" and go from there. The filter sidebar shows available values with counts, so you can discover which models, observation names, or error levels are most common before committing to a filter.
For conceptual background, see the observation-centric data model. For broader release context, see the Fast Preview (v4) docs.
Common views (recipes)
These are some of the most useful starting points. Each can be saved as a saved view for one-click access.
| I want to see… | How to filter |
|---|---|
| All traces (like the old table) | Filter for root observations (observations with no parent), save as a view |
| All LLM generations | Filter type = generation |
| Expensive LLM calls | Filter type = generation, sort by total_cost descending |
| Errors for a specific user | Filter by user_id and level = ERROR |
| Slow observations in a session | Filter by session_id, sort by latency descending |
| All operations for one trace | Filter by trace_id |
| Model performance comparison | Filter type = generation, group by model in a dashboard or sort by model column |
We recommend setting up 2-3 saved views for your most common debugging workflows so the observations table feels immediately useful to your team.
Before → After
| I want to have… | v3 | v4 |
|---|---|---|
| One row per trace | Traces table | Filter for root observations (observations with no parent), save as a saved view |
| One row per trace, scoped to a user or session | Traces table → filter by user/session | Same as above, add user_id or session_id filter |
| Cost, latency, or errors by user, session, or observation name | Traces table with filters | Self-serve dashboards |
Upgrade checklist
Ingest with a v4-compatible setup
Use one of these ingestion paths so your data appears in the unified table in real time:
- Python SDK v4: migration guide
- JS/TS SDK v5: migration guide
- Direct OpenTelemetry ingestion: set
x-langfuse-ingestion-version: 4on your OTEL span exporter. If you use OTLP HTTP environment variables, addx-langfuse-ingestion-version=4toOTEL_EXPORTER_OTLP_HEADERS. See OpenTelemetry setup.
If you are still sending data via older SDK versions, or via direct OpenTelemetry ingestion without x-langfuse-ingestion-version: 4, traces can appear in the unified tracing table with a delay of up to 10 minutes.
Propagate correlating attributes across observations
Use the SDK propagation helpers to propagate correlating attributes across child observations:
- Python:
propagate_attributes() - JS/TS:
propagateAttributes()
This is very important for filters to work accurately.
Attributes such as userId, sessionId, tags, metadata, version, and traceName should be available on observations so you can filter one table by request-level context and still work at observation granularity.
See Add attributes to observations for the SDK implementation details.
Share feedback
We are still iterating on the unified tracing experience. If something feels confusing, missing, or slower than expected, share feedback via support.
FAQ
Why are observations delayed or missing in the unified table?
The most common reason is that data is still being sent via older SDK versions or through a direct OpenTelemetry exporter without x-langfuse-ingestion-version: 4.
In the new v4 experience, those setups can lead to multi-minute delays before traces show up in the unified table.
If this happens, upgrade to Python SDK v4 or JS/TS SDK v5, or add the ingestion version header to your OTEL exporter.
How can I make this look more like the old traces table?
Create a saved view that filters to the root observation representing the start of each trace in your application (observations with no parent). That gives you a stable, trace-like list while still letting you drill into lower-level observations when needed. We recommend naming this view "Traces" so it feels familiar to your team.
The table shows too many rows — how do I make sense of it?
This is the most common reaction when first switching to the observations table. The old traces table showed one row per request; the new table shows every operation. The solution is filters and saved views — not scrolling. Start by filtering for root observations to get the trace-like view, then gradually explore more specific views (e.g., "all generations," "errors only"). Once you save 2-3 views that match your debugging workflows, the table will feel more focused than the old traces table, not less.
Can I get the old experience back?
Yes. For now, you can switch the v4 beta experience off in the UI and return to the previous tracing experience. This is temporary, though: the unified table will become the standard experience, so it is worth setting up saved views and instrumentation for the new model.