OpenTelemetry standardizes three kinds of telemetry — traces, metrics, and logs — collectively called "signals." Each answers a different question about your system's behavior.
Traces
A trace represents the full journey of a single request as it moves through a distributed system — from the load balancer, through an API gateway, into several microservices, and out to a database. A trace is made up of one or more spans, each representing a single unit of work (an HTTP call, a database query, a function execution). Spans carry a start time, a duration, attributes, and a parent-child relationship to other spans, which is what lets you reconstruct the whole call tree.
Traces answer: "Where did this specific request spend its time, and where did it fail?"
Metrics
A metric is a numeric measurement recorded over time — a request count, an error rate, memory usage, queue depth. Metrics are aggregated: instead of storing every individual value, the SDK combines many measurements into a compact time series (a sum, an average, a histogram bucket). This makes metrics cheap to store and fast to query even at very high volume.
Metrics answer: "How is the system behaving in aggregate, right now and over time?"
Logs
A log is a timestamped, unstructured or structured record of a discrete event — an error message, a warning, a debug statement. Logs are the oldest and most granular signal: often free-text, but OpenTelemetry's log data model supports structured attributes and, critically, can be linked to the trace and span that was active when the log was emitted.
Logs answer: "What exactly happened, in detail, at this moment?"
The resource: what ties them together
Every signal — every span, metric data point, and log record — is tagged with a Resource: a set of attributes describing the entity producing the telemetry (service name, service version, deployment environment, host, container ID, cloud region). Because all three signals share the same resource model, you can pivot from a metric spike straight to the traces and logs from the same service, in the same environment, at the same time.
A resource attribute describes the thing producing telemetry (e.g. service.name) and is attached once per process. A span/metric/log attribute describes the specific event (e.g. http.status_code) and varies per data point.
Correlating the three
The real power of OpenTelemetry isn't any single signal — it's correlation. A typical debugging flow looks like:
- A metric dashboard shows p99 latency spiking on the checkout service.
- You jump to traces for that service in the spike window and find slow spans concentrated in a downstream call to the inventory service.
- You pull the logs emitted during that exact span (linked via trace ID and span ID) and find a connection pool exhaustion warning.
Each signal narrows the search. Metrics tell you something is wrong and roughly where; traces tell you which requests and which hop; logs tell you why, in detail.
Which signal answers which question
| Question | Signal |
|---|---|
| Is the system healthy right now? | Metrics |
| Which specific request was slow, and where? | Traces |
| What exact error message was thrown? | Logs |
| What's the error rate trend over the last week? | Metrics |
| Did this request retry, and how many times? | Traces |
| What was the stack trace at the moment of failure? | Logs |
Traces, metrics, and logs are complementary, not redundant. OpenTelemetry's contribution is making sure all three carry the same resource identity so they can be correlated in one backend instead of three disconnected tools.