Connecting .NET Logs and Traces
Datadog の調査レポート: サーバーレスの状態 レポート: サーバーレスの状態

Connecting .NET Logs and Traces

このページは日本語には対応しておりません。随時翻訳に取り組んでいます。翻訳に関してご質問やご意見ございましたら、お気軽にご連絡ください。

Automatically Inject Trace and Span IDs

Enable injection in the .NET Tracer’s configuration by setting DD_LOGS_INJECTION=true through environment variables or the configuration files.

The .NET Tracer uses the LibLog library to automatically inject trace IDs, span IDs, env, service, and version into your application logs. If you haven’t done so already, it is recommended to configure the .NET tracer with DD_ENV, DD_SERVICE, and DD_VERSION. This will provide the best experience when adding env, service, and version (see Unified Service Tagging for more details).

We support Serilog, NLog (version 2.0.0.2000+), or log4net. Automatic injection only displays in the application logs after enabling LogContext enrichment in your Serilog logger or Mapped Diagnostics Context in your NLog or log4net logger (see examples below).

Note: Automatic injection only works for logs formatted as JSON.

var log = new LoggerConfiguration()
    // Add Enrich.FromLogContext to emit MDC properties
    .Enrich.FromLogContext()
    .WriteTo.File(new JsonFormatter(), "log.json")
    .CreateLogger();
  <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 value="message" />
    <!--remove the default preformatted message member-->
    <member value="message:messageobject" />
    <!--add raw message-->

    <!-- Add value='properties' to emit MDC properties -->
    <member value='properties'/>
  </layout>

For NLog version 4.6+:

  <!-- 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:

  <!-- 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>

Manually Inject Trace and Span IDs

If you prefer to manually correlate your traces with your logs and tie together data for your service, leverage the Datadog API to retrieve correlation identifiers:

  • Use CorrelationIdentifier.<FIELD> API methods to inject identifiers at the beginning and end of each span to log (see examples below).
  • Configure MDC to use the injected keys:

    • dd.env Globally configured env for the tracer (defaults to "" if not set)
    • dd.service Globally configured root service name (defaults to the name of the application or IIS site name if not set)
    • dd.version Globally configured version for the service (defaults to "" if not set)
    • dd.trace_id Active Trace ID during the log statement (defaults to 0 if no trace)
    • dd.span_id Active Span ID during the log statement (defaults to 0 if no trace)
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
}
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");
}
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
}

Note: 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. More information can be found in the FAQ on this topic.

Further Reading