Skip to content

Commit

Permalink
Add documentation and sample applications for Automatic Trace ID Inje…
Browse files Browse the repository at this point in the history
…ction (DataDog#538)

- Create a demo directory in the repo to highlight small code samples that our users can reference for setting up various capabilities
- Add an AutomaticTraceIdInjection folder with a README that describes the additional change needed to get Trace/Log correlation working correctly, and sample apps for each supported logging framework with this capability:
    - log4net
    - NLog
    - Serilog
  • Loading branch information
zacharycmontoya authored Mar 19, 2020
1 parent 549672e commit 1709f7e
Show file tree
Hide file tree
Showing 17 changed files with 540 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Datadog.Trace" Version="1.8.0" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="log4net.Ext.Json" Version="2.0.8.3" />
</ItemGroup>

<ItemGroup>
<None Update="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.IO;
using Datadog.Trace;
using log4net;
using log4net.Config;

namespace Log4NetExample
{
class Program
{
private static readonly ILog log = LogManager.GetLogger(typeof(Program));

static void Main(string[] args)
{
var logRepository = LogManager.GetRepository(typeof(Program).Assembly);
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));

try
{
LogicalThreadContext.Properties["order-number"] = 1024;
log.Info("Message before a trace.");
using (var scope = Tracer.Instance.StartActive("Log4NetExample - Main()"))
{
log.Info("Message during a trace.");
}
}
finally
{
LogicalThreadContext.Properties.Remove("order-number");
}

log.Info("Message after a trace.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"profiles": {
"Log4NetExample": {
"commandName": "Project",
"environmentVariables": {
"DD_LOGS_INJECTION": "true"
},
"nativeDebugging": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<!-- For the SerializedLayout from the log4net.Ext.Json NuGet package, you can explicitly extract the 'dd.trace_id' and 'dd.span_id' values using new <member> nodes (see: https://github.com/BrightOpen/log4net.Ext.Json#json-stuff) -->
<!--
Additions to layout:
- <member value='dd.trace_id' />
- <member value='dd.span_id' />
-->
<appender name="jsonFileExplicitPropertiesAppender" type="log4net.Appender.FileAppender" >
<file value="log-log4net-jsonFile-explicitProperties.log" />
<layout type='log4net.Layout.SerializedLayout, log4net.Ext.Json'>
<decorator type='log4net.Layout.Decorators.StandardTypesDecorator, log4net.Ext.Json' />
<default />
<!--explicit default members-->
<remove value='message' />
<!--remove the default preformatted message member-->
<member value='message:messageobject' />
<!--add raw message-->
<member value='order-number' />

<!-- Manual changes: start -->
<member value='dd.trace_id' />
<member value='dd.span_id' />
<!-- Manual changes: end -->
</layout>
</appender>

<!-- For the SerializedLayout from the log4net.Ext.Json NuGet package, you can also explicitly extract the 'properties' value, which will automatically emit the `dd.trace_id` and `dd.span_id` values (see: https://github.com/BrightOpen/log4net.Ext.Json#json-stuff) -->
<!--
Additions to layout:
- <member value='properties'/>
-->
<appender name="jsonFileAllPropertiesAppender" type="log4net.Appender.FileAppender" >
<file value="log-log4net-jsonFile-allProperties.log" />
<!-- Set up SerializedLayout as defined here: https://github.com/BrightOpen/log4net.Ext.Json#json-stuff -->
<layout type='log4net.Layout.SerializedLayout, log4net.Ext.Json'>
<decorator type='log4net.Layout.Decorators.StandardTypesDecorator, log4net.Ext.Json' />
<default />
<!--explicit default members-->
<remove value='message' />
<!--remove the default preformatted message member-->
<member value='message:messageobject' />
<!--add raw message-->

<!-- Manual changes: start -->
<member value='properties'/>
<!-- Manual changes: end -->
</layout>
</appender>



<!-- For the default PatternLayout, you must explicitly extract the 'dd.trace_id' and 'dd.span_id' values using the %property{name} syntax (see: https://logging.apache.org/log4net/release/manual/contexts.html) -->
<!--
- Additions to layout: {traceId=&quot;%property{dd.trace_id}&quot;,spanId=&quot;%property{dd.span_id}&quot;}
- -->
<!--
Parsing this log line with a custom Pipeline that adds Trace/Log correlation can be done with the following Processors:
1. Grok Parser: Set the parsing rules to `log_parser %{date("yyyy-MM-dd HH:mm:ss,SSS"):date} \[%{integer:thread}\] %{word:level} %{notSpace:logger} \{%{data::keyvalue}} - %{data:message}`
2. Trace Id Remapper: Set the trace_id attribute to 'traceId'
-->
<appender name="textFileAppender" type="log4net.Appender.FileAppender">
<file value="log-log4net-textFile.log" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %level %logger {traceId=&quot;%property{dd.trace_id}&quot;, spanId=&quot;%property{dd.span_id}&quot;} - %message%newline" />
</layout>
</appender>

<root>
<level value="INFO" />
<appender-ref ref="jsonFileExplicitPropertiesAppender" />
<appender-ref ref="jsonFileAllPropertiesAppender" />
<appender-ref ref="textFileAppender" />
</root>
</log4net>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<!-- For JsonLayout when includeMdc=true, you do not need to do any additional work to extract the 'dd.trace_id' and 'dd.span_id' values (see: https://github.com/NLog/NLog/wiki/JsonLayout) -->
<!--
Additions to layout: none
-->
<target name="jsonFile-includeMdc-true" xsi:type="File" fileName="log-NLog45-jsonFile-includeMdc-true.log">
<layout xsi:type="JsonLayout" includeMdc="true">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception:format=ToString}" />
</layout>
</target>

<!-- For JsonLayout when includeMdc=false, you must explicitly extract the 'dd.trace_id' and 'dd.span_id' values using new <attribute> nodes (see: https://github.com/NLog/NLog/wiki/JsonLayout) -->
<!--
Additions to layout:
- <attribute name="dd.trace_id" layout="${mdc:item=dd.trace_id}"/>
- <attribute name="dd.span_id" layout="${mdc:item=dd.span_id}"/>
-->
<target name="jsonFile-includeMdc-false" xsi:type="File" fileName="log-NLog45-jsonFile-includeMdc-false.log">
<layout xsi:type="JsonLayout" includeMdc="false">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception:format=ToString}" />

<!-- Manual changes: start -->
<attribute name="dd.trace_id" layout="${mdc:item=dd.trace_id}"/>
<attribute name="dd.span_id" layout="${mdc:item=dd.span_id}"/>
<!-- Manual changes: end -->
</layout>
</target>

<!-- For a custom layout, you must explicitly extract the 'dd.trace_id' and 'dd.span_id' values -->
<!--
Additions to layout: {traceId=&quot;${mdc:item=dd.trace_id}&quot;,spanId=&quot;${mdc:item=dd.span_id}&quot;}
-->
<!--
Parsing this log line with a custom Pipeline that adds Trace/Log correlation can be done with the following Processors:
1. Grok Parser: Set the parsing rules to `log_parser %{date("yyyy-MM-dd HH:mm:ss.SSSS"):time}\|%{word:level}\|%{notSpace:logger}\|\{%{data::keyvalue}}\|%{data:message}`
2. Trace Id Remapper: Set the trace_id attribute to 'traceId'
-->
<target name="textFile" xsi:type="File" fileName="log-NLog45-textFile.log"
layout="${longdate}|${uppercase:${level}}|${logger}|{traceId=&quot;${mdc:item=dd.trace_id}&quot;,spanId=&quot;${mdc:item=dd.span_id}&quot;}|${message}" />
</targets>

<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="jsonFile-includeMdc-true,jsonFile-includeMdc-false,textFile" />
</rules>
</nlog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Datadog.Trace" Version="1.8.0" />
<PackageReference Include="NLog" Version="4.5.11" />
</ItemGroup>

<ItemGroup>
<None Update="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Datadog.Trace;
using NLog;

namespace NLog45Example
{
class Program
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

static void Main(string[] args)
{
using (MappedDiagnosticsLogicalContext.SetScoped("order-number", 1024))
{
Logger.Info("Message before a trace.");

using (var scope = Tracer.Instance.StartActive("NLog45Example - Main()"))
{
Logger.Info("Message during a trace.");
}

Logger.Info("Message after a trace.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"profiles": {
"NLog45Example": {
"commandName": "Project",
"environmentVariables": {
"DD_LOGS_INJECTION": "true"
},
"nativeDebugging": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<!-- For JsonLayout when includeMdlc=true, you do not need to do any additional work to extract the 'dd.trace_id' and 'dd.span_id' values (see: https://github.com/NLog/NLog/wiki/JsonLayout) -->
<!--
Additions to layout: none
-->
<target name="jsonFile-includeMdlc-true" xsi:type="File" fileName="log-NLog46-jsonFile-includeMdlc-true.log">
<layout xsi:type="JsonLayout" includeMdlc="true">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception:format=ToString}" />
</layout>
</target>

<!-- For JsonLayout when includeMdlc=false, you must explicitly extract the 'dd.trace_id' and 'dd.span_id' values using new <attribute> nodes (see: https://github.com/NLog/NLog/wiki/JsonLayout) -->
<!--
Additions to layout:
- <attribute name="dd.trace_id" layout="${mdlc:item=dd.trace_id}"/>
- <attribute name="dd.span_id" layout="${mdlc:item=dd.span_id}"/>
-->
<target name="jsonFile-includeMdlc-false" xsi:type="File" fileName="log-NLog46-jsonFile-includeMdlc-false.log">
<layout xsi:type="JsonLayout" includeMdlc="false">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception:format=ToString}" />

<!-- Manual changes: start -->
<attribute name="dd.trace_id" layout="${mdlc:item=dd.trace_id}"/>
<attribute name="dd.span_id" layout="${mdlc:item=dd.span_id}"/>
<!-- Manual changes: end -->
</layout>
</target>

<!-- For a custom layout, you must explicitly extract the 'dd.trace_id' and 'dd.span_id' values -->
<!--
Additions to layout: {traceId=&quot;${mdlc:item=dd.trace_id}&quot;,spanId=&quot;${mdlc:item=dd.span_id}&quot;}
-->
<!--
Parsing this log line with a custom Pipeline that adds Trace/Log correlation can be done with the following Processors:
1. Grok Parser: Set the parsing rules to `log_parser %{date("yyyy-MM-dd HH:mm:ss.SSSS"):time}\|%{word:level}\|%{notSpace:logger}\|\{%{data::keyvalue}}\|%{data:message}`
2. Trace Id Remapper: Set the trace_id attribute to 'trace_id'
-->
<target name="textFile" xsi:type="File" fileName="log-NLog46-textFile.log"
layout="${longdate}|${uppercase:${level}}|${logger}|{traceId=&quot;${mdlc:item=dd.trace_id}&quot;,spanId=&quot;${mdlc:item=dd.span_id}&quot;}|${message}" />
</targets>

<!-- rules to map from logger name to target -->
<rules>
<logger name="*" minlevel="Trace" writeTo="jsonFile-includeMdlc-true,jsonFile-includeMdlc-false,textFile" />
</rules>
</nlog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Datadog.Trace" Version="1.8.0" />
<PackageReference Include="NLog" Version="4.6.7" />
</ItemGroup>

<ItemGroup>
<None Update="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Datadog.Trace;
using NLog;

namespace NLog46Example
{
class Program
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

static void Main(string[] args)
{
using (MappedDiagnosticsLogicalContext.SetScoped("order-number", 1024))
{
Logger.Info("Message before a trace.");

using (var scope = Tracer.Instance.StartActive("NLog46Example - Main()"))
{
Logger.Info("Message during a trace.");
}

Logger.Info("Message after a trace.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"profiles": {
"NLog46Example": {
"commandName": "Project",
"environmentVariables": {
"DD_LOGS_INJECTION": "true"
},
"nativeDebugging": true
}
}
}
Loading

0 comments on commit 1709f7e

Please sign in to comment.