How Is Log-Trace Correlation Actually Implemented in OpenTelemetry?
A log line tells you what happened, and a trace tells you where it happened in the journey of a request. Correlation stamps the trace identity onto each log record so you can jump from one to the other. This tutorial opens the hood and shows exactly how that stamp gets there.
Imagine a hospital where every patient wears a wristband with a unique number. The doctor writes notes in one book, the nurse records vital signs in another, and the lab stores test results in a third. Because the wristband number appears in all three places, anyone can gather the complete story of one patient in a minute. Without the wristband, you would be comparing handwriting and guessing from timestamps. In OpenTelemetry, the wristband is the trace ID and span ID, and log-trace correlation is the practice of writing that wristband number on every log record.
1The Problem: Logs and Traces Living in Separate Worlds
Both signals describe the same events, yet by default they know nothing about each other.
Two different views of the same request
When a customer places an order, the system creates a trace that shows the request moving through the order service, the payment service, and the inventory service. The trace answers questions such as “which step was slow?” and “which service called which?” At the same time, each service writes log lines such as “payment declined” or “stock level too low.” The logs answer a different question: “what exactly did the code say at that moment?”
Each signal is useful, but each alone is incomplete. A trace shows a slow span but not the error message that explains why. A log shows an error message but not which customer request it belonged to, or what happened before and after it in other services.
The painful workaround: guessing by time
Without correlation, engineers use timestamps. They notice a slow span at 14:03:22, open the logs, filter by the service name, and scroll through lines around that time, hoping to spot the right one. On a busy service, hundreds of requests are happening in the same second, so many log lines look equally plausible. This guessing wastes time during incidents and sometimes leads to wrong conclusions.
Think of a busy railway station where announcements are recorded in one tape and camera footage in another. If you only know “around 5 pm,” you must watch and listen to everything. If the announcement tape and the camera footage both mention the platform number and train number, you can match them instantly.
Correlation replaces guessing with matching. A shared identifier written into both signals lets a tool, or a person, connect a log record to its trace in one step.
2A Quick Refresher on the Building Blocks
A few terms will appear again and again in this tutorial, so let us pin them down.
Trace and Span
A trace is the full story of one request. It is made of spans, which are timed steps such as “call the database.” Every span belongs to exactly one trace.
Trace ID and Span ID
The trace ID is a long unique number shared by all spans in one trace. The span ID is a shorter unique number for one particular span.
Log record
One entry in a log, with a time, a severity level such as warning or error, a message, and extra details attached as attributes.
Context
A small container, kept for the current piece of work, that holds the active span among other things. It is how code deep inside the program can find out which request it is serving.
Resource
A description of what is producing the telemetry, such as the service name, version, and host. All signals from the same service carry the same resource details.
Why the current context is the hero of this story
Inside a running program, the OpenTelemetry SDK keeps track of the current context, usually through a mechanism tied to the running thread or task. When code starts a span, that span becomes the active one in the current context. Any code that runs afterwards, including logging calls, can ask “what is the active span right now?” and get an answer, without anyone passing the span around as a parameter.
This quiet ability is the foundation of correlation. A logging call does not need to know about tracing. The logging machinery can peek into the current context at the moment the log is created and copy the identifiers from there.
The current context is like a visitor badge pinned to your shirt in an office. Every room you enter can read the badge without you introducing yourself. A log call is like writing in the visitor register: the register clerk glances at your badge and copies the number.
3What Does “Correlation” Really Mean?
Correlation is not one single technique. It works at three different levels, from strongest to weakest.
Level one: identity correlation
This is the strongest form. The log record carries the exact trace ID and span ID of the request that produced it. A tool can find the trace for any log, and every log for any trace, with a direct lookup. This is what people usually mean by log-trace correlation, and it is the main subject of this tutorial.
Level two: resource correlation
The second form is based on shared descriptions. Logs and traces from the same service instance carry the same resource attributes, such as the service name and the instance identifier. This does not point to one request, but it narrows the search to the right program and the right machine. It is useful when identity is missing.
Level three: time correlation
The weakest form uses time. Combined with resource correlation, you look at logs from the same service within the time window of a slow span. This is the guessing method described earlier. It is always available, but it is approximate, and it becomes unreliable under heavy traffic.
| Level | What links the signals | Precision | When it is used |
|---|---|---|---|
| Identity | Trace ID and span ID inside the log record | Exact, down to the request and the step | Whenever the logging path has access to the active context |
| Resource | Same service name, instance, and environment details | Narrows to a service or instance, not a request | Fallback, or a first filter before identity lookup |
| Time | Overlapping timestamps | Approximate | Last resort when nothing better exists |
Some people think correlation means that logs and traces are merged into one thing. They are not merged. They remain separate signals, often stored in different systems. Correlation is only the shared reference that lets tools connect them.
4The Log Data Model: Where the IDs Live
OpenTelemetry defines a standard shape for a log record, and trace identity has a dedicated place in it.
Top-level fields, not just attributes
In the OpenTelemetry log data model, the trace ID, span ID, and trace flags are first-class fields of the log record. They are not hidden inside a free-form attribute bag. This matters because tools can recognize and index these fields consistently, regardless of which language or logging library produced the record.
Timestamp
When the event happened, according to the source. A companion field records when the system observed it, which helps when logs are collected later from files.
Trace ID
The identifier of the trace that was active when the log was emitted. It is the main key for finding the matching trace.
Span ID
The identifier of the active span at that moment. It points to the exact step of work that wrote the log.
Trace flags
Small flags copied from the trace context, including whether the trace was sampled. This tells you if a stored trace is likely to exist.
Severity
How serious the record is, as both a standard number and an optional text label such as warning or error.
Body and attributes
The message itself, and additional key-value details that describe the event, such as the order number or the failure reason.
Resource and scope
Who produced the record, such as the service and host, and which library or module inside the service created it.
The format of the identifiers
The trace ID is a 16-byte value, usually shown as 32 lowercase hexadecimal characters. The span ID is an 8-byte value, shown as 16 hexadecimal characters. These are the same values that appear in the traceparent header used to pass context between services. Because the formats match, a log record’s trace ID can be compared directly with the ID of a stored trace.
A log record is like a delivery note with a printed box at the top for the order number. The box is always in the same place on every note, so a clerk can find it at a glance. A free-form comment buried in the text would be much harder to find reliably.
5The Core Mechanism: Reading the Active Span at Log Time
Every implementation, however different it looks on the surface, relies on the same small trick.
The trick in plain words
At the exact moment a log record is created, the system looks at the current context, finds the active span, reads its trace ID, span ID, and trace flags, and copies them into the log record. That is all. Everything else in this tutorial is about where and how this copying step is plugged into real logging libraries.
A request arrives and a span starts
The tracing instrumentation creates a server span for the incoming request and makes it the active span in the current context.
Application code runs and logs something
Somewhere deep in the code, a developer calls the normal logging library, for example to record that a payment was declined.
The logging hook looks at the current context
A small piece of OpenTelemetry-aware code, attached to the logging library, asks for the active span in the current context.
The identifiers are copied
The trace ID, span ID, and trace flags are read from the active span’s context and attached to the log record being built.
The log continues on its way
The record, now carrying its identity, is written to a file, printed to the console, or sent through the OpenTelemetry pipeline, depending on the chosen implementation path.
The copy happens at log creation time, not later. If no span is active at that moment, for example because the log is written before the request span starts, the record gets no identifiers. Correlation cannot be added afterwards by magic.
It is like a photographer who stamps the date and event name on a photo at the moment it is taken. If the stamp is not applied then, you can only guess the event later from the background.
Example: A declined payment
A payment service handles a request inside an active span. The code logs “card declined.” The logging hook reads the active span, copies its trace ID and span ID into the record, and from then on that log line is permanently tied to that exact step of that exact request.
6Path A: The Logs Bridge and Appenders
The first implementation path sends logs through the OpenTelemetry pipeline itself, with identity attached on the way.
The idea of a bridge
Most applications already use a logging library chosen long before OpenTelemetry existed. Developers do not want to rewrite thousands of logging calls. OpenTelemetry therefore defines a Logs Bridge API. This is not meant to be used by application developers directly. It is meant for authors of adapters, often called appenders or handlers, that plug into existing logging libraries and forward their records to the OpenTelemetry SDK.
What the bridge does
When the application logs through its usual library, the adapter receives the record, converts it into an OpenTelemetry log record, and hands it to a logger from the SDK. While doing so, it makes sure the current context is used. If the adapter does not supply a specific context, the SDK reads the current context and fills in the trace ID, span ID, and trace flags from the active span.
The path of a record
Application logging call
Developers keep using the logging library they already know.
OpenTelemetry appender
A plug-in attached to the library captures each record and converts its fields, such as message, level, and extra data.
Logger provider and SDK
The SDK builds the final log record, adds resource and scope details, and fills in trace identity from the current context.
Log record processor
A component that can batch records, filter them, or add information before export.
Exporter
Sends records, usually through OTLP, to a Collector or a backend.
flowchart LR
APP["Application log call"] --> LIB["Existing logging library"]
LIB --> APPD["OpenTelemetry appender or handler"]
APPD --> SDK["Logs SDK reads current context"]
SDK --> PROC["Log record processor"]
PROC --> EXP["OTLP exporter"]
EXP --> COL["Collector or backend"]
Where this path appears in practice
For several languages, appenders or handlers exist for the popular logging libraries. In some ecosystems, instrumentation agents install the appender automatically, so that existing logs flow through OpenTelemetry without code changes. Availability, default behavior, and maturity differ between languages and versions, so confirm the details for your stack.
Identity is added at the source, inside the process where the current context is certain to be available. The record is then exported in a structured form, with no text parsing needed later.
A bridge is like a translator who sits next to each speaker. The speakers keep talking in their own language, and the translator converts every sentence into the shared language on the spot, adding a name tag as well.
7Path B: Injecting Identifiers into Existing Log Output
Many teams keep writing logs to files or the console, and they still want correlation. A second path serves them.
The idea of enriching the log line
In this path, logs do not pass through the OpenTelemetry SDK. Instead, the instrumentation adds the trace ID and span ID into the data that the logging library already uses to build its text output. The log line is then written in the usual way, and the identifiers appear inside the text or inside the JSON, ready to be read later.
Two common techniques
Thread-local log context
Some logging libraries offer a per-thread dictionary, often called a mapped diagnostic context, whose values can be printed in every log line. The instrumentation places the trace ID, span ID, and trace flags into it whenever a span becomes active, and removes them afterwards.
Log record factory or filter
Other libraries allow a hook that creates or processes each log record. The instrumentation uses it to add extra fields, such as the trace ID, span ID, and service name, to every record as it is built.
The log format must cooperate
Adding values to the logging context is not enough on its own. The log format, also called the layout or pattern, must include those values in the output. If the format string never mentions the trace ID field, the value exists in memory but never reaches the file. Teams often discover this only when they inspect their logs and find no identifiers.
A span becomes active
The tracing instrumentation starts a span for the request or operation.
Identifiers are placed into the log context
The instrumentation writes the trace ID, span ID, and trace flags into the logging library’s context store for this thread or task.
The application logs normally
Developers call the logging library as they always did.
The layout prints the identifiers
The configured pattern or JSON layout includes the context fields, so they appear in each output line.
The identifiers are cleaned up
When the span ends, the instrumentation removes the values so that unrelated later logs do not carry stale identity.
Enabling the instrumentation but forgetting to update the log layout. The trace ID is available inside the program but never printed. Always check a real log file to confirm the identifiers appear.
Imagine a notebook with a header on every page, and a secretary who updates the header with the current case number each morning. Every note written that day automatically sits under the right case number, but only if the notebook actually has a header printed on the page.
8Path C: The Collector Reads Identity from Log Files
When identifiers sit inside text or JSON in log files, the OpenTelemetry Collector can lift them into proper log fields.
Why this step is needed
After Path B, the trace ID and span ID are present in the log files, but only as ordinary text. A backend reading the raw text would not know that a particular sequence of characters is a trace ID. To make correlation work in the standard way, someone must read those characters and put them into the top-level trace ID and span ID fields of the log record.
The file log receiver and its parsers
The Collector includes a receiver that reads log files from disk and turns each line into a log record. It supports a chain of small steps, called operators, that parse the line. Among them are parsers for JSON or pattern-based text, parsers that extract the timestamp and the severity, and a dedicated parser that takes trace ID, span ID, and trace flags from named fields and writes them into the proper positions in the log record.
Read the line
The receiver tails the log file and picks up each new line as raw text.
Parse its structure
A JSON or text parser splits the line into named parts, such as the message, level, time, and the identifier fields.
Promote the identifiers
The trace parsing step reads the trace ID and span ID parts and stores them in the record’s real trace ID and span ID fields.
Add resource details
Processors in the Collector add service and host information, so the log shares resource attributes with its traces.
Export
The now-correlated records are sent to the backend, where they can be linked to the traces.
flowchart LR
APP["Application writes enriched log line"] --> FILE["Log file or console stream"]
FILE --> FR["Collector file log receiver"]
FR --> PARSE["Parse JSON or text"]
PARSE --> TP["Promote trace ID and span ID to real fields"]
TP --> PROC["Add resource attributes"]
PROC --> EXP["Exporter to backend"]
This path is especially valuable for logs from containers on a cluster, where the platform already writes each container’s output to files on the node. The Collector can read those files without any change to the application process.
The parser expects identifiers in the format it is configured for, such as lowercase hexadecimal strings of the right length. If the application prints them differently, for example with extra prefixes, the parsing step may fail silently and leave the fields empty.
Think of a mailroom clerk who reads handwritten notes from old files, finds the case number written inside each one, and writes it on a new label in the official box. The information was already there. The clerk just moves it to the place where the filing system can use it.
9Comparing the Three Paths
None of the paths is universally best. The right choice depends on your logging setup and your operating model.
| Aspect | Path A: Bridge or appender | Path B: Inject into log output | Path C: Collector parses files |
|---|---|---|---|
| Where identity is added | Inside the SDK at log creation | Inside the log library’s context at log creation | In the Collector after the log is written |
| Uses OpenTelemetry log pipeline in the app | Yes | No | No, uses Collector pipeline |
| Output form | Structured records through OTLP | Text or JSON in files or console | Structured records after parsing |
| Code changes | Often none with an agent, or a small setup change | Layout or format change needed | Collector configuration needed |
| Strength | Clean, reliable, no parsing | Keeps existing log files and tools working | Works with logs the app cannot change |
| Weakness | Depends on appender support for your library | Depends on correct layout and formats | Depends on parsing rules, fragile if formats change |
Combining the paths
The paths are not mutually exclusive. A common setup uses Path B inside the application so that log files contain identifiers and remain readable for people, and Path C in the Collector to ship those files. Another common setup uses Path A in new services and Path B plus C for older ones. Platform teams often support all three, because a company’s services rarely share the same logging stack.
Example: A mixed fleet
A company has modern services using an agent with an appender, older services writing JSON files, and a vendor product that writes plain text. The platform team uses Path A for the first group, Path B plus C for the second, and for the third they accept resource and time correlation only, while asking the vendor about trace context support.
Prefer Path A when you can, because it avoids parsing. Use Paths B and C when you must keep file-based logs, or when you cannot change how the application ships its logs.
10Resource Attributes: The Second Half of Correlation
Identifiers connect individual events, but resource attributes connect whole services, and both matter.
Why resources need to match
Even with perfect identity correlation, you often start an investigation from a service, not from a single trace. You might ask “show me everything from the payment service in production.” For that to work, logs and traces must describe their source in exactly the same way. If traces say the service is “payment-service” and logs say “PaymentSvc,” tools cannot connect them.
Shared attributes worth getting right
service.name
The logical name of the service. It must be identical across traces, metrics, and logs.
service.version
The release version, which lets you compare behavior before and after a deployment.
deployment.environment
Whether the data comes from production, staging, or another environment, to avoid mixing them.
service.instance.id
The identity of one running copy of the service, which helps find the specific machine or container involved.
Host and container details
Detected facts such as the host name, container ID, or pod name that tie telemetry to its infrastructure.
Where mismatches come from
Traces and logs often take different paths. Traces may be produced by an agent that sets the service name from a setting, while logs are collected from files by a Collector that has to add the name itself. If the two sources are configured separately, small differences creep in. The solution is to define the service name once, in a common place such as an environment variable used by both, and to let the Collector enrich logs using the same values.
Identity correlation can work perfectly while resource correlation is broken, so that clicking from a log to its trace works but filtering by service in the dashboard shows two different names. Check both.
If a company spells its name differently on invoices and on delivery slips, the accounting system cannot match them even if the order numbers are right. Consistent naming is part of making records reconcile.
11An End-to-End Journey Across Two Services
Let us follow one request and see correlation working across services, using the simplest path.
The scenario
A customer places an order. The order service calls the payment service. The payment service declines the card and logs a warning. Both services use an agent with a logging appender, send telemetry to a Collector, and the Collector forwards traces to a tracing backend and logs to a log backend.
sequenceDiagram
participant O as Order Service
participant P as Payment Service
participant C as Collector
participant T as Tracing Backend
participant L as Log Backend
Note over O: Span A starts, trace ID is created
O->>P: Call with traceparent header
Note over P: Span B starts as child, same trace ID
Note over P: Log warning card declined, record gets trace ID and span B ID
P-->>O: Error response
Note over O: Log order failed, record gets trace ID and span A ID
O->>C: Export spans and logs
P->>C: Export spans and logs
C->>T: Spans
C->>L: Log records with trace and span IDs
What each piece contributes
Context propagation links the services
The order service passes the trace identity to the payment service through headers. Without this, the second service would start a different trace and its logs would carry a different trace ID.
Each service’s logging hook reads its own active span
The payment log gets the payment span’s ID and the shared trace ID. The order log gets the order span’s ID and the same trace ID.
The Collector ships both signals
Traces go to the tracing backend, and logs go to the log backend, each keeping the identifiers intact.
The user connects them
From the log line, a click on the trace ID opens the trace. From the failing span, a click opens the logs with the same trace ID, now from both services.
Context propagation gives all services the same trace ID, and the logging hook copies that ID into logs. If either part is missing, the chain of correlation breaks at that point.
12Sampling and Correlation: When the Trace Is Missing
A log may carry a perfectly valid trace ID, and yet clicking it may show nothing. Sampling is usually the reason.
Why a trace may not exist
Tracing systems rarely keep every trace, because of cost. A sampler decides at the start of a request whether to record it. If the trace is dropped, no spans are stored for it. But the logging hook still reads a valid trace ID from the active span context, because the span context exists even when the span is not recorded. The log record therefore points to a trace that was never stored.
The trace flags field to the rescue
The trace flags carried in the log record include the sampled flag. This tells a tool whether the trace was selected for recording. A log viewer can use it to decide whether to show a link to the trace, and an engineer reading the log can tell immediately that a missing trace is expected, not a bug.
flowchart TD
REQ["Request arrives"] --> SAMP{"Sampler decision"}
SAMP -- "Keep" --> REC["Span recorded, trace stored"]
SAMP -- "Drop" --> NOREC["Span not recorded, trace not stored"]
REC --> LOG1["Log has trace ID, sampled flag on"]
NOREC --> LOG2["Log has trace ID, sampled flag off"]
LOG1 --> OK["Link to trace works"]
LOG2 --> GAP["Link leads nowhere, by design"]
Strategies to reduce the gap
| Strategy | How it helps | Cost or trade-off |
|---|---|---|
| Keep traces that contain errors, using tail sampling in the Collector | The most interesting traces, those with error logs, are more likely to exist | The Collector must buffer traces, which uses memory and needs careful design |
| Use a higher sampling rate for critical services | More traces exist for important flows | More storage and processing cost |
| Show the sampled flag in the log viewer | Engineers know when a missing trace is expected | Requires tooling that understands the flag |
| Rely on resource and time correlation as fallback | Still lets you narrow down the area of the problem | Less precise than identity |
A log with a trace ID but no matching trace is not necessarily a broken integration. Before debugging, check the trace flags and the sampling settings. The data may simply have been dropped on purpose.
A library catalogue may list a book that was later sold off. The reference number is valid, but the shelf is empty. A note saying “withdrawn from circulation” explains why. The sampled flag is that note.
13Using Correlation in Practice: Investigation Workflows
Correlation matters only if it changes how engineers find and fix problems. Here are the typical workflows.
From a log to its trace
Find an error log
An alert or a search leads the engineer to a log record showing a failure.
Click the trace link
The log viewer uses the trace ID to open the full trace for that request.
See the context
The trace shows which services were involved, how long each step took, and where the failing span sits in the whole story.
From a trace to its logs
Spot a slow or failed span
Looking at a trace, the engineer sees a span with an error status or an unusual duration.
Open related logs
The tool queries the log backend for records with the same trace ID, and possibly the same span ID.
Read the explanation
The log messages reveal exceptions, input values, or decisions that explain why the span behaved as it did.
Other everyday uses
Support tickets with a trace ID
Some teams return the trace ID in error responses or show it in the application’s error page. A customer can quote it to support staff, who then pull up every log and span for that exact request.
Filtering noise during an incident
Instead of reading thousands of lines from a busy service, the engineer filters logs to only those belonging to traces that include a failing span. The haystack shrinks dramatically.
Events as logs
OpenTelemetry has been moving toward representing point-in-time events as log records rather than as events attached inside spans. Because those log records carry trace identity, they still appear in the right place within a trace. Check the current status of this direction in the project documentation.
The links between logs and traces are drawn by your backend or dashboard tool, not by OpenTelemetry itself. OpenTelemetry supplies the identifiers. The tool must be configured to know where logs and traces live and how to link them.
14Strengths, Costs, and Security Considerations
Correlation is cheap compared to its value, but it is not free of caveats.
Advantages
- Direct jump between a log record and its trace
- Replaces timestamp guessing with exact matching
- Costs only two small identifiers per log record
- Works across services thanks to context propagation
- Uses open standards, so backends can be changed
- Helps support teams trace one customer’s request end to end
Disadvantages / Trade-offs
- Needs setup in each language and logging library
- Fails silently when the context is lost or formats mismatch
- Logs may point to traces dropped by sampling
- Third-party logs may carry no identifiers at all
- Logs and traces may have different retention periods
Privacy and security angles
Trace IDs are random identifiers and are not secrets by themselves, but they are powerful keys for finding related data. Anyone who can search logs by trace ID can reconstruct what happened during a request. Logs themselves often contain sensitive details, such as email addresses or tokens, written by careless code. Correlation makes such data easier to find, which is good for debugging and risky for privacy.
Sensitive log content
Review what your code logs, and mask personal data before it is written. Collector processors can also redact attributes before export.
Access control
Ensure that people who can search logs by trace ID are the same people allowed to see the underlying data, and review access to both backends.
Exposing IDs externally
Returning a trace ID to customers is helpful, but it should be done knowingly, since it reveals an internal identifier and may help correlate requests.
Volume and cost
Sending all logs through the telemetry pipeline can be large. Use severity filters and sampling rules for noisy, low-value logs.
A patient’s wristband number is harmless on its own, but it opens the door to the whole medical file. So hospitals protect the files and decide carefully who may look up a number.
15Troubleshooting, Best Practices, and Anti-patterns
When the link between a log and a trace is missing, the cause usually falls into a small number of categories.
Troubleshooting guide
| Symptom | Likely cause | What to check |
|---|---|---|
| Logs have no trace ID at all | No active span at log time, or logging hook not installed | Whether the instrumentation or appender is enabled, and whether the log is written inside a request |
| Trace ID present in memory but not in the log file | Log layout does not print the context fields | The log pattern or JSON layout configuration |
| Trace ID in text but empty in the backend | Collector parsing not configured or formats mismatch | Parser settings and the exact identifier format in the log line |
| Logs from background threads lack identity | Context not carried to the other thread or task | Context handoff in custom thread pools and async code |
| Link to trace leads nowhere | Trace was not sampled or has expired | Trace flags, sampling policy, and retention periods |
| Log and trace show different service names | Resource attributes configured separately | Service name settings in the application and in the Collector |
| Logs from one service have wrong trace IDs | Stale values left in the thread’s log context | Cleanup after spans end, and thread reuse in pools |
Habits that work
Verify with a real request
Send a test request, find its log line, and click through to the trace. Do this after every logging change.
Prefer structured logging
JSON or similar structured output keeps identifiers in named fields and makes parsing reliable.
Define the service name once
Use a single source of truth for resource attributes so traces and logs always agree.
Carry context across threads
Use context-aware wrappers for thread pools, timers, and callbacks, so logs in background work keep their identity.
Align retention
Keep logs and traces for compatible periods, so links do not outlive their destinations.
Configure backend links
Teach your dashboards how to map a trace ID in a log to the tracing backend, and the reverse.
Traps to avoid
Problem
Developers manually copy trace IDs into log messages as part of the message text, using their own formats.
Why It’s Harmful
Identifiers end up in inconsistent places and formats, tools cannot recognize them, and every new service repeats the work with different mistakes.
Correct Approach
Let the instrumentation or appender populate standard fields automatically, and keep application code free of tracing details.
Problem
Teams rely only on timestamps and service names to connect logs and traces, even though identity correlation is available.
Why It’s Harmful
Under heavy traffic, many requests share the same time window, so matches are unreliable and investigations are slow.
Correct Approach
Enable identity correlation and treat time and resource matching as fallbacks only.
Problem
The log layout is never updated, so identifiers are available in the program but never printed into files.
Why It’s Harmful
The team believes correlation is working, but no log line contains an identifier, and the gap is discovered during an incident.
Correct Approach
Inspect real log output after enabling instrumentation, and add a check to your deployment tests.
Problem
Logs are shipped with correlation fields, but sampling and retention differ widely between the logging and tracing systems, with no one tracking the mismatch.
Why It’s Harmful
Engineers click links that lead to missing or expired traces, lose trust in the feature, and stop using it.
Correct Approach
Align sampling and retention policies, surface the sampled flag, and document what users can expect.
16Frequently Asked Questions
Quick answers to the questions people ask most often.
No. You can keep your existing log files and add identifiers to the log output, then let the Collector or your log tool read them. Sending logs through the OpenTelemetry SDK is one option, not a requirement.
No. It is intended for people who write adapters between existing logging libraries and the OpenTelemetry SDK. Application developers continue to use their normal logging library.
They are read from the active span in the current context at the moment the log record is created. This is the same span that the tracing instrumentation made active for the current request or operation.
Common reasons are that no span was active when the log was written, the logging hook is not installed, the log was written on a thread that lost the context, or the log came from software that does not support trace context.
No. The Collector can only move identifiers that already exist in the log into the proper fields. It cannot invent the identity of a request after the fact. Identity has to be captured at log creation time.
Metrics are linked to traces through a different mechanism called exemplars, which attach sample measurements with trace identity to metric data points. Resource attributes also connect metrics, logs, and traces from the same service.
The most common reason is sampling, where the trace was never stored. Another is that the trace has already expired in the tracing backend. Check the sampled flag and the retention settings of both systems.
Yes, as long as context propagation works between them and each service attaches the active trace identity to its own logs. The identifiers use the same standard formats everywhere.
The cost is very small, since it involves reading two identifiers and writing them into the record. The larger costs come from the volume of logs shipped, not from the correlation itself.
Prefer sending logs through an appender when your language and library support it, because it avoids parsing. Use log file enrichment with Collector parsing when you must keep file-based logs or cannot change how applications ship them. Many organizations use more than one path at the same time.
17Summary and Key Takeaways
Log-trace correlation in OpenTelemetry rests on one simple idea: at the moment a log record is created, read the active span from the current context and stamp its trace ID, span ID, and trace flags onto the record. The log data model gives those values dedicated fields, so every tool can find them. There are three common ways to implement the stamp. A logs bridge or appender sends records through the SDK with identity attached. Context injection writes the identifiers into the output of existing logging libraries. The Collector can then parse file logs and promote the identifiers into real fields. Resource attributes and timestamps provide weaker fallback links. Context propagation keeps the trace ID consistent across services, and sampling decides whether a log’s trace actually exists. With matching service names, aligned retention, and careful handling of sensitive data, correlation turns two separate signals into one searchable story.
Key Takeaways
- The core mechanism is simple — at log creation time, the active span is read from the current context, and its trace ID, span ID, and flags are copied into the log record.
- The log data model has dedicated fields — trace ID, span ID, and trace flags are top-level fields, so tools can index and link them consistently.
- Three practical paths exist — appenders send logs through the SDK, context injection enriches existing log output, and the Collector parses files to promote identifiers into proper fields.
- The Logs Bridge API is for adapter authors — application developers keep using their normal logging libraries.
- Resource and time correlation are fallbacks — consistent service names narrow the search, but only identity proves which request a log belongs to.
- Sampling can leave links without a destination — check the sampled flag and retention before assuming the integration is broken.
- Verify and protect — test with a real request, make sure the log layout prints the fields, and treat trace IDs and log content with proper access and privacy controls.