The most surprising thing about Tempo’s "exemplars" is that they aren’t just any log line associated with a trace; they’re specifically the first log line that matches a particular criteria at the time the trace was sampled.

Let’s watch this in action. Imagine you have a service, my-app, that’s receiving requests. When a request comes in, it generates a trace ID. This trace ID is propagated through your system. At various points, your application logs messages, and these log messages also get annotated with the trace ID.

Here’s a simplified log line from my-app:

{
  "ts": "2023-10-27T10:30:00Z",
  "level": "info",
  "msg": "Processing user request",
  "trace_id": "a1b2c3d4e5f67890",
  "span_id": "0987654321fedcba",
  "user_id": "user-123"
}

And here’s a trace from Tempo, showing a span within my-app that corresponds to this request:

[Span ID: 0987654321fedcba]
  - Service: my-app
  - Operation: ProcessUserRequest
  - Start: 2023-10-27T10:30:00Z
  - Duration: 50ms
  - Attributes:
    - http.method: POST
    - http.url: /users/123/process

When Tempo is configured to collect logs, and specifically when it’s set up for "exemplars," it looks for these log lines associated with the trace. It doesn’t just grab all logs for that trace; it grabs a sample. The "exemplar" is typically the first log line generated for a given trace ID that matches certain criteria (like having a trace_id field).

The magic happens when you’re viewing a trace in Grafana. You’ll see the trace spans, and if exemplars are configured and found, you’ll see a small log icon next to certain spans. Clicking this icon doesn’t take you to a separate log viewer; it embeds the exemplar log line directly within the trace view.

[Span ID: 0987654321fedcba]
  - Service: my-app
  - Operation: ProcessUserRequest
  - Start: 2023-10-27T10:30:00Z
  - Duration: 50ms
  - Attributes:
    - http.method: POST
    - http.url: /users/123/process
  - [Log Icon] "Processing user request" (ts: 2023-10-27T10:30:00Z, trace_id: a1b2c3d4e5f67890)

This correlation is achieved through a few key components:

  1. Tempo’s Ingestion: Tempo needs to be configured to receive logs. This typically involves a collector (like the Grafana Agent or Fluentd/Fluent Bit) that forwards logs to Tempo.
  2. Log Line Structure: Crucially, your log lines must contain the trace_id that was originally generated by your tracing system (e.g., Jaeger, OpenTelemetry). This is the glue.
  3. Grafana Configuration: In Grafana, you set up Tempo as a data source. Then, in your dashboard or Explore view, when viewing traces, you enable the "Trace to Logs" feature. This tells Grafana to look for associated logs.
  4. Exemplar Configuration (Tempo & Collector): The collector sending logs to Tempo needs to be configured to tag logs with trace_id. Tempo itself, when configured for exemplars, uses this trace_id to link logs back to traces. The critical part is that the collector needs to be configured to send these trace IDs along with the logs to Tempo. For example, with the Grafana Agent, you might have a loki component that sends logs, and you ensure the trace_id is present and correctly mapped. Tempo then uses a specific mechanism to identify these "exemplar" logs during ingestion, often by looking for a specific field or pattern.

The mental model here is that tracing gives you the "what happened and when" across services, and logs give you the "why" at a granular, per-service level. Exemplars bridge this by pulling representative log entries directly into the trace view, eliminating the need to manually switch context and search for logs based on a trace ID. You’re essentially asking Tempo: "For this specific trace, what was the most important log message happening concurrently?"

The "exemplar" is determined by the sampling strategy of the collector at the time the log was ingested and associated with a trace ID. If a log line doesn’t have a trace_id field, or if the collector isn’t configured to send it, it won’t be linkable as an exemplar. This means that even if a log should be associated with a trace, if the trace_id wasn’t captured correctly by the log collection pipeline, it will never appear as an exemplar.

The next step you’ll likely encounter is needing to correlate these trace-linked logs with metrics, leading you to explore Tempo’s integration with Prometheus or other metric systems.

Want structured learning?

Take the full Tempo course →