diff --git a/tracer/missing-nullability-files.csv b/tracer/missing-nullability-files.csv
index fb6d4823eb59..fc32fd2d4afc 100644
--- a/tracer/missing-nullability-files.csv
+++ b/tracer/missing-nullability-files.csv
@@ -24,8 +24,6 @@ src/Datadog.Trace/OSPlatformName.cs
src/Datadog.Trace/ProcessArchitecture.cs
src/Datadog.Trace/PropagationErrorTagValues.cs
src/Datadog.Trace/ReadOnlySpanContext.cs
-src/Datadog.Trace/SamplingPriority.cs
-src/Datadog.Trace/SamplingPriorityValues.cs
src/Datadog.Trace/Scope.cs
src/Datadog.Trace/Scope.IScope.cs
src/Datadog.Trace/Span.cs
@@ -85,7 +83,6 @@ src/Datadog.Trace/Ci/IEvent.cs
src/Datadog.Trace/ClrProfiler/AutomaticTracer.cs
src/Datadog.Trace/ClrProfiler/CallTargetKind.cs
src/Datadog.Trace/ClrProfiler/ClrNames.cs
-src/Datadog.Trace/ClrProfiler/CommonTracer.cs
src/Datadog.Trace/ClrProfiler/DistributedTracer.cs
src/Datadog.Trace/ClrProfiler/IAutomaticTracer.cs
src/Datadog.Trace/ClrProfiler/ICommonTracer.cs
@@ -198,20 +195,14 @@ src/Datadog.Trace/RuntimeMetrics/PerformanceCounterWrapper.cs
src/Datadog.Trace/RuntimeMetrics/RuntimeEventListener.cs
src/Datadog.Trace/RuntimeMetrics/RuntimeMetricsWriter.cs
src/Datadog.Trace/RuntimeMetrics/Timing.cs
-src/Datadog.Trace/Sampling/CustomSamplingRule.cs
-src/Datadog.Trace/Sampling/DefaultSamplingRule.cs
-src/Datadog.Trace/Sampling/GlobalSamplingRule.cs
src/Datadog.Trace/Sampling/IRateLimiter.cs
-src/Datadog.Trace/Sampling/ISamplingRule.cs
src/Datadog.Trace/Sampling/ISpanSamplingRule.cs
-src/Datadog.Trace/Sampling/ITraceSampler.cs
src/Datadog.Trace/Sampling/OverheadController.cs
src/Datadog.Trace/Sampling/RateLimiter.cs
src/Datadog.Trace/Sampling/SamplingMechanism.cs
src/Datadog.Trace/Sampling/SpanRateLimiter.cs
src/Datadog.Trace/Sampling/SpanSamplingRule.cs
src/Datadog.Trace/Sampling/TracerRateLimiter.cs
-src/Datadog.Trace/Sampling/TraceSampler.cs
src/Datadog.Trace/ServiceFabric/ServiceRemotingConstants.cs
src/Datadog.Trace/Tagging/AerospikeTags.cs
src/Datadog.Trace/Tagging/AspNetCoreEndpointTags.cs
diff --git a/tracer/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs b/tracer/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs
index 1b1f23dca72d..66dccc2dd058 100644
--- a/tracer/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs
+++ b/tracer/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
-using System.IO;
using System.Runtime.CompilerServices;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.Processors;
@@ -228,19 +227,24 @@ private int Serialize(ref byte[] bytes, int offset, in SpanModel spanModel)
private int WriteSpanLink(ref byte[] bytes, int offset, in SpanModel spanModel)
{
int originalOffset = offset;
+
offset += MessagePackBinary.WriteStringBytes(ref bytes, offset, _spanLinkBytes);
offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, spanModel.Span.SpanLinks.Count);
+
foreach (var spanLink in spanModel.Span.SpanLinks)
{
var context = spanLink.Context;
var samplingPriority = context.TraceContext?.SamplingPriority ?? context.SamplingPriority;
+
var traceFlags = samplingPriority switch
{
null => 0u, // not set
> 0 => 1u + (1u << 31), // keep
<= 0 => 1u << 31, // drop
};
+
var len = 3;
+
// check to serialize tracestate
if (context.IsRemote)
{
diff --git a/tracer/src/Datadog.Trace/Agent/MessagePack/TraceChunkModel.cs b/tracer/src/Datadog.Trace/Agent/MessagePack/TraceChunkModel.cs
index e7dce93f5c49..4f53674dc628 100644
--- a/tracer/src/Datadog.Trace/Agent/MessagePack/TraceChunkModel.cs
+++ b/tracer/src/Datadog.Trace/Agent/MessagePack/TraceChunkModel.cs
@@ -10,7 +10,6 @@
using System.Threading;
using Datadog.Trace.Configuration;
using Datadog.Trace.Tagging;
-using Datadog.Trace.Util;
namespace Datadog.Trace.Agent.MessagePack;
@@ -62,7 +61,7 @@ internal readonly struct TraceChunkModel
/// The spans that will be within this .
/// Optional sampling priority to override the sampling priority.
public TraceChunkModel(in ArraySegment spans, int? samplingPriority = null)
- : this(spans, GetTraceContext(spans), samplingPriority)
+ : this(spans, TraceContext.GetTraceContext(spans), samplingPriority)
{
// since all we have is an array of spans, use the trace context from the first span
// to get the other values we need (sampling priority, origin, trace tags, etc) for now.
@@ -78,19 +77,29 @@ private TraceChunkModel(in ArraySegment spans, TraceContext? traceContext,
if (traceContext is not null)
{
- DefaultServiceName = traceContext.Tracer?.DefaultServiceName;
SamplingPriority ??= traceContext.SamplingPriority;
+
Environment = traceContext.Environment;
ServiceVersion = traceContext.ServiceVersion;
Origin = traceContext.Origin;
Tags = traceContext.Tags;
- IsRunningInAzureAppService = traceContext.Tracer?.Settings?.IsRunningInAzureAppService ?? false;
- AzureAppServiceSettings = traceContext.Tracer?.Settings?.AzureAppServiceMetadata ?? null;
- if (traceContext.Tracer?.GitMetadataTagsProvider?.TryExtractGitMetadata(out var gitMetadata) == true &&
- gitMetadata != GitMetadata.Empty)
+
+ if (traceContext.Tracer is { } tracer)
{
- GitRepositoryUrl = gitMetadata.RepositoryUrl;
- GitCommitSha = gitMetadata.CommitSha;
+ DefaultServiceName = tracer.DefaultServiceName;
+
+ if (tracer.Settings is { } settings)
+ {
+ IsRunningInAzureAppService = settings.IsRunningInAzureAppService;
+ AzureAppServiceSettings = settings.AzureAppServiceMetadata ?? null;
+ }
+
+ if (tracer.GitMetadataTagsProvider?.TryExtractGitMetadata(out var gitMetadata) == true &&
+ gitMetadata != GitMetadata.Empty)
+ {
+ GitRepositoryUrl = gitMetadata.RepositoryUrl;
+ GitCommitSha = gitMetadata.CommitSha;
+ }
}
}
}
@@ -121,16 +130,6 @@ internal TraceChunkModel(in ArraySegment spans, Span? localRootSpan)
// used in tests
internal bool HashSetInitialized => _hashSet?.IsValueCreated == true && _hashSet.Value.Count > 0;
- private static TraceContext? GetTraceContext(in ArraySegment spans)
- {
- if (spans.Count > 0)
- {
- return spans.Array![spans.Offset].Context.TraceContext;
- }
-
- return null;
- }
-
public SpanModel GetSpanModel(int spanIndex)
{
if (spanIndex >= _spans.Count)
diff --git a/tracer/src/Datadog.Trace/Ci/Test.cs b/tracer/src/Datadog.Trace/Ci/Test.cs
index 9877f741fd82..53383b42fdcb 100644
--- a/tracer/src/Datadog.Trace/Ci/Test.cs
+++ b/tracer/src/Datadog.Trace/Ci/Test.cs
@@ -51,7 +51,7 @@ internal Test(TestSuite suite, string name, DateTimeOffset? startDate, TraceId t
scope.Span.Type = SpanTypes.Test;
scope.Span.ResourceName = $"{suite.Name}.{name}";
- scope.Span.Context.TraceContext.SetSamplingPriority((int)SamplingPriority.AutoKeep, SamplingMechanism.Manual);
+ scope.Span.Context.TraceContext.SetSamplingPriority(SamplingPriorityValues.AutoKeep, SamplingMechanism.Manual);
scope.Span.Context.TraceContext.Origin = TestTags.CIAppTestOriginName;
TelemetryFactory.Metrics.RecordCountSpanCreated(MetricTags.IntegrationName.CiAppManual);
diff --git a/tracer/src/Datadog.Trace/Ci/TestModule.cs b/tracer/src/Datadog.Trace/Ci/TestModule.cs
index b3441bc513eb..5ab33ae8f408 100644
--- a/tracer/src/Datadog.Trace/Ci/TestModule.cs
+++ b/tracer/src/Datadog.Trace/Ci/TestModule.cs
@@ -172,7 +172,7 @@ internal TestModule(string name, string? framework, string? frameworkVersion, Da
span.Type = SpanTypes.TestModule;
span.ResourceName = name;
- span.Context.TraceContext.SetSamplingPriority((int)SamplingPriority.AutoKeep);
+ span.Context.TraceContext.SetSamplingPriority(SamplingPriorityValues.AutoKeep);
span.Context.TraceContext.Origin = TestTags.CIAppTestOriginName;
tags.ModuleId = span.SpanId;
diff --git a/tracer/src/Datadog.Trace/Ci/TestSession.cs b/tracer/src/Datadog.Trace/Ci/TestSession.cs
index f72bad32bd4a..f2ba5acce8f8 100644
--- a/tracer/src/Datadog.Trace/Ci/TestSession.cs
+++ b/tracer/src/Datadog.Trace/Ci/TestSession.cs
@@ -61,7 +61,7 @@ private TestSession(string? command, string? workingDirectory, string? framework
span.Type = SpanTypes.TestSession;
span.ResourceName = $"{span.OperationName}.{command}";
- span.Context.TraceContext.SetSamplingPriority((int)SamplingPriority.AutoKeep);
+ span.Context.TraceContext.SetSamplingPriority(SamplingPriorityValues.AutoKeep);
span.Context.TraceContext.Origin = TestTags.CIAppTestOriginName;
tags.SessionId = span.SpanId;
diff --git a/tracer/src/Datadog.Trace/Ci/TestSuite.cs b/tracer/src/Datadog.Trace/Ci/TestSuite.cs
index 5b7add69624a..9e0f9c2ac209 100644
--- a/tracer/src/Datadog.Trace/Ci/TestSuite.cs
+++ b/tracer/src/Datadog.Trace/Ci/TestSuite.cs
@@ -38,7 +38,7 @@ internal TestSuite(TestModule module, string name, DateTimeOffset? startDate)
span.Type = SpanTypes.TestSuite;
span.ResourceName = name;
- span.Context.TraceContext.SetSamplingPriority((int)SamplingPriority.AutoKeep);
+ span.Context.TraceContext.SetSamplingPriority(SamplingPriorityValues.AutoKeep);
span.Context.TraceContext.Origin = TestTags.CIAppTestOriginName;
tags.SuiteId = span.SpanId;
diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Grpc/GrpcLegacy/Client/GrpcLegacyClientCommon.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Grpc/GrpcLegacy/Client/GrpcLegacyClientCommon.cs
index 0dc2961f7548..5b09a9c4b43b 100644
--- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Grpc/GrpcLegacy/Client/GrpcLegacyClientCommon.cs
+++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Grpc/GrpcLegacy/Client/GrpcLegacyClientCommon.cs
@@ -81,9 +81,9 @@ internal static class GrpcLegacyClientCommon
span.SetHeaderTags(requestMetadataWrapper, tracer.Settings.GrpcTagsInternal, GrpcCommon.RequestMetadataTagPrefix);
scope = tracer.ActivateSpan(span);
- if (setSamplingPriority && existingSpanContext?.SamplingPriority is not null)
+ if (setSamplingPriority && existingSpanContext?.SamplingPriority is { } samplingPriority)
{
- span.Context.TraceContext?.SetSamplingPriority(existingSpanContext.SamplingPriority.Value);
+ span.Context.TraceContext?.SetSamplingPriority(samplingPriority);
}
GrpcCommon.RecordFinalStatus(span, receivedStatus.StatusCode, receivedStatus.Detail, receivedStatus.DebugException);
@@ -242,10 +242,10 @@ private static Span CreateInactiveSpan(Tracer tracer, string? methodFullName)
var operationName = tracer.CurrentTraceSettings.Schema.Client.GetOperationNameForProtocol("grpc");
var serviceName = tracer.CurrentTraceSettings.Schema.Client.GetServiceName(component: "grpc-client");
var tags = tracer.CurrentTraceSettings.Schema.Client.CreateGrpcClientTags();
- var span = tracer.StartSpan(operationName, tags, serviceName: serviceName, addToTraceContext: false);
tags.SetAnalyticsSampleRate(IntegrationId.Grpc, tracer.Settings, enabledWithGlobalSetting: false);
tracer.CurrentTraceSettings.Schema.RemapPeerService(tags);
+ var span = tracer.StartSpan(operationName, tags, serviceName: serviceName, addToTraceContext: false);
span.Type = SpanTypes.Grpc;
span.ResourceName = methodFullName;
diff --git a/tracer/src/Datadog.Trace/ClrProfiler/CommonTracer.cs b/tracer/src/Datadog.Trace/ClrProfiler/CommonTracer.cs
index 0c61cc67d1af..b4defa7f7298 100644
--- a/tracer/src/Datadog.Trace/ClrProfiler/CommonTracer.cs
+++ b/tracer/src/Datadog.Trace/ClrProfiler/CommonTracer.cs
@@ -3,7 +3,7 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
-using Datadog.Trace.Sampling;
+#nullable enable
namespace Datadog.Trace.ClrProfiler
{
diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.AzureAppService.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.AzureAppService.cs
index e7c055d72caa..f2959e5234d5 100644
--- a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.AzureAppService.cs
+++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.AzureAppService.cs
@@ -67,7 +67,7 @@ internal class AzureAppService
internal const string OperatingSystemKey = "WEBSITE_OS";
///
- /// Used to force the loader to start the tracer agent (in case automatic instrumentation is disabled)
+ /// Used to force the loader to start the trace agent (in case automatic instrumentation is disabled)
///
public const string AasEnableCustomTracing = "DD_AAS_ENABLE_CUSTOM_TRACING";
diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DynamicConfigConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DynamicConfigConfigurationSource.cs
index a6d86baa8e20..9cf530e4dd3b 100644
--- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DynamicConfigConfigurationSource.cs
+++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DynamicConfigConfigurationSource.cs
@@ -15,7 +15,7 @@ namespace Datadog.Trace.Configuration.ConfigurationSources
{
internal class DynamicConfigConfigurationSource : JsonConfigurationSource
{
- private static readonly IReadOnlyDictionary Mapping = new Dictionary
+ private static readonly Dictionary Mapping = new()
{
{ ConfigurationKeys.TraceEnabled, "tracing_enabled" },
// { ConfigurationKeys.DebugEnabled, "tracing_debug" },
@@ -48,17 +48,17 @@ internal DynamicConfigConfigurationSource(string json, ConfigurationOrigins orig
return jobject;
}
- private static IDictionary ReadHeaderTags(JToken token)
+ private static Dictionary ReadHeaderTags(JToken token)
{
return ((JArray)token).ToDictionary(t => t["header"]!.Value()!, t => t["tag_name"]!.Value()!);
}
- private static IDictionary ReadServiceMapping(JToken token)
+ private static Dictionary ReadServiceMapping(JToken token)
{
return ((JArray)token).ToDictionary(t => t["from_key"]!.Value()!, t => t["to_name"]!.Value()!);
}
- private static IDictionary ReadGlobalTags(JToken token)
+ private static Dictionary ReadGlobalTags(JToken token)
{
var result = new Dictionary();
diff --git a/tracer/src/Datadog.Trace/Configuration/PerTraceSettings.cs b/tracer/src/Datadog.Trace/Configuration/PerTraceSettings.cs
index 2deff37388b4..a0ac5202a0e1 100644
--- a/tracer/src/Datadog.Trace/Configuration/PerTraceSettings.cs
+++ b/tracer/src/Datadog.Trace/Configuration/PerTraceSettings.cs
@@ -52,16 +52,5 @@ internal string GetServiceName(Tracer tracer, string serviceName)
return finalServiceName;
}
-
- internal bool TryGetServiceName(string key, out string? serviceName)
- {
- if (ServiceNames.TryGetValue(key, out serviceName))
- {
- return true;
- }
-
- serviceName = null;
- return false;
- }
}
}
diff --git a/tracer/src/Datadog.Trace/Propagators/B3MultipleHeaderContextPropagator.cs b/tracer/src/Datadog.Trace/Propagators/B3MultipleHeaderContextPropagator.cs
index edfd12bf738b..cdecbb961a80 100644
--- a/tracer/src/Datadog.Trace/Propagators/B3MultipleHeaderContextPropagator.cs
+++ b/tracer/src/Datadog.Trace/Propagators/B3MultipleHeaderContextPropagator.cs
@@ -73,9 +73,11 @@ public bool TryExtract(TCarrier carrier, TCarrierGette
internal static void CreateHeaders(SpanContext context, out string traceId, out string spanId, out string sampled)
{
- var samplingPriority = context.TraceContext?.SamplingPriority ?? context.SamplingPriority;
- sampled = samplingPriority > 0 ? "1" : "0";
+ // BUG: we should fall back to SamplingPriorityValues.AutoKeep
+ var samplingPriority = context.TraceContext?.SamplingPriority ??
+ context.SamplingPriority; // should never happen in production, but some tests rely on this
+ sampled = SamplingPriorityValues.IsKeep(samplingPriority) ? "1" : "0";
traceId = context.RawTraceId;
spanId = context.RawSpanId;
}
diff --git a/tracer/src/Datadog.Trace/Propagators/B3SingleHeaderContextPropagator.cs b/tracer/src/Datadog.Trace/Propagators/B3SingleHeaderContextPropagator.cs
index 66921bb5ec1d..2b09e16eec0c 100644
--- a/tracer/src/Datadog.Trace/Propagators/B3SingleHeaderContextPropagator.cs
+++ b/tracer/src/Datadog.Trace/Propagators/B3SingleHeaderContextPropagator.cs
@@ -139,8 +139,11 @@ public bool TryExtract(TCarrier carrier, TCarrierGette
internal static string CreateHeader(SpanContext context)
{
- var samplingPriority = context.TraceContext?.SamplingPriority ?? context.SamplingPriority;
- var sampled = samplingPriority > 0 ? "1" : "0";
+ // BUG: we should fall back to SamplingPriorityValues.AutoKeep
+ var samplingPriority = context.TraceContext?.SamplingPriority ??
+ context.SamplingPriority; // should never happen in production, but some tests rely on this
+
+ var sampled = SamplingPriorityValues.IsKeep(samplingPriority) ? "1" : "0";
#if NET6_0_OR_GREATER
return string.Create(null, stackalloc char[128], $"{context.RawTraceId}-{context.RawSpanId}-{sampled}");
diff --git a/tracer/src/Datadog.Trace/Propagators/DatadogContextPropagator.cs b/tracer/src/Datadog.Trace/Propagators/DatadogContextPropagator.cs
index e3337a4545ad..b83567720d8d 100644
--- a/tracer/src/Datadog.Trace/Propagators/DatadogContextPropagator.cs
+++ b/tracer/src/Datadog.Trace/Propagators/DatadogContextPropagator.cs
@@ -36,19 +36,12 @@ public void Inject(SpanContext context, TCarrier carri
carrierSetter.Set(carrier, HttpHeaderNames.Origin, context.Origin);
}
- var samplingPriority = context.TraceContext?.SamplingPriority ?? context.SamplingPriority;
+ var samplingPriority = context.TraceContext?.SamplingPriority ??
+ context.SamplingPriority; // should never happen in production, but some tests rely on this
if (samplingPriority != null)
{
- var samplingPriorityString = samplingPriority.Value switch
- {
- -1 => "-1",
- 0 => "0",
- 1 => "1",
- 2 => "2",
- _ => samplingPriority.Value.ToString(invariantCulture)
- };
-
+ var samplingPriorityString = SamplingPriorityValues.ToString(samplingPriority);
carrierSetter.Set(carrier, HttpHeaderNames.SamplingPriority, samplingPriorityString);
}
diff --git a/tracer/src/Datadog.Trace/Propagators/SpanContextPropagator.cs b/tracer/src/Datadog.Trace/Propagators/SpanContextPropagator.cs
index a4c7000b52f7..486e16269fd7 100644
--- a/tracer/src/Datadog.Trace/Propagators/SpanContextPropagator.cs
+++ b/tracer/src/Datadog.Trace/Propagators/SpanContextPropagator.cs
@@ -11,7 +11,6 @@
using System.Linq;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.Headers;
-using Datadog.Trace.Util;
namespace Datadog.Trace.Propagators
{
diff --git a/tracer/src/Datadog.Trace/Propagators/W3CTraceContextPropagator.cs b/tracer/src/Datadog.Trace/Propagators/W3CTraceContextPropagator.cs
index 27f408f00394..cf6bb3104285 100644
--- a/tracer/src/Datadog.Trace/Propagators/W3CTraceContextPropagator.cs
+++ b/tracer/src/Datadog.Trace/Propagators/W3CTraceContextPropagator.cs
@@ -8,7 +8,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
using Datadog.Trace.SourceGenerators;
@@ -119,6 +118,7 @@ public void Inject(SpanContext context, TCarrier carri
where TCarrierSetter : struct, ICarrierSetter
{
TelemetryFactory.Metrics.RecordCountContextHeaderStyleInjected(MetricTags.ContextHeaderStyle.TraceContext);
+
var traceparent = CreateTraceParentHeader(context);
carrierSetter.Set(carrier, TraceParentHeaderName, traceparent);
@@ -132,8 +132,12 @@ public void Inject(SpanContext context, TCarrier carri
internal static string CreateTraceParentHeader(SpanContext context)
{
- var samplingPriority = context.TraceContext?.SamplingPriority ?? context.SamplingPriority ?? SamplingPriorityValues.AutoKeep;
- var sampled = samplingPriority > 0 ? "01" : "00";
+ var samplingPriority = context.TraceContext?.SamplingPriority ??
+ context.SamplingPriority ?? // should never happen in production, but some tests rely on this
+ SamplingPriorityValues.AutoKeep; // fallback
+
+ var sampled = SamplingPriorityValues.IsKeep(samplingPriority) ? "01" : "00";
+
#if NET6_0_OR_GREATER
return string.Create(null, stackalloc char[128], $"00-{context.RawTraceId}-{context.RawSpanId}-{sampled}");
#else
@@ -150,11 +154,9 @@ internal static string CreateTraceStateHeader(SpanContext context)
sb.Append("dd=");
// sampling priority ("s:")
- var samplingPriority = SamplingPriorityToString(context.TraceContext?.SamplingPriority);
-
- if (samplingPriority != null)
+ if (context.TraceContext?.SamplingPriority is { } samplingPriority)
{
- sb.Append("s:").Append(samplingPriority).Append(TraceStateDatadogPairsSeparator);
+ sb.Append("s:").Append(SamplingPriorityValues.ToString(samplingPriority)).Append(TraceStateDatadogPairsSeparator);
}
// origin ("o:")
@@ -563,20 +565,6 @@ internal static void SplitTraceStateValues(string header, out string? ddValues,
}
}
- [return: NotNullIfNotNull("samplingPriority")]
- private static string? SamplingPriorityToString(int? samplingPriority)
- {
- return samplingPriority switch
- {
- 2 => "2",
- 1 => "1",
- 0 => "0",
- -1 => "-1",
- null => null,
- not null => samplingPriority.Value.ToString(CultureInfo.InvariantCulture)
- };
- }
-
#if NETCOREAPP
private static int? SamplingPriorityToInt32(ReadOnlySpan samplingPriority)
{
diff --git a/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RcmCapabilitiesIndices.cs b/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RcmCapabilitiesIndices.cs
index f3293e7c35a2..01a56dcdae2f 100644
--- a/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RcmCapabilitiesIndices.cs
+++ b/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RcmCapabilitiesIndices.cs
@@ -49,6 +49,26 @@ internal static class RcmCapabilitiesIndices
public static readonly BigInteger ApmTracingTracingEnabled = Create(19);
+ public static readonly BigInteger ApmTracingDataStreamsEnabled = Create(20);
+
+ public static readonly BigInteger AsmRaspSqli = Create(21);
+
+ public static readonly BigInteger AsmRaspLfi = Create(22);
+
+ public static readonly BigInteger AsmRaspSsrf = Create(23);
+
+ public static readonly BigInteger AsmRaspShi = Create(24);
+
+ public static readonly BigInteger AsmRaspXxe = Create(25);
+
+ public static readonly BigInteger AsmRaspRce = Create(26);
+
+ public static readonly BigInteger AsmRaspNosqli = Create(27);
+
+ public static readonly BigInteger AsmRaspXss = Create(28);
+
+ public static readonly BigInteger ApmTracingSampleRules = Create(29);
+
private static BigInteger Create(int index) => new(1UL << index);
}
}
diff --git a/tracer/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs b/tracer/src/Datadog.Trace/Sampling/AgentSamplingRule.cs
similarity index 85%
rename from tracer/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs
rename to tracer/src/Datadog.Trace/Sampling/AgentSamplingRule.cs
index ae7b79b05563..753d7f923f83 100644
--- a/tracer/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs
+++ b/tracer/src/Datadog.Trace/Sampling/AgentSamplingRule.cs
@@ -1,8 +1,10 @@
-//
+//
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
using System;
using System.Collections.Generic;
using Datadog.Trace.Logging;
@@ -13,16 +15,14 @@ namespace Datadog.Trace.Sampling
{
// These "default" sampling rule contains the mapping of service/env names to sampling rates.
// These rates are received in http responses from the trace agent after we send a trace payload.
- internal class DefaultSamplingRule : ISamplingRule
+ internal class AgentSamplingRule : ISamplingRule
{
private const string DefaultKey = "service:,env:";
- private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor();
+ private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor();
private Dictionary _sampleRates = new();
private float? _defaultSamplingRate;
- public string RuleName => "default-rule";
-
// if there are no rules, this normally means we haven't sent any payloads to the Agent yet (aka cold start), so the mechanism is "Default".
// if there are rules, there should always be at least one match (the fallback "service:,env:") and the mechanism is "AgentRate".
public int SamplingMechanism => _sampleRates.Count == 0 && _defaultSamplingRate == null ?
@@ -34,10 +34,7 @@ internal class DefaultSamplingRule : ISamplingRule
///
public int Priority => int.MinValue;
- public bool IsMatch(Span span)
- {
- return true;
- }
+ public bool IsMatch(Span span) => true;
public float GetSamplingRate(Span span)
{
@@ -49,18 +46,20 @@ public float GetSamplingRate(Span span)
// either we don't have sampling rate from the agent yet (cold start),
// or the only rate we received is for "service:,env:", which is not added to _sampleRates
defaultRate = _defaultSamplingRate ?? 1;
- SetSamplingAgentDecision(span, defaultRate); // Keep it to ease investigations
+
+ // add the _dd.agent_psr tag even if we didn't use rates from the agent (to ease investigations)
+ SetSamplingRateTag(span, defaultRate);
return defaultRate;
}
- var env = span.Context.TraceContext.Environment;
+ var env = span.Context.TraceContext.Environment ?? string.Empty;
var service = span.ServiceName;
var key = new SampleRateKey(service, env);
if (_sampleRates.TryGetValue(key, out var sampleRate))
{
- SetSamplingAgentDecision(span, sampleRate);
+ SetSamplingRateTag(span, sampleRate);
return sampleRate;
}
@@ -69,11 +68,12 @@ public float GetSamplingRate(Span span)
Log.Debug("Could not establish sample rate for trace {TraceId}. Using default rate instead: {Rate}", span.Context.RawTraceId, _defaultSamplingRate);
}
+ // no match by service/env, you default rate
defaultRate = _defaultSamplingRate ?? 1;
- SetSamplingAgentDecision(span, defaultRate);
+ SetSamplingRateTag(span, defaultRate);
return defaultRate;
- static void SetSamplingAgentDecision(Span span, float sampleRate)
+ static void SetSamplingRateTag(Span span, float sampleRate)
{
if (span.Tags is CommonTags commonTags)
{
@@ -88,7 +88,7 @@ static void SetSamplingAgentDecision(Span span, float sampleRate)
public void SetDefaultSampleRates(IReadOnlyDictionary sampleRates)
{
- if (sampleRates is null || sampleRates.Count == 0)
+ if (sampleRates is not { Count: > 0 })
{
Log.Debug("sampling rates received from the agent are empty");
return;
@@ -122,10 +122,15 @@ public void SetDefaultSampleRates(IReadOnlyDictionary sampleRates
_sampleRates = rates;
}
+ public override string ToString()
+ {
+ return "AgentSamplingRates";
+ }
+
private readonly struct SampleRateKey : IEquatable
{
- private static readonly char[] PartSeparator = new[] { ',' };
- private static readonly char[] ValueSeparator = new[] { ':' };
+ private static readonly char[] PartSeparator = [','];
+ private static readonly char[] ValueSeparator = [':'];
private readonly string _service;
private readonly string _env;
@@ -169,7 +174,7 @@ public bool Equals(SampleRateKey other)
return _service == other._service && _env == other._env;
}
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
return obj is SampleRateKey other && Equals(other);
}
diff --git a/tracer/src/Datadog.Trace/Sampling/CustomSamplingRule.cs b/tracer/src/Datadog.Trace/Sampling/CustomSamplingRule.cs
index ad6fdf455a6a..762e027df88d 100644
--- a/tracer/src/Datadog.Trace/Sampling/CustomSamplingRule.cs
+++ b/tracer/src/Datadog.Trace/Sampling/CustomSamplingRule.cs
@@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
@@ -19,25 +21,23 @@ internal class CustomSamplingRule : ISamplingRule
private readonly bool _alwaysMatch;
// TODO consider moving toward these https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/Text/SimpleRegex.cs
- private readonly Regex _serviceNameRegex;
- private readonly Regex _operationNameRegex;
- private readonly Regex _resourceNameRegex;
- private readonly List> _tagRegexes;
+ private readonly Regex? _serviceNameRegex;
+ private readonly Regex? _operationNameRegex;
+ private readonly Regex? _resourceNameRegex;
+ private readonly List>? _tagRegexes;
private bool _regexTimedOut;
public CustomSamplingRule(
float rate,
- string ruleName,
string patternFormat,
- string serviceNamePattern,
- string operationNamePattern,
- string resourceNamePattern,
- ICollection> tagPatterns,
+ string? serviceNamePattern,
+ string? operationNamePattern,
+ string? resourceNamePattern,
+ ICollection>? tagPatterns,
TimeSpan timeout)
{
_samplingRate = rate;
- RuleName = ruleName;
_serviceNameRegex = RegexBuilder.Build(serviceNamePattern, patternFormat, timeout);
_operationNameRegex = RegexBuilder.Build(operationNamePattern, patternFormat, timeout);
@@ -54,15 +54,13 @@ _resourceNameRegex is null &&
}
}
- public string RuleName { get; }
-
public int SamplingMechanism => Datadog.Trace.Sampling.SamplingMechanism.TraceSamplingRule;
///
- /// Gets or sets the priority of the rule.
+ /// Gets the priority of the rule.
/// Configuration rules will default to 1 as a priority and rely on order of specification.
///
- public int Priority { get; protected set; } = 1;
+ public int Priority => 1;
public static IEnumerable BuildFromConfigurationString(string configuration, string patternFormat, TimeSpan timeout)
{
@@ -71,23 +69,19 @@ public static IEnumerable BuildFromConfigurationString(strin
if (!string.IsNullOrWhiteSpace(configuration) &&
JsonConvert.DeserializeObject>(configuration) is { Count: > 0 } rules)
{
- var index = 0;
var samplingRules = new List(rules.Count);
foreach (var r in rules)
{
- index++; // Used to create a readable rule name if one is not specified
-
samplingRules.Add(
new CustomSamplingRule(
- r.SampleRate,
- r.RuleName ?? $"config-rule-{index}",
- patternFormat,
- r.Service,
- r.OperationName,
- r.Resource,
- r.Tags,
- timeout));
+ rate: r.SampleRate,
+ patternFormat: patternFormat,
+ serviceNamePattern: r.Service,
+ operationNamePattern: r.OperationName,
+ resourceNamePattern: r.Resource,
+ tagPatterns: r.Tags,
+ timeout: timeout));
}
return samplingRules;
@@ -135,27 +129,31 @@ public float GetSamplingRate(Span span)
return _samplingRate;
}
- [Serializable]
- private class CustomRuleConfig
+ public override string ToString()
{
- [JsonProperty(PropertyName = "rule_name")]
- public string RuleName { get; set; }
+ // later this will return different values depending on the rule's provenance:
+ // local, customer (remote), or dynamic (remote)
+ return "LocalSamplingRule";
+ }
+ // ReSharper disable once ClassNeverInstantiated.Local
+ private class CustomRuleConfig
+ {
[JsonRequired]
[JsonProperty(PropertyName = "sample_rate")]
public float SampleRate { get; set; }
[JsonProperty(PropertyName = "name")]
- public string OperationName { get; set; }
+ public string? OperationName { get; set; }
[JsonProperty(PropertyName = "service")]
- public string Service { get; set; }
+ public string? Service { get; set; }
[JsonProperty(PropertyName = "resource")]
- public string Resource { get; set; }
+ public string? Resource { get; set; }
[JsonProperty(PropertyName = "tags")]
- public Dictionary Tags { get; set; }
+ public Dictionary? Tags { get; set; }
}
}
}
diff --git a/tracer/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs b/tracer/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs
index 5dbf84e6c90e..1a6b84f99b88 100644
--- a/tracer/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs
+++ b/tracer/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs
@@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
using Datadog.Trace.Logging;
namespace Datadog.Trace.Sampling
@@ -18,8 +20,6 @@ public GlobalSamplingRule(float rate)
_globalRate = rate;
}
- public string RuleName => "global-rate-rule";
-
///
/// Gets the priority which is one beneath custom rules.
///
@@ -27,16 +27,19 @@ public GlobalSamplingRule(float rate)
public int SamplingMechanism => Datadog.Trace.Sampling.SamplingMechanism.TraceSamplingRule;
- public bool IsMatch(Span span)
- {
- return true;
- }
+ public bool IsMatch(Span span) => true;
public float GetSamplingRate(Span span)
{
Log.Debug("Using the global sampling rate: {Rate}", _globalRate);
+
span.SetMetric(Metrics.SamplingRuleDecision, _globalRate);
return _globalRate;
}
+
+ public override string ToString()
+ {
+ return "GlobalSamplingRate";
+ }
}
}
diff --git a/tracer/src/Datadog.Trace/Sampling/ISamplingRule.cs b/tracer/src/Datadog.Trace/Sampling/ISamplingRule.cs
index 3bc995dab7ad..2a772a2fa0a0 100644
--- a/tracer/src/Datadog.Trace/Sampling/ISamplingRule.cs
+++ b/tracer/src/Datadog.Trace/Sampling/ISamplingRule.cs
@@ -3,16 +3,12 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
namespace Datadog.Trace.Sampling
{
internal interface ISamplingRule
{
- ///
- /// Gets the rule name.
- /// Used for debugging purposes mostly.
- ///
- string RuleName { get; }
-
///
/// Gets the rule priority.
/// Higher number means higher priority.
diff --git a/tracer/src/Datadog.Trace/Sampling/ITraceSampler.cs b/tracer/src/Datadog.Trace/Sampling/ITraceSampler.cs
index 797138f4fb79..ae19d435f79d 100644
--- a/tracer/src/Datadog.Trace/Sampling/ITraceSampler.cs
+++ b/tracer/src/Datadog.Trace/Sampling/ITraceSampler.cs
@@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
using System.Collections.Generic;
namespace Datadog.Trace.Sampling
diff --git a/tracer/src/Datadog.Trace/Sampling/RegexBuilder.cs b/tracer/src/Datadog.Trace/Sampling/RegexBuilder.cs
index d95d442e0249..a0943cae0254 100644
--- a/tracer/src/Datadog.Trace/Sampling/RegexBuilder.cs
+++ b/tracer/src/Datadog.Trace/Sampling/RegexBuilder.cs
@@ -64,7 +64,7 @@ internal static class RegexBuilder
}
}
- public static List> Build(ICollection> patterns, string format, TimeSpan timeout)
+ public static List> Build(ICollection>? patterns, string format, TimeSpan timeout)
{
if (patterns is { Count: > 0 })
{
diff --git a/tracer/src/Datadog.Trace/Sampling/SamplingDecision.cs b/tracer/src/Datadog.Trace/Sampling/SamplingDecision.cs
index 6862426fb02e..4c3e61eea437 100644
--- a/tracer/src/Datadog.Trace/Sampling/SamplingDecision.cs
+++ b/tracer/src/Datadog.Trace/Sampling/SamplingDecision.cs
@@ -14,7 +14,7 @@ internal readonly struct SamplingDecision
/// or no sampling rules match. For example, this value is used if the tracer has not yet
/// received any sampling rates from agent and there are no configured sampling rates.
///
- public static SamplingDecision Default = new(SamplingPriorityValues.AutoKeep, SamplingMechanism.Default);
+ public static SamplingDecision Default = new(SamplingPriorityValues.Default, SamplingMechanism.Default);
public readonly int Priority;
diff --git a/tracer/src/Datadog.Trace/Sampling/SamplingMechanism.cs b/tracer/src/Datadog.Trace/Sampling/SamplingMechanism.cs
index 9f7eee63c90c..4372eada56ef 100644
--- a/tracer/src/Datadog.Trace/Sampling/SamplingMechanism.cs
+++ b/tracer/src/Datadog.Trace/Sampling/SamplingMechanism.cs
@@ -3,6 +3,7 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+using System;
using System.Globalization;
namespace Datadog.Trace.Sampling;
@@ -32,6 +33,7 @@ internal static class SamplingMechanism
/// and (1).
/// (Reserved for future use.)
///
+ [Obsolete("This value is reserved for future use.")]
public const int RemoteRateAuto = 2;
///
@@ -61,12 +63,14 @@ internal static class SamplingMechanism
/// and (2).
/// (Reserved for future use.)
///
+ [Obsolete("This value is reserved for future use.")]
public const int RemoteRateUser = 6;
///
/// A sampling decision was made using a sampling rule configured remotely by Datadog.
/// (Reserved for future use.)
///
+ [Obsolete("This value is reserved for future use.")]
public const int RemoteRateDatadog = 7;
///
@@ -75,14 +79,38 @@ internal static class SamplingMechanism
///
public const int SpanSamplingRule = 8;
+ ///
+ /// A sampling decision was made using the OTLP-compatible probabilistic sampling in the Agent.
+ ///
+ [Obsolete("This value is used in the trace agent, not in tracing libraries.")]
+ public const int OtlpIngestProbabilisticSampling = 9;
+
+ ///
+ /// Traces coming from spark/databricks workload tracing
+ ///
+ public const int DataJobsMonitoring = 10;
+
+ ///
+ /// A sampling decision was made using a trace sampling rule that was configured remotely by the user
+ /// and sent via remote configuration (RCM).
+ /// The available sampling priorities are (-1)
+ /// and (2).
+ ///
+ public const int RemoteUserSamplingRule = 11;
+
+ ///
+ /// A sampling decision was made using a trace sampling rule that was computed remotely by Datadog
+ /// and sent via remote configuration (RCM).
+ /// The available sampling priorities are (-1)
+ /// and (2).
+ ///
+ public const int RemoteAdaptiveSamplingRule = 12;
+
public static string GetTagValue(int mechanism)
{
- // set the sampling mechanism trace tag
- // * only set tag if priority is AUTO_KEEP (1) or USER_KEEP (2)
- // * do not overwrite an existing value
- // * don't set tag if sampling mechanism is unknown (null)
- // * the "-" prefix is a left-over separator from a previous iteration of this feature (not a typo or a negative sign)
-
+ // the "-" prefix is a left-over separator from a previous iteration of this feature
+ // (not a negative sign)
+#pragma warning disable CS0618 // Type or member is obsolete
return mechanism switch
{
Default => "-0",
@@ -94,7 +122,14 @@ public static string GetTagValue(int mechanism)
RemoteRateUser => "-6",
RemoteRateDatadog => "-7",
SpanSamplingRule => "-8",
+ OtlpIngestProbabilisticSampling => "-9",
+ DataJobsMonitoring => "-10",
+ RemoteUserSamplingRule => "-11",
+ RemoteAdaptiveSamplingRule => "-12",
+
+ // forwards-compatibility for future values
_ => $"-{mechanism.ToString(CultureInfo.InvariantCulture)}"
};
+#pragma warning restore CS0618 // Type or member is obsolete
}
}
diff --git a/tracer/src/Datadog.Trace/Sampling/TraceSampler.cs b/tracer/src/Datadog.Trace/Sampling/TraceSampler.cs
index a8567e385d6d..65fdadc28f42 100644
--- a/tracer/src/Datadog.Trace/Sampling/TraceSampler.cs
+++ b/tracer/src/Datadog.Trace/Sampling/TraceSampler.cs
@@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
using System.Collections.Generic;
using Datadog.Trace.Logging;
using Datadog.Trace.Util;
@@ -15,7 +17,7 @@ internal class TraceSampler : ITraceSampler
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor();
private readonly IRateLimiter _limiter;
- private readonly DefaultSamplingRule _defaultRule = new();
+ private readonly AgentSamplingRule _defaultRule = new();
private readonly List _rules = new();
public TraceSampler(IRateLimiter limiter)
@@ -42,8 +44,8 @@ public SamplingDecision MakeSamplingDecision(Span span)
if (Log.IsEnabled(LogEventLevel.Debug))
{
Log.Debug(
- "Matched on rule {RuleName}. Applying rate of {Rate} to trace id {TraceId}",
- rule.RuleName,
+ "Matched on rule {Rule}. Applying rate of {Rate} to trace id {TraceId}",
+ rule,
sampleRate,
span.Context.RawTraceId);
}
diff --git a/tracer/src/Datadog.Trace/SamplingPriority.cs b/tracer/src/Datadog.Trace/SamplingPriority.cs
index ca1870ba43eb..3b6804d3dc5a 100644
--- a/tracer/src/Datadog.Trace/SamplingPriority.cs
+++ b/tracer/src/Datadog.Trace/SamplingPriority.cs
@@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
namespace Datadog.Trace
{
///
diff --git a/tracer/src/Datadog.Trace/SamplingPriorityValues.cs b/tracer/src/Datadog.Trace/SamplingPriorityValues.cs
index f9cc710c0664..3fa6cdf53574 100644
--- a/tracer/src/Datadog.Trace/SamplingPriorityValues.cs
+++ b/tracer/src/Datadog.Trace/SamplingPriorityValues.cs
@@ -3,10 +3,22 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
//
+#nullable enable
+
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+
namespace Datadog.Trace
{
internal static class SamplingPriorityValues
{
+ ///
+ /// The default sampling priority used when there is no sampler available
+ /// or no sampling rules match. For example, this value is used if the tracer has not yet
+ /// received any sampling rates from agent and there are no configured sampling rates.
+ ///
+ public const int Default = AutoKeep;
+
///
/// Trace should be dropped (not sampled).
/// Sampling decision made explicitly by user through
@@ -32,5 +44,23 @@ internal static class SamplingPriorityValues
/// code or configuration (e.g. the rules sampler).
///
public const int UserKeep = 2;
+
+ [return: NotNullIfNotNull("samplingPriority")]
+ internal static string? ToString(int? samplingPriority)
+ {
+ return samplingPriority switch
+ {
+ 2 => "2",
+ 1 => "1",
+ 0 => "0",
+ -1 => "-1",
+ null => null,
+ { } value => value.ToString(CultureInfo.InvariantCulture)
+ };
+ }
+
+ internal static bool IsKeep(int? samplingPriority) => samplingPriority > 0;
+
+ internal static bool IsDrop(int? samplingPriority) => samplingPriority <= 0;
}
}
diff --git a/tracer/src/Datadog.Trace/Span.cs b/tracer/src/Datadog.Trace/Span.cs
index 68a10346a583..3f4a08636ed3 100644
--- a/tracer/src/Datadog.Trace/Span.cs
+++ b/tracer/src/Datadog.Trace/Span.cs
@@ -4,20 +4,16 @@
//
using System;
-using System.Collections;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Threading;
-using System.Threading.Tasks;
using Datadog.Trace.Debugger.ExceptionAutoInstrumentation;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.Logging;
using Datadog.Trace.Sampling;
using Datadog.Trace.Tagging;
using Datadog.Trace.Telemetry;
-using Datadog.Trace.Telemetry.Metrics;
using Datadog.Trace.Util;
using Datadog.Trace.Vendors.Serilog.Events;
@@ -176,11 +172,14 @@ public override string ToString()
sb.AppendLine($"OperationName: {OperationName}");
sb.AppendLine($"Resource: {ResourceName}");
sb.AppendLine($"Type: {Type}");
- sb.AppendLine($"Start: {StartTime.ToString("O")}");
+ sb.AppendLine($"Start: {StartTime:O}");
sb.AppendLine($"Duration: {Duration}");
- sb.AppendLine($"End: {StartTime.Add(Duration).ToString("O")}");
+ sb.AppendLine($"End: {StartTime.Add(Duration):O}");
sb.AppendLine($"Error: {Error}");
- sb.AppendLine($"TraceSamplingPriority: {(Context.TraceContext.SamplingPriority?.ToString(CultureInfo.InvariantCulture) ?? "not set")}");
+
+ var samplingPriority = Context.TraceContext?.SamplingPriority;
+ sb.AppendLine($"TraceSamplingPriority: {SamplingPriorityValues.ToString(samplingPriority) ?? "not set"}");
+
sb.AppendLine($"Meta: {Tags}");
return StringBuilderCache.GetStringAndRelease(sb);
@@ -421,7 +420,7 @@ internal void SetExceptionTags(Exception exception)
// for AggregateException, use the first inner exception until we can support multiple errors.
// there will be only one error in most cases, and even if there are more and we lose
// the other ones, it's still better than the generic "one or more errors occurred" message.
- if (exception is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0)
+ if (exception is AggregateException { InnerExceptions.Count: > 0 } aggregateException)
{
exception = aggregateException.InnerExceptions[0];
}
@@ -452,21 +451,15 @@ internal string GetTag(string key)
{
// since we don't expose a public API for getting trace-level attributes yet,
// allow retrieval through any span in the trace
- switch (key)
+ return key switch
{
- case Trace.Tags.SamplingPriority:
- return Context.TraceContext?.SamplingPriority?.ToString();
- case Trace.Tags.Env:
- return Context.TraceContext?.Environment;
- case Trace.Tags.Version:
- return Context.TraceContext?.ServiceVersion;
- case Trace.Tags.Origin:
- return Context.TraceContext?.Origin;
- case Trace.Tags.TraceId:
- return Context.RawTraceId;
- default:
- return Tags.GetTag(key);
- }
+ Trace.Tags.SamplingPriority => SamplingPriorityValues.ToString(Context.TraceContext?.SamplingPriority),
+ Trace.Tags.Env => Context.TraceContext?.Environment,
+ Trace.Tags.Version => Context.TraceContext?.ServiceVersion,
+ Trace.Tags.Origin => Context.TraceContext?.Origin,
+ Trace.Tags.TraceId => Context.RawTraceId,
+ _ => Tags.GetTag(key)
+ };
}
internal void Finish(TimeSpan duration)
diff --git a/tracer/src/Datadog.Trace/TraceContext.cs b/tracer/src/Datadog.Trace/TraceContext.cs
index d7cb699ff190..cf1e24049bde 100644
--- a/tracer/src/Datadog.Trace/TraceContext.cs
+++ b/tracer/src/Datadog.Trace/TraceContext.cs
@@ -7,7 +7,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Datadog.Trace.AppSec;
using Datadog.Trace.ClrProfiler;
@@ -35,26 +34,25 @@ internal class TraceContext
private ArrayBuilder _spans;
private int _openSpans;
private int? _samplingPriority;
- // _rootSpan was chosen at some point to be used as the key for a lock that protects
+
+ // _rootSpan was chosen in #4125 to be the lock that protects
// * _spans
// * _openSpans
// although it's a nullable field, the _rootSpan must always be set before operations on
- // _spans & _samplingPriority take place, so it's okay to use it as a lock key
+ // _spans take place, so it's okay to use it as a lock key
// even though we need to override the nullable warnings in some places.
- // The reason _rootSpan was chosen is unknown, we're assuming it's to avoid
- // allocation a separate field for the lock
+ // The reason _rootSpan was chosen is to avoid
+ // allocating a separate object for the lock.
private Span? _rootSpan;
public TraceContext(IDatadogTracer tracer, TraceTagCollection? tags = null)
{
CurrentTraceSettings = tracer.PerTraceSettings;
- var settings = tracer.Settings;
-
// TODO: Environment, ServiceVersion, GitCommitSha, and GitRepositoryUrl are stored on the TraceContext
// even though they likely won't change for the lifetime of the process. We should consider moving them
// elsewhere to reduce the memory usage.
- if (settings is not null)
+ if (tracer.Settings is { } settings)
{
// these could be set from DD_ENV/DD_VERSION or from DD_TAGS
Environment = settings.EnvironmentInternal;
@@ -69,7 +67,6 @@ public TraceContext(IDatadogTracer tracer, TraceTagCollection? tags = null)
public Span? RootSpan
{
get => _rootSpan;
- private set => _rootSpan = value;
}
public TraceClock Clock => _clock;
@@ -81,7 +78,6 @@ public Span? RootSpan
///
/// Gets the collection of trace-level tags.
///
- [NotNull]
public TraceTagCollection Tags { get; }
///
@@ -110,6 +106,11 @@ public int? SamplingPriority
///
internal IastRequestContext? IastRequestContext => _iastRequestContext;
+ internal static TraceContext? GetTraceContext(in ArraySegment spans) =>
+ spans.Count > 0 ?
+ spans.Array![spans.Offset].Context.TraceContext :
+ null;
+
internal void AddWafSecurityEvents(IReadOnlyCollection