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:

Configure injection in logs

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

PREVIEWING: esther/docs-9518-update-example-control-sensitive-log-data