diff --git a/src/Elastic.CommonSchema.NLog/ActivityExtensions.cs b/src/Elastic.CommonSchema.NLog/ActivityExtensions.cs
new file mode 100644
index 00000000..f2805975
--- /dev/null
+++ b/src/Elastic.CommonSchema.NLog/ActivityExtensions.cs
@@ -0,0 +1,51 @@
+using System.Diagnostics;
+
+namespace Elastic.CommonSchema.NLog
+{
+ ///
+ /// Helpers for getting the right values from Activity no matter the format (w3c or hierarchical)
+ ///
+ internal static class ActivityExtensions
+ {
+ private static readonly ActivitySpanId EmptySpanId = default;
+ private static readonly ActivityTraceId EmptyTraceId = default;
+
+ public static string GetSpanId(this Activity activity) =>
+ activity.IdFormat == ActivityIdFormat.W3C ?
+ SpanIdToHexString(activity.SpanId) :
+ activity.Id;
+
+ public static string GetTraceId(this Activity activity) =>
+ activity.IdFormat == ActivityIdFormat.W3C ?
+ TraceIdToHexString(activity.TraceId) :
+ activity.RootId;
+
+ public static string GetParentId(this Activity activity) =>
+ activity.IdFormat == ActivityIdFormat.W3C ?
+ SpanIdToHexString(activity.ParentSpanId) :
+ activity.ParentId;
+
+ private static string SpanIdToHexString(ActivitySpanId spanId)
+ {
+ if (EmptySpanId.Equals(spanId))
+ return string.Empty;
+
+ var spanHexString = spanId.ToHexString();
+ if (ReferenceEquals(spanHexString, EmptySpanId.ToHexString()))
+ return string.Empty;
+
+ return spanHexString;
+ }
+
+ private static string TraceIdToHexString(ActivityTraceId traceId)
+ {
+ if (EmptyTraceId.Equals(traceId))
+ return string.Empty;
+
+ var traceHexString = traceId.ToHexString();
+ return ReferenceEquals(traceHexString, EmptyTraceId.ToHexString())
+ ? string.Empty
+ : traceHexString;
+ }
+ }
+}
diff --git a/src/Elastic.CommonSchema.NLog/EcsLayout.cs b/src/Elastic.CommonSchema.NLog/EcsLayout.cs
index d824040c..70e76be0 100644
--- a/src/Elastic.CommonSchema.NLog/EcsLayout.cs
+++ b/src/Elastic.CommonSchema.NLog/EcsLayout.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Runtime.Serialization;
using System.Text;
using System.Text.Json.Serialization;
@@ -21,6 +22,7 @@ internal class NlogEcsDocumentCreationOptions : IEcsDocumentCreationOptions
public bool IncludeHost { get; set; } = false;
public bool IncludeProcess { get; set; } = false;
public bool IncludeUser { get; set; } = false;
+ public bool IncludeTraceId { get; set; } = false;
}
/// An NLOG layout implementation that renders logs as ECS json
@@ -146,11 +148,11 @@ private static bool NLogWeb4Registered() =>
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
///
- public Layout ApmTraceId { get; set; }
+ public Layout ApmTraceId { get; set; } = FromMethod(_ => ResolveTraceId());
///
public Layout ApmTransactionId { get; set; }
///
- public Layout ApmSpanId { get; set; }
+ public Layout ApmSpanId { get; set; } = FromMethod(_ => ResolveSpanId());
///
public Layout ApmServiceName { get; set; }
@@ -775,6 +777,10 @@ private static void Populate(IDictionary propertyBag, string key
propertyBag.Add(usedKey, value);
}
+ private static string ResolveTraceId() => Activity.Current?.GetTraceId();
+
+ private static string ResolveSpanId() => Activity.Current?.GetSpanId();
+
///
/// A subclass of that adds additional properties related to Extensions logging.
/// For instance it adds scope information to each logged event
diff --git a/src/Elastic.CommonSchema.Serilog/EcsTextFormatterConfiguration.cs b/src/Elastic.CommonSchema.Serilog/EcsTextFormatterConfiguration.cs
index b67bccf7..4416119e 100644
--- a/src/Elastic.CommonSchema.Serilog/EcsTextFormatterConfiguration.cs
+++ b/src/Elastic.CommonSchema.Serilog/EcsTextFormatterConfiguration.cs
@@ -57,6 +57,9 @@ public class EcsTextFormatterConfiguration : IEcsTextFormatterConf
///
public bool IncludeUser { get; set; } = true;
+ ///
+ public bool IncludeTraceId { get; set; } = true;
+
///
public IHttpAdapter? MapHttpAdapter { get; set; }
diff --git a/src/Elastic.CommonSchema/EcsDocument.cs b/src/Elastic.CommonSchema/EcsDocument.cs
index 23fbb888..2fdb9ad6 100644
--- a/src/Elastic.CommonSchema/EcsDocument.cs
+++ b/src/Elastic.CommonSchema/EcsDocument.cs
@@ -34,6 +34,11 @@ public interface IEcsDocumentCreationOptions
/// Gets or sets a flag indicating whether user details should be included in the message. Defaults to true.
///
bool IncludeUser { get; set; }
+
+ ///
+ /// Gets or sets a flag indicating whether TraceId/SpanId should be included in the message. Defaults to true.
+ ///
+ bool IncludeTraceId { get; set; }
}
///
@@ -85,11 +90,12 @@ public static TEcsDocument CreateNewWithDefaults(
Error = GetError(exception),
Service = GetService(initialCache)
};
- SetActivityData(doc);
if (options?.IncludeHost is null or true) doc.Host = GetHost(initialCache);
if (options?.IncludeProcess is null or true) doc.Process = GetProcess(initialCache);
if (options?.IncludeUser is null or true) doc.User = GetUser();
+ if (options?.IncludeTraceId is null or true)
+ SetActivityData(doc);
return doc;
}
diff --git a/src/Elastic.Extensions.Logging/Options/ElasticsearchLoggerOptions.cs b/src/Elastic.Extensions.Logging/Options/ElasticsearchLoggerOptions.cs
index 35793e6b..40c547c5 100644
--- a/src/Elastic.Extensions.Logging/Options/ElasticsearchLoggerOptions.cs
+++ b/src/Elastic.Extensions.Logging/Options/ElasticsearchLoggerOptions.cs
@@ -29,6 +29,11 @@ public class ElasticsearchLoggerOptions : IEcsDocumentCreationOptions
///
public bool IncludeUser { get; set; } = true;
+ ///
+ /// Gets or sets a flag indicating whether TraceId/SpanId should be included in the message. Defaults to true.
+ ///
+ public bool IncludeTraceId { get; set; } = true;
+
///
/// The data stream to log into, defaults to logs-generic-default if neither or is set.
///