Correlating PHP Logs and Traces
Automatic injection
Starting in version 0.89.0
, the PHP tracer automatically injects trace correlation identifiers into application logs. To enable automatic injection, set the environment variable DD_LOGS_INJECTION
(INI setting datadog.logs_injection
) to true
.
The PHP tracer supports PSR-3 compliant loggers, such as Monolog or Laminas Log.
Note: Set up your logging library to produce logs in JSON format so that:
If you haven’t done so already, configure the PHP tracer with DD_ENV
, DD_SERVICE
, and DD_VERSION
. This provides the best experience for adding env
, service
, and version
to your logs (see Unified Service Tagging for more details).
The PHP tracer provides various ways to configure the injection of trace correlation identifiers into your logs:
Option 1: Add all trace correlation identifiers to the log context
The default behavior of the PHP tracer is to add all trace correlation identifiers to the log context.
For example, if you are using the Monolog library in a Laravel application as follows:
use Illuminate\Support\Facades\Log;
# ...
Log::debug('Hello, World!');
The PHP tracer adds the available trace correlation identifiers to the log context, in JSON format. The logged message above could be transformed into:
[2022-12-09 16:02:42] production.DEBUG: Hello, World! {"dd.trace_id":"1234567890abcdef","dd.span_id":"1234567890abcdef","dd.service":"laravel","dd.version":"8.0.0","dd.env":"production","status":"debug"}
Note: If there is a placeholder in your message or if a trace ID is already present in the message, the PHP tracer does not add the trace correlation identifiers to the log context.
Option 2: Use placeholders in your message
You can use placeholders in your message to select which trace correlation identifiers are automatically injected into your logs. The PHP tracer supports the following placeholders:
%dd.trace_id%
: the trace ID%dd.span_id%
: the span ID%dd.service%
: the service name%dd.version%
: the service version%dd.env%
: the service environment
Placeholders are case-sensitive and must be enclosed in %
characters.
For example, if you are using the Monolog library in a Laravel application, you can configure the injection into a log message as follows:
use Illuminate\Support\Facades\Log;
# ...
Log::info('Hello, World! [%dd.trace_id% %dd.span_id% %status%]');
The PHP tracer replaces the placeholders with the corresponding values. For example, the logged message above is transformed into:
[2022-12-09 16:02:42] production.INFO: Hello, World! [dd.trace_id="1234567890abcdef" dd.span_id="1234567890abcdef" status="info"]
Note: The brackets are mandatory if you plan on using the default parsing rules provided in the PHP log pipeline. If you are using a custom parsing rule, you can omit the brackets if needed.
Manual injection
Note: The function
\DDTrace\current_context()
has been introduced in version
0.61.0 and returns decimal trace identifiers.
To connect your logs and traces together, your logs must contain the dd.trace_id
and dd.span_id
attributes that respectively contain your trace ID and your span ID.
If you are not using a Datadog Log Integration to parse your logs, custom log parsing rules need to ensure that dd.trace_id
and dd.span_id
are being parsed as strings and remapped thanks to the Trace Remapper. More information can be found in Correlated Logs Not Showing Up in the Trace ID Panel.
For instance, you would append those two attributes to your logs with:
<?php
$append = sprintf(
' [dd.trace_id=%s dd.span_id=%s]',
\DDTrace\logs_correlation_trace_id(),
\dd_trace_peek_span_id()
);
my_error_logger('Error message.' . $append);
?>
If the logger implements the monolog/monolog library, use Logger::pushProcessor()
to automatically append the identifiers to all log messages. For monolog v1, add the following configuration:
<?php
$logger->pushProcessor(function ($record) {
$record['message'] .= sprintf(
' [dd.trace_id=%s dd.span_id=%s]',
\DDTrace\logs_correlation_trace_id(),
\dd_trace_peek_span_id()
);
return $record;
});
?>
For monolog v2, add the following configuration:
<?php
$logger->pushProcessor(function ($record) {
return $record->with(message: $record['message'] . sprintf(
' [dd.trace_id=%s dd.span_id=%s]',
\DDTrace\logs_correlation_trace_id(),
\dd_trace_peek_span_id()
));
});
?>
If your application uses JSON logs format, you can add a first-level key dd
that contains the trace_id
and span_id
, instead of appending trace_id
and span_id
to the log message:
<?php
$logger->pushProcessor(function ($record) use ($context) {
$record['dd'] = [
'trace_id' => \DDTrace\logs_correlation_trace_id(),
'span_id' => \dd_trace_peek_span_id()
];
return $record;
});
?>
For monolog v3, add the following configuration:
<?php
$logger->pushProcessor(function ($record) {
$record->extra['dd'] = [
'trace_id' => \DDTrace\logs_correlation_trace_id(),
'span_id' => \dd_trace_peek_span_id()
];
return $record;
});
?>
If you are ingesting your logs as JSON, go to Preprocessing for JSON logs and add extra.dd.trace_id
to the Trace Id Attributes field.
Further Reading
Additional helpful documentation, links, and articles: