How Observe's unified field model uses trace_id, span_id and service to link logs, metrics and traces, letting you drill from one alert down to the failing log line and code path.
When something breaks in production, the usual drill goes like this: the dashboard shows the error rate spiking, the alert gives you a curve and a few numbers, then you switch to the logging platform to grep through dozens of files with a different query language, and finally open the tracing UI to find out which service and method actually threw. Three systems, three query syntaxes, three sets of permissions — and the incident window keeps widening while you bounce between them.
Every context switch costs minutes. You re-authenticate, re-learn the query syntax, re-type the same filter conditions, and copy identifiers from one tab to another. For a team on-call at 3 a.m., those minutes are exactly what turns a contained failure into a customer-visible outage.
Logs answer "what happened", metrics answer "what's the overall trend", and traces answer "how did this request travel end to end". All three come from the same requests, but because they live in separate systems with inconsistent field naming, matching them up by hand is painful. The most common failure mode looks like this: an error-rate alert fires, an engineer digs through logs and finds the exception stack, but has no idea what the full call path was — so they head back to the tracing system and start hunting blind.
Observe normalizes three key fields at ingestion time:
The same trace_id appears in an ERROR log line, in a specific span of the trace, and in the latency and error metrics produced by that request. Once the fields are aligned, correlation becomes a query-level capability rather than manual stitching.
These three fields were chosen deliberately. trace_id is the join key that spans all three datasets; span_id gives you sub-request granularity so you can pinpoint a single method; service is the aggregation dimension every dashboard and alert already uses. This is why we keep repeating one point: an observability platform's value is not in "how much data it stores", but in "whether the data can be matched against each other".
Say an alert fires because order-service exceeds a 5% error rate. In Observe, the investigation is four steps:
-- 1. Find the endpoint with the most errors
SELECT endpoint, count(*) AS err_cnt
FROM metrics
WHERE service = 'order-service' AND status = 'error' AND ts > now() - 10m
GROUP BY endpoint ORDER BY err_cnt DESC LIMIT 10;
-- 2. Grab the trace_id of a failing request
SELECT trace_id
FROM logs
WHERE service = 'order-service' AND level = 'ERROR'
ORDER BY ts DESC LIMIT 1;
-- 3. Open the trace detail in the console to find the slow/failing span
-- 4. Back to logs, read the context around that span
SELECT * FROM logs WHERE trace_id = '<trace_id from above>' ORDER BY ts ASC;
Four steps take you from "error rate is up" to "this log line, that method timed out" — all inside one platform, no copying trace_ids between three systems. Search is SQL-like, so anyone who can write SELECT ... WHERE ... is productive immediately; ops, developers and testers all speak the same language instead of each maintaining a private dialect. That single language also means a new teammate can follow an incident's trail without first learning three different tools.
Unified fields are the precondition for correlation, and the data foundation for everything that comes after — automatic attribution, AI root-cause analysis and anomaly detection. Get the fields right first, and the advanced features will have solid ground to stand on.