---
title: Correlating .NET Logs and Traces
description: Connect your .NET logs and traces to correlate them in Datadog.
breadcrumbs: >-
  Docs > APM > Correlate APM Data with Other Telemetry > Correlate Logs and
  Traces > Correlating .NET Logs and Traces
---

# Correlating .NET Logs and Traces

You can set up your logging library and .NET tracing configurations so that trace and span IDs are injected into application logs, providing you with application performance monitoring data correlated with log data.

Configure the .NET Tracer with [Unified Service Tagging](https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging) for the best experience and helpful context when correlating application traces and logs.

The .NET Tracer supports the following logging libraries:

- [Serilog](http://serilog.net) (v1.4+)
- [log4net](https://logging.apache.org/log4net)
- [NLog](http://nlog-project.org)
- [Microsoft.Extensions.Logging](https://docs.microsoft.com/en-us/dotnet/core/extensions/logging) (added in v1.28.6)

## Configure log collection{% #configure-log-collection %}

Ensure that log collection is configured in the Datadog Agent and that the [Logs Agent configuration](https://docs.datadoghq.com/logs/log_collection/csharp/#configure-your-datadog-agent) for the specified files to tail is set to `source: csharp` so log pipelines can parse the log files. For more information, see [C# Log Collection](https://docs.datadoghq.com/logs/log_collection/csharp/). If the `source` is set to a value other than `csharp`, you may need to add a [trace remapper](https://docs.datadoghq.com/logs/log_configuration/processors/?tab=ui#trace-remapper) to the appropriate log processing pipeline for the correlation to work correctly.

{% alert level="danger" %}
Automatic log collection only works for logs formatted as JSON. Alternatively, use custom parsing rules.
{% /alert %}

## Configure injection in logs{% #configure-injection-in-logs %}

To inject correlation identifiers into your log messages, follow the instructions for your logging library.

{% alert level="info" %}
See the [samples in dd-trace-dotnet](https://github.com/DataDog/dd-trace-dotnet/tree/master/tracer/samples/AutomaticTraceIdInjection) for more examples.
{% /alert %}

{% tab title="Serilog" %}

{% alert level="danger" %}
**Note:**Starting with .NET Tracer version 2.0.1, automatic injection for the Serilog logging library requires the application to be instrumented with automatic instrumentation.
{% /alert %}

To automatically inject correlation identifiers into your log messages:

1. Configure the .NET Tracer with the following tracer settings:

   - `DD_ENV`
   - `DD_SERVICE`
   - `DD_VERSION`

1. Enable auto-instrumentation tracing of your app by following the [instructions to install the .NET Tracer](https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-core/).

{% /tab %}

{% tab title="log4net" %}

{% alert level="danger" %}
**Note:**Starting with .NET Tracer version 1.29.0, automatic injection for the log4net logging library requires the application to be instrumented with automatic instrumentation.
{% /alert %}

To automatically inject correlation identifiers into your log messages:

1. Configure the .NET Tracer with the following tracer settings:

   - `DD_ENV`
   - `DD_SERVICE`
   - `DD_VERSION`

1. Enable auto-instrumentation tracing of your app by following the [instructions to install the .NET Tracer](https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-core/).

1. Add `dd.env`, `dd.service`, `dd.version`, `dd.trace_id`, and `dd.span_id` log properties into your logging output. This can be done by including these properties *individually* or by including *all* log properties. Both approaches are shown in the following example code:

```xml
  <layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
    <decorator type="log4net.Layout.Decorators.StandardTypesDecorator, log4net.Ext.Json" />
    <default />
    <!--explicit default members-->
    <remove value="ndc" />
    <!--remove the default preformatted message member-->
    <remove value="message" />
    <!--add raw message-->
    <member value="message:messageobject" />

    <!-- Include Datadog properties -->
    <!-- EITHER Include individual properties with value='<property_name>' -->
    <member value='dd.env' />
    <member value='dd.service' />
    <member value='dd.version' />
    <member value='dd.trace_id' />
    <member value='dd.span_id' />
    <!-- OR Include all properties with value='properties' -->
    <member value='properties'/>
  </layout>
```

For additional examples, see [the log4net automatic trace ID injection project](https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/samples/AutomaticTraceIdInjection/Log4NetExample/log4net.config) on GitHub.
{% /tab %}

{% tab title="NLog" %}

{% alert level="danger" %}
**Note:**Starting with .NET Tracer version 2.0.1, automatic injection for the NLog logging library requires the application to be instrumented with automatic instrumentation.
{% /alert %}

To automatically inject correlation identifiers into your log messages:

1. Configure the .NET Tracer with the following tracer settings:

   - `DD_ENV`
   - `DD_SERVICE`
   - `DD_VERSION`

1. Enable auto-instrumentation tracing of your app by following the [instructions to install the .NET Tracer](https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-core/).

1. Enable mapped diagnostic context (MDC), as shown in the following example code for NLog version 5.0+:

```xml
  <!-- Add includeScopeProperties="true" to emit ScopeContext properties -->
  <layout xsi:type="JsonLayout" includeScopeProperties="true">
    <attribute name="date" layout="${longdate}" />
    <attribute name="level" layout="${level:upperCase=true}"/>
    <attribute name="message" layout="${message}" />
    <attribute name="exception" layout="${exception:format=ToString}" />
  </layout>
```

For NLog version 4.6+:

```xml
  <!-- Add includeMdlc="true" to emit MDC properties -->
  <layout xsi:type="JsonLayout" includeMdlc="true">
    <attribute name="date" layout="${longdate}" />
    <attribute name="level" layout="${level:upperCase=true}"/>
    <attribute name="message" layout="${message}" />
    <attribute name="exception" layout="${exception:format=ToString}" />
  </layout>
```

For NLog version 4.5:

```xml
  <!-- Add includeMdc="true" to emit MDC properties -->
  <layout xsi:type="JsonLayout" includeMdc="true">
    <attribute name="date" layout="${longdate}" />
    <attribute name="level" layout="${level:upperCase=true}"/>
    <attribute name="message" layout="${message}" />
    <attribute name="exception" layout="${exception:format=ToString}" />
  </layout>
```

For additional examples, see the automatic trace ID injection projects using [NLog 4.0](https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/samples/AutomaticTraceIdInjection/NLog40Example/NLog.config), [NLog 4.5](https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/samples/AutomaticTraceIdInjection/NLog45Example/NLog.config), or [NLog 4.6](https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/samples/AutomaticTraceIdInjection/NLog46Example/NLog.config) on GitHub.
{% /tab %}

{% tab title="Microsoft.Extensions.Logging" %}
To automatically inject correlation identifiers into your log messages:

1. Configure the .NET Tracer with the following tracer settings:

   - `DD_ENV`
   - `DD_SERVICE`
   - `DD_VERSION`

1. Enable auto-instrumentation tracing of your app by following the [instructions to install the .NET Tracer](https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-core/).

1. Enable [log scopes](https://docs.microsoft.com/aspnet/core/fundamentals/logging/#log-scopes-1) for your logging provider, as shown in the example code. Only providers that support log scopes will have correlation identifiers injected.

```csharp
Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        logging.AddFile(opts =>
        {
            opts.IncludeScopes = true; // must include scopes so that correlation identifiers are added
            opts.FormatterName = "json";
        });
    }
```

If there is an active trace when the log is being written, trace and span IDs are automatically injected into the application logs with `dd_trace_id` and `dd_span_id` properties. If there is not an active trace, only `dd_env`, `dd_service`, and `dd_version` properties are injected.

**Note:** If you are using a logging library that replaces the default `LoggerFactory` implementation such as the [*Serilog.Extensions.Hosting*](https://github.com/serilog/serilog-extensions-hosting) or [*Serilog.Extensions.Logging*](https://github.com/serilog/serilog-extensions-logging) packages, follow the framework-specific instructions (in this example, see **Serilog**).

For additional examples, see [the Microsoft.Extensions.Logging automatic trace id injection project](https://github.com/DataDog/dd-trace-dotnet/blob/master/tracer/samples/AutomaticTraceIdInjection/MicrosoftExtensionsExample/Program.cs) on GitHub.
{% /tab %}

Next, complete the setup for either automatic or manual injection.

## Automatic injection{% #automatic-injection %}

To enable automatic correlation identifier injection, ensure `DD_LOGS_INJECTION` is enabled.

Starting in version 3.24.0, `DD_LOGS_INJECTION` is enabled by default. For older versions, set `DD_LOGS_INJECTION=true` in the .NET Tracer's environment variables.

To configure the .NET Tracer with a different method, see [Configuring the .NET Tracer](https://docs.datadoghq.com/tracing/trace_collection/library_config/dotnet-core/#configuring-the-net-tracer).

After configuring the correlation identifier injection, see [C# Log Collection](https://docs.datadoghq.com/logs/log_collection/csharp/) to configure your log collection.

**Note:** To correlate traces with logs, you might need to set up a [trace ID remapper](https://docs.datadoghq.com/logs/log_configuration/processors/?tab=ui#trace-remapper) to parse `dd_trace_id` as the log's trace ID. See [Correlated Logs Not Showing Up in the Trace ID Panel](https://docs.datadoghq.com/tracing/troubleshooting/correlated-logs-not-showing-up-in-the-trace-id-panel/?tab=withlogintegration) for more information.

{% alert level="info" %}
Starting in version 2.35.0, if [Agent Remote Configuration](https://docs.datadoghq.com/remote_configuration) is enabled where this service runs, you can set `DD_LOGS_INJECTION` in the [Software Catalog](https://docs.datadoghq.com/tracing/software_catalog) UI.
{% /alert %}

## Manual injection{% #manual-injection %}

If you prefer to manually correlate your traces with your logs, you can add correlation identifiers to your logs.

| Required key  | Description                                                                                                     |
| ------------- | --------------------------------------------------------------------------------------------------------------- |
| `dd.env`      | Globally configures the `env` for the tracer. Defaults to `""` if not set.                                      |
| `dd.service`  | Globally configures the root service name. Defaults to the name of the application or IIS site name if not set. |
| `dd.version`  | Globally configures `version` for the service. Defaults to `""` if not set.                                     |
| `dd.trace_id` | Active trace ID (represented as a 64-bit decimal number) during the log statement. Defaults to `0` if no trace. |
| `dd.span_id`  | Active span ID (represented as a 64-bit decimal number) during the log statement. Defaults to `0` if no trace.  |

**Note:** If you are not using a [Datadog Log Integration](https://docs.datadoghq.com/logs/log_collection/csharp/) to parse your logs, custom log parsing rules must parse `dd.trace_id` and `dd.span_id` as strings. For information, see [Correlated Logs Not Showing Up in the Trace ID Panel](https://docs.datadoghq.com/tracing/troubleshooting/correlated-logs-not-showing-up-in-the-trace-id-panel/?tab=custom).

**Note**: If you are using Serilog, Nlog or log4net through ILogger, see the Microsoft.Extensions.Logging section to configure these properties using `BeginScope()`.

After completing the getting started steps, finish your manual log enrichment setup:

1. Reference the [`Datadog.Trace` NuGet package](https://www.nuget.org/packages/Datadog.Trace/) in your project.

1. Use the `CorrelationIdentifier` API to retrieve correlation identifiers and add them to the log context while a span is active.

Lastly, see [C# Log Collection](https://docs.datadoghq.com/logs/log_collection/csharp/) to configure your log collection.

Examples:

{% tab title="Serilog" %}
**Note**: The Serilog library requires message property names to be valid C# identifiers. The required property names are: `dd_env`, `dd_service`, `dd_version`, `dd_trace_id`, and `dd_span_id`.

```csharp
using Datadog.Trace;
using Serilog.Context;

// there must be spans started and active before this block.
using (LogContext.PushProperty("dd_env", CorrelationIdentifier.Env))
using (LogContext.PushProperty("dd_service", CorrelationIdentifier.Service))
using (LogContext.PushProperty("dd_version", CorrelationIdentifier.Version))
using (LogContext.PushProperty("dd_trace_id", CorrelationIdentifier.TraceId.ToString()))
using (LogContext.PushProperty("dd_span_id", CorrelationIdentifier.SpanId.ToString()))
{
    // Log something
}
```

{% /tab %}

{% tab title="log4net" %}

```csharp
using Datadog.Trace;
using log4net;

// there must be spans started and active before this block.
try
{
    LogicalThreadContext.Properties["dd.env"] = CorrelationIdentifier.Env;
    LogicalThreadContext.Properties["dd.service"] = CorrelationIdentifier.Service;
    LogicalThreadContext.Properties["dd.version"] = CorrelationIdentifier.Version;
    LogicalThreadContext.Properties["dd.trace_id"] = CorrelationIdentifier.TraceId.ToString();
    LogicalThreadContext.Properties["dd.span_id"] = CorrelationIdentifier.SpanId.ToString();

    // Log something

}
finally
{
    LogicalThreadContext.Properties.Remove("dd.env");
    LogicalThreadContext.Properties.Remove("dd.service");
    LogicalThreadContext.Properties.Remove("dd.version");
    LogicalThreadContext.Properties.Remove("dd.trace_id");
    LogicalThreadContext.Properties.Remove("dd.span_id");
}
```

{% /tab %}

{% tab title="NLog" %}

```csharp
using Datadog.Trace;
using NLog;

// there must be spans started and active before this block.
using (MappedDiagnosticsLogicalContext.SetScoped("dd.env", CorrelationIdentifier.Env))
using (MappedDiagnosticsLogicalContext.SetScoped("dd.service", CorrelationIdentifier.Service))
using (MappedDiagnosticsLogicalContext.SetScoped("dd.version", CorrelationIdentifier.Version))
using (MappedDiagnosticsLogicalContext.SetScoped("dd.trace_id", CorrelationIdentifier.TraceId.ToString()))
using (MappedDiagnosticsLogicalContext.SetScoped("dd.span_id", CorrelationIdentifier.SpanId.ToString()))
{
    // Log something
}
```

{% /tab %}

{% tab title="Microsoft.Extensions.Logging" %}

```csharp
using Datadog.Trace;
using Microsoft.Extensions.Logging;

ILogger _logger;

// there must be spans started and active before this block.
using(_logger.BeginScope(new Dictionary<string, object>
{
    {"dd.env", CorrelationIdentifier.Env},
    {"dd.service", CorrelationIdentifier.Service},
    {"dd.version", CorrelationIdentifier.Version},
    {"dd.trace_id", CorrelationIdentifier.TraceId.ToString()},
    {"dd.span_id", CorrelationIdentifier.SpanId.ToString()},
}))
{
    // Log something
}
```

{% /tab %}

You can read more about using BeginScope to create structured log messages for the following log providers:

- Serilog: [The semantics of ILogger.BeginScope()](https://nblumhardt.com/2016/11/ilogger-beginscope/)
- NLog: [NLog properties with Microsoft Extension Logging](https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-properties-with-Microsoft-Extension-Logging)
- log4net: [Using BeginScope](https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore#using-beginscope)

## Further Reading{% #further-reading %}

- [Manually instrument your application to create traces.](https://docs.datadoghq.com/tracing/trace_collection/custom_instrumentation)
- [Explore your services, resources, and traces](https://docs.datadoghq.com/tracing/glossary/)
- [Correlate request logs with traces automatically](https://www.datadoghq.com/blog/request-log-correlation/)
- [Ease troubleshooting with cross product correlation.](https://docs.datadoghq.com/logs/guide/ease-troubleshooting-with-cross-product-correlation/)
