From 12f6483959102ecf185c27af9f1baddf9e1da4a6 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 13:21:48 -0500 Subject: [PATCH 01/38] Add serverless compat layer instrumentation for pipe coordination - Detect compat layer presence, generate unique pipe names only when present - Add instrumentation to override compat layer pipe name calculations - Tracer controls naming, compat layer uses instrumented values - Supports Azure Functions multifunction, doesn't affect regular Windows Co-Authored-By: Claude Sonnet 4.5 --- ..._CalculateDogStatsDPipeName_Integration.cs | 90 +++++++++++++++++++ ...ayer_CalculateTracePipeName_Integration.cs | 90 +++++++++++++++++++ .../Configuration/ExporterSettings.cs | 60 ++++++++++++- .../Configuration/IntegrationId.cs | 3 +- 4 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs create mode 100644 tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs new file mode 100644 index 000000000000..7552da7d0981 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -0,0 +1,90 @@ +// +// 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. +// + +#if NETCOREAPP +using System; +using System.ComponentModel; +using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless +{ + /// + /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateDogStatsDPipeName method. + /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, + /// ensuring the tracer's runtime metrics and the compat layer use the same pipe name. + /// + [InstrumentMethod( + AssemblyName = "Datadog.Serverless.Compat", + TypeName = "Datadog.Serverless.CompatibilityLayer", + MethodName = "CalculateDogStatsDPipeName", + ReturnTypeName = ClrNames.String, + ParameterTypeNames = new string[0], + MinimumVersion = "1.0.0", + MaximumVersion = "2.*.*", + IntegrationName = nameof(IntegrationId.ServerlessCompat), + InstrumentationCategory = InstrumentationCategory.Tracing)] + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public class CompatibilityLayer_CalculateDogStatsDPipeName_Integration + { + /// + /// OnMethodEnd callback - intercepts the return value and overrides it with the tracer's pipe name + /// + /// Type of the target + /// Instance value, aka `this` of the instrumented method (null for static methods) + /// The pipe name calculated by the compat layer + /// Exception instance in case the original code threw an exception + /// Calltarget state value + /// The tracer's pre-generated pipe name, overriding the compat layer's calculation + internal static CallTargetReturn OnMethodEnd( + TTarget instance, + string returnValue, + Exception exception, + in CallTargetState state) + { + if (exception != null) + { + // If there was an exception, pass it through + return new CallTargetReturn(returnValue); + } + + try + { + // Get the tracer's pre-generated pipe name from ExporterSettings + var tracerInstance = Tracer.Instance; + var exporterSettings = tracerInstance?.Settings?.Exporter; + var tracerPipeName = exporterSettings?.MetricsPipeName; + + if (!string.IsNullOrEmpty(tracerPipeName)) + { + Log.Debug( + "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", + returnValue, + tracerPipeName); + + // Override with tracer's value + return new CallTargetReturn(tracerPipeName); + } + else + { + Log.Warning( + "ServerlessCompat integration: Tracer DogStatsD pipe name is null or empty. " + + "Using compat layer's calculated value: {CompatPipeName}", + returnValue); + } + } + catch (Exception ex) + { + Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); + } + + // Fallback to compat layer's original value + return new CallTargetReturn(returnValue); + } + } +} +#endif diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs new file mode 100644 index 000000000000..96d61997379e --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -0,0 +1,90 @@ +// +// 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. +// + +#if NETCOREAPP +using System; +using System.ComponentModel; +using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless +{ + /// + /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateTracePipeName method. + /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, + /// ensuring both the tracer and the compat layer use the same pipe name for communication. + /// + [InstrumentMethod( + AssemblyName = "Datadog.Serverless.Compat", + TypeName = "Datadog.Serverless.CompatibilityLayer", + MethodName = "CalculateTracePipeName", + ReturnTypeName = ClrNames.String, + ParameterTypeNames = new string[0], + MinimumVersion = "1.0.0", + MaximumVersion = "2.*.*", + IntegrationName = nameof(IntegrationId.ServerlessCompat), + InstrumentationCategory = InstrumentationCategory.Tracing)] + [Browsable(false)] + [EditorBrowsable(EditorBrowsableState.Never)] + public class CompatibilityLayer_CalculateTracePipeName_Integration + { + /// + /// OnMethodEnd callback - intercepts the return value and overrides it with the tracer's pipe name + /// + /// Type of the target + /// Instance value, aka `this` of the instrumented method (null for static methods) + /// The pipe name calculated by the compat layer + /// Exception instance in case the original code threw an exception + /// Calltarget state value + /// The tracer's pre-generated pipe name, overriding the compat layer's calculation + internal static CallTargetReturn OnMethodEnd( + TTarget instance, + string returnValue, + Exception exception, + in CallTargetState state) + { + if (exception != null) + { + // If there was an exception, pass it through + return new CallTargetReturn(returnValue); + } + + try + { + // Get the tracer's pre-generated pipe name from ExporterSettings + var tracerInstance = Tracer.Instance; + var exporterSettings = tracerInstance?.Settings?.Exporter; + var tracerPipeName = exporterSettings?.TracesPipeName; + + if (!string.IsNullOrEmpty(tracerPipeName)) + { + Log.Debug( + "ServerlessCompat integration: Overriding compat layer trace pipe name. " + + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", + returnValue, + tracerPipeName); + + // Override with tracer's value + return new CallTargetReturn(tracerPipeName); + } + else + { + Log.Warning( + "ServerlessCompat integration: Tracer pipe name is null or empty. " + + "Using compat layer's calculated value: {CompatPipeName}", + returnValue); + } + } + catch (Exception ex) + { + Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); + } + + // Fallback to compat layer's original value + return new CallTargetReturn(returnValue); + } + } +} +#endif diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index e56b169691f8..fb84513cf095 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -87,9 +87,27 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); + // Check if serverless compat layer is loaded + // Only generate unique pipe names if compat layer is present (Azure Functions) + // Otherwise, use configured pipe names for regular Windows with Datadog Agent + var isCompatLayerLoaded = IsServerlessCompatLayerLoaded(); + + var tracesPipeName = rawSettings.TracesPipeName; + var metricsPipeName = rawSettings.MetricsPipeName; + + if (isCompatLayerLoaded) + { + // Generate unique pipe names for Azure Functions multifunction scenario + // These will be used to override compat layer's calculations via instrumentation + tracesPipeName = GenerateUniquePipeName(tracesPipeName, "dd_trace"); + metricsPipeName = GenerateUniquePipeName(metricsPipeName, "dd_dogstatsd"); + + Log.Information("Serverless compat layer detected. Generated unique pipe names for multi-function scenario."); + } + var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, - tracesPipeName: rawSettings.TracesPipeName, + tracesPipeName: tracesPipeName, agentHost: rawSettings.TraceAgentHost, agentPort: rawSettings.TraceAgentPort, tracesUnixDomainSocketPath: rawSettings.TracesUnixDomainSocketPath); @@ -104,7 +122,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi traceAgentUrl: rawSettings.TraceAgentUri, agentHost: rawSettings.TraceAgentHost, dogStatsdPort: rawSettings.DogStatsdPort, - metricsPipeName: rawSettings.MetricsPipeName, + metricsPipeName: metricsPipeName, metricsUnixDomainSocketPath: rawSettings.MetricsUnixDomainSocketPath); MetricsHostname = metricsSettings.Hostname; @@ -562,5 +580,43 @@ internal static Raw CreateUpdatedFromManualConfig( } } } + + /// + /// Checks if the Datadog Serverless Compatibility Layer is loaded in the current process. + /// The compat layer is used in Azure Functions for multi-function deployments. + /// + /// True if the compat layer assembly is loaded, false otherwise. + private static bool IsServerlessCompatLayerLoaded() + { + try + { + var compatAssembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().Name == "Datadog.Serverless.Compat"); + + return compatAssembly != null; + } + catch (Exception ex) + { + Log.Debug(ex, "Error checking if serverless compat layer is loaded"); + return false; + } + } + + /// + /// Generates a unique pipe name by appending a GUID to the base name. + /// Used in Azure Functions to avoid conflicts when multiple functions run in the same namespace. + /// + /// The configured pipe name from environment variables, or null + /// The default base name to use if no configuration provided + /// A unique pipe name in the format {base}_{guid} + private static string GenerateUniquePipeName(string? configuredName, string defaultBaseName) + { + var baseName = configuredName ?? defaultBaseName; + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens + var uniqueName = $"{baseName}_{guid}"; + + Log.Debug("Generated unique pipe name: {PipeName} (base: {BaseName})", uniqueName, baseName); + return uniqueName; + } } } diff --git a/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs b/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs index d40a2736d301..787eb373cf17 100644 --- a/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs +++ b/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs @@ -90,6 +90,7 @@ internal enum IntegrationId AzureEventHubs, DatadogTraceVersionConflict, Hangfire, - OpenFeature + OpenFeature, + ServerlessCompat } } From 91f1c921984e66e7e9c58d6fdaaf2dc9fc24e480 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 15:30:48 -0500 Subject: [PATCH 02/38] Improve validation for windows pipe name --- ...er_CalculateDogStatsDPipeName_Integration.cs | 12 +++++++++++- ...yLayer_CalculateTracePipeName_Integration.cs | 12 +++++++++++- .../Configuration/ExporterSettings.cs | 17 +++++++++++++++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 7552da7d0981..d4f586a5fa3f 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -55,7 +55,17 @@ internal static CallTargetReturn OnMethodEnd( { // Get the tracer's pre-generated pipe name from ExporterSettings var tracerInstance = Tracer.Instance; - var exporterSettings = tracerInstance?.Settings?.Exporter; + + if (tracerInstance == null) + { + Log.Debug( + "ServerlessCompat integration: Tracer.Instance is null. " + + "Using compat layer's calculated value: {CompatPipeName}", + returnValue); + return new CallTargetReturn(returnValue); + } + + var exporterSettings = tracerInstance.Settings?.Exporter; var tracerPipeName = exporterSettings?.MetricsPipeName; if (!string.IsNullOrEmpty(tracerPipeName)) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 96d61997379e..5fa4ab8d6d7d 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -55,7 +55,17 @@ internal static CallTargetReturn OnMethodEnd( { // Get the tracer's pre-generated pipe name from ExporterSettings var tracerInstance = Tracer.Instance; - var exporterSettings = tracerInstance?.Settings?.Exporter; + + if (tracerInstance == null) + { + Log.Debug( + "ServerlessCompat integration: Tracer.Instance is null. " + + "Using compat layer's calculated value: {CompatPipeName}", + returnValue); + return new CallTargetReturn(returnValue); + } + + var exporterSettings = tracerInstance.Settings?.Exporter; var tracerPipeName = exporterSettings?.TracesPipeName; if (!string.IsNullOrEmpty(tracerPipeName)) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index fb84513cf095..ad05b1e56124 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -102,7 +102,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi tracesPipeName = GenerateUniquePipeName(tracesPipeName, "dd_trace"); metricsPipeName = GenerateUniquePipeName(metricsPipeName, "dd_dogstatsd"); - Log.Information("Serverless compat layer detected. Generated unique pipe names for multi-function scenario."); + Log.Information("Serverless compat layer detected. Generated unique pipe names for multi-function scenario - Traces: {TracesPipe}, Metrics: {MetricsPipe}", tracesPipeName, metricsPipeName); } var traceSettings = GetTraceTransport( @@ -605,6 +605,7 @@ private static bool IsServerlessCompatLayerLoaded() /// /// Generates a unique pipe name by appending a GUID to the base name. /// Used in Azure Functions to avoid conflicts when multiple functions run in the same namespace. + /// Validates and truncates the base name if necessary to ensure the full pipe path stays within Windows limits. /// /// The configured pipe name from environment variables, or null /// The default base name to use if no configuration provided @@ -612,7 +613,19 @@ private static bool IsServerlessCompatLayerLoaded() private static string GenerateUniquePipeName(string? configuredName, string defaultBaseName) { var baseName = configuredName ?? defaultBaseName; - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens + + // Validate base pipe name length before appending GUID + // Windows pipe path format: \\.\pipe\{base}_{guid} + // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 + const int maxBaseLength = 214; + + if (baseName.Length > maxBaseLength) + { + Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); + baseName = baseName.Substring(0, maxBaseLength); + } + + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) var uniqueName = $"{baseName}_{guid}"; Log.Debug("Generated unique pipe name: {PipeName} (base: {BaseName})", uniqueName, baseName); From bfb08b6f08ac44c9db3844b61432a433ad212afd Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 16:39:01 -0500 Subject: [PATCH 03/38] Lazy compat layer named pipe generation --- ..._CalculateDogStatsDPipeName_Integration.cs | 56 +++---- ...ayer_CalculateTracePipeName_Integration.cs | 56 +++---- .../ServerlessCompatPipeNameHelper.cs | 48 ++++++ .../Configuration/ExporterSettings.cs | 72 +-------- .../ServerlessCompatIntegrationTests.cs | 153 ++++++++++++++++++ 5 files changed, 251 insertions(+), 134 deletions(-) create mode 100644 tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs create mode 100644 tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index d4f586a5fa3f..839e316a9945 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -30,15 +30,18 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless [EditorBrowsable(EditorBrowsableState.Never)] public class CompatibilityLayer_CalculateDogStatsDPipeName_Integration { + private static string? _cachedDogStatsDPipeName; + private static readonly object _lock = new object(); + /// - /// OnMethodEnd callback - intercepts the return value and overrides it with the tracer's pipe name + /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name /// /// Type of the target /// Instance value, aka `this` of the instrumented method (null for static methods) /// The pipe name calculated by the compat layer /// Exception instance in case the original code threw an exception /// Calltarget state value - /// The tracer's pre-generated pipe name, overriding the compat layer's calculation + /// A unique pipe name for coordination between tracer and compat layer internal static CallTargetReturn OnMethodEnd( TTarget instance, string returnValue, @@ -53,43 +56,32 @@ internal static CallTargetReturn OnMethodEnd( try { - // Get the tracer's pre-generated pipe name from ExporterSettings - var tracerInstance = Tracer.Instance; - - if (tracerInstance == null) + // Lazy generation: generate unique pipe name once when compat layer first calls this method + if (_cachedDogStatsDPipeName == null) { - Log.Debug( - "ServerlessCompat integration: Tracer.Instance is null. " + - "Using compat layer's calculated value: {CompatPipeName}", - returnValue); - return new CallTargetReturn(returnValue); + lock (_lock) + { + if (_cachedDogStatsDPipeName == null) + { + _cachedDogStatsDPipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + returnValue, + "dd_dogstatsd", + "DogStatsD"); + } + } } - var exporterSettings = tracerInstance.Settings?.Exporter; - var tracerPipeName = exporterSettings?.MetricsPipeName; - - if (!string.IsNullOrEmpty(tracerPipeName)) - { - Log.Debug( - "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + - "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", - returnValue, - tracerPipeName); + Log.Debug( + "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", + returnValue, + _cachedDogStatsDPipeName); - // Override with tracer's value - return new CallTargetReturn(tracerPipeName); - } - else - { - Log.Warning( - "ServerlessCompat integration: Tracer DogStatsD pipe name is null or empty. " + - "Using compat layer's calculated value: {CompatPipeName}", - returnValue); - } + return new CallTargetReturn(_cachedDogStatsDPipeName); } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error generating DogStatsD pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 5fa4ab8d6d7d..9e6a4e253860 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -30,15 +30,18 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless [EditorBrowsable(EditorBrowsableState.Never)] public class CompatibilityLayer_CalculateTracePipeName_Integration { + private static string? _cachedTracePipeName; + private static readonly object _lock = new object(); + /// - /// OnMethodEnd callback - intercepts the return value and overrides it with the tracer's pipe name + /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name /// /// Type of the target /// Instance value, aka `this` of the instrumented method (null for static methods) /// The pipe name calculated by the compat layer /// Exception instance in case the original code threw an exception /// Calltarget state value - /// The tracer's pre-generated pipe name, overriding the compat layer's calculation + /// A unique pipe name for coordination between tracer and compat layer internal static CallTargetReturn OnMethodEnd( TTarget instance, string returnValue, @@ -53,43 +56,32 @@ internal static CallTargetReturn OnMethodEnd( try { - // Get the tracer's pre-generated pipe name from ExporterSettings - var tracerInstance = Tracer.Instance; - - if (tracerInstance == null) + // Lazy generation: generate unique pipe name once when compat layer first calls this method + if (_cachedTracePipeName == null) { - Log.Debug( - "ServerlessCompat integration: Tracer.Instance is null. " + - "Using compat layer's calculated value: {CompatPipeName}", - returnValue); - return new CallTargetReturn(returnValue); + lock (_lock) + { + if (_cachedTracePipeName == null) + { + _cachedTracePipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + returnValue, + "dd_trace", + "trace"); + } + } } - var exporterSettings = tracerInstance.Settings?.Exporter; - var tracerPipeName = exporterSettings?.TracesPipeName; - - if (!string.IsNullOrEmpty(tracerPipeName)) - { - Log.Debug( - "ServerlessCompat integration: Overriding compat layer trace pipe name. " + - "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", - returnValue, - tracerPipeName); + Log.Debug( + "ServerlessCompat integration: Overriding compat layer trace pipe name. " + + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", + returnValue, + _cachedTracePipeName); - // Override with tracer's value - return new CallTargetReturn(tracerPipeName); - } - else - { - Log.Warning( - "ServerlessCompat integration: Tracer pipe name is null or empty. " + - "Using compat layer's calculated value: {CompatPipeName}", - returnValue); - } + return new CallTargetReturn(_cachedTracePipeName); } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error generating trace pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs new file mode 100644 index 000000000000..41c1cc5a4f8b --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -0,0 +1,48 @@ +// +// 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. +// + +#if NETCOREAPP +using System; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless +{ + /// + /// Helper class for generating unique pipe names for serverless compat layer coordination. + /// Shared logic for both trace and metrics pipe name generation. + /// + internal static class ServerlessCompatPipeNameHelper + { + /// + /// Generates a unique pipe name by appending a GUID to the base name. + /// Validates and truncates the base name if necessary to ensure the full pipe path stays within Windows limits. + /// + /// The base name calculated by the compat layer, or null + /// The default base name to use if compat layer returns null + /// The type of pipe for logging (e.g., "trace" or "DogStatsD") + /// A unique pipe name in the format {base}_{guid} + internal static string GenerateUniquePipeName(string? compatLayerBaseName, string defaultBaseName, string pipeType) + { + var baseName = compatLayerBaseName ?? defaultBaseName; + + // Validate base pipe name length before appending GUID + // Windows pipe path format: \\.\pipe\{base}_{guid} + // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 + const int maxBaseLength = 214; + + if (baseName.Length > maxBaseLength) + { + Log.Warning("{PipeType} pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", pipeType, maxBaseLength, baseName.Length); + baseName = baseName.Substring(0, maxBaseLength); + } + + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) + var uniqueName = $"{baseName}_{guid}"; + + Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); + return uniqueName; + } + } +} +#endif diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index ad05b1e56124..78df4e309fef 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -87,27 +87,9 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); - // Check if serverless compat layer is loaded - // Only generate unique pipe names if compat layer is present (Azure Functions) - // Otherwise, use configured pipe names for regular Windows with Datadog Agent - var isCompatLayerLoaded = IsServerlessCompatLayerLoaded(); - - var tracesPipeName = rawSettings.TracesPipeName; - var metricsPipeName = rawSettings.MetricsPipeName; - - if (isCompatLayerLoaded) - { - // Generate unique pipe names for Azure Functions multifunction scenario - // These will be used to override compat layer's calculations via instrumentation - tracesPipeName = GenerateUniquePipeName(tracesPipeName, "dd_trace"); - metricsPipeName = GenerateUniquePipeName(metricsPipeName, "dd_dogstatsd"); - - Log.Information("Serverless compat layer detected. Generated unique pipe names for multi-function scenario - Traces: {TracesPipe}, Metrics: {MetricsPipe}", tracesPipeName, metricsPipeName); - } - var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, - tracesPipeName: tracesPipeName, + tracesPipeName: rawSettings.TracesPipeName, agentHost: rawSettings.TraceAgentHost, agentPort: rawSettings.TraceAgentPort, tracesUnixDomainSocketPath: rawSettings.TracesUnixDomainSocketPath); @@ -122,7 +104,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi traceAgentUrl: rawSettings.TraceAgentUri, agentHost: rawSettings.TraceAgentHost, dogStatsdPort: rawSettings.DogStatsdPort, - metricsPipeName: metricsPipeName, + metricsPipeName: rawSettings.MetricsPipeName, metricsUnixDomainSocketPath: rawSettings.MetricsUnixDomainSocketPath); MetricsHostname = metricsSettings.Hostname; @@ -581,55 +563,5 @@ internal static Raw CreateUpdatedFromManualConfig( } } - /// - /// Checks if the Datadog Serverless Compatibility Layer is loaded in the current process. - /// The compat layer is used in Azure Functions for multi-function deployments. - /// - /// True if the compat layer assembly is loaded, false otherwise. - private static bool IsServerlessCompatLayerLoaded() - { - try - { - var compatAssembly = AppDomain.CurrentDomain.GetAssemblies() - .FirstOrDefault(a => a.GetName().Name == "Datadog.Serverless.Compat"); - - return compatAssembly != null; - } - catch (Exception ex) - { - Log.Debug(ex, "Error checking if serverless compat layer is loaded"); - return false; - } - } - - /// - /// Generates a unique pipe name by appending a GUID to the base name. - /// Used in Azure Functions to avoid conflicts when multiple functions run in the same namespace. - /// Validates and truncates the base name if necessary to ensure the full pipe path stays within Windows limits. - /// - /// The configured pipe name from environment variables, or null - /// The default base name to use if no configuration provided - /// A unique pipe name in the format {base}_{guid} - private static string GenerateUniquePipeName(string? configuredName, string defaultBaseName) - { - var baseName = configuredName ?? defaultBaseName; - - // Validate base pipe name length before appending GUID - // Windows pipe path format: \\.\pipe\{base}_{guid} - // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 - const int maxBaseLength = 214; - - if (baseName.Length > maxBaseLength) - { - Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); - baseName = baseName.Substring(0, maxBaseLength); - } - - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) - var uniqueName = $"{baseName}_{guid}"; - - Log.Debug("Generated unique pipe name: {PipeName} (base: {BaseName})", uniqueName, baseName); - return uniqueName; - } } } diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs new file mode 100644 index 000000000000..0232f5f1fa34 --- /dev/null +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -0,0 +1,153 @@ +// +// 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. +// + +#if NETCOREAPP +using System; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; +using Datadog.Trace.ClrProfiler.CallTarget; +using FluentAssertions; +using Xunit; + +namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless; + +public class ServerlessCompatIntegrationTests +{ + [Theory] + [InlineData(null, "dd_trace")] // Null base name should use default + [InlineData("custom_pipe", "custom_pipe")] // Custom base name should be used + [InlineData("short", "short")] // Short name should work + [InlineData("this_is_a_very_long_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_characters_before_appending_guid_suffix_extra_padding", "this_is_a_very_long_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_cha")] // Long name should be truncated to 214 chars + public void CalculateTracePipeName_GeneratesValidUniquePipeName(string compatLayerValue, string expectedBase) + { + // Arrange + var state = new CallTargetState(); + + // Act - First call generates the pipe name + var result1 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + instance: null, + returnValue: compatLayerValue, + exception: null, + in state); + + // Second call should return the same cached value + var result2 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + instance: null, + returnValue: compatLayerValue, + exception: null, + in state); + + // Assert + result1.GetReturnValue().Should().NotBeNullOrEmpty(); + result2.GetReturnValue().Should().NotBeNullOrEmpty(); + + // Should return the same cached value + result1.GetReturnValue().Should().Be(result2.GetReturnValue()); + + // Should start with expected base name + result1.GetReturnValue().Should().StartWith(expectedBase); + + // Should have GUID suffix (underscore + 32 hex chars) + result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); + + // Total length should not exceed Windows limit (base + underscore + GUID) + result1.GetReturnValue().Length.Should().BeLessOrEqualTo(214 + 1 + 32); // 247 max + + // If input was longer than 214, verify truncation + if (compatLayerValue?.Length > 214) + { + var pipeName = result1.GetReturnValue(); + var baseNamePart = pipeName.Substring(0, pipeName.LastIndexOf('_')); + baseNamePart.Length.Should().Be(214); + } + } + + [Fact] + public void CalculateTracePipeName_HandlesException_ReturnsFallback() + { + // Arrange + var state = new CallTargetState(); + var expectedException = new InvalidOperationException("Test exception"); + var fallbackValue = "fallback_pipe_name"; + + // Act - Pass exception to OnMethodEnd + var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + instance: null, + returnValue: fallbackValue, + exception: expectedException, + in state); + + // Assert - Should return the fallback value when exception is present + result.GetReturnValue().Should().Be(fallbackValue); + } + + [Theory] + [InlineData(null, "dd_dogstatsd")] // Null base name should use default + [InlineData("custom_statsd", "custom_statsd")] // Custom base name should be used + [InlineData("short", "short")] // Short name should work + [InlineData("this_is_a_very_long_dogstatsd_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_characters_before_appending_the_guid_suffix", "this_is_a_very_long_dogstatsd_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_")] // Long name should be truncated to 214 chars + public void CalculateDogStatsDPipeName_GeneratesValidUniquePipeName(string compatLayerValue, string expectedBase) + { + // Arrange + var state = new CallTargetState(); + + // Act - First call generates the pipe name + var result1 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + instance: null, + returnValue: compatLayerValue, + exception: null, + in state); + + // Second call should return the same cached value + var result2 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + instance: null, + returnValue: compatLayerValue, + exception: null, + in state); + + // Assert + result1.GetReturnValue().Should().NotBeNullOrEmpty(); + result2.GetReturnValue().Should().NotBeNullOrEmpty(); + + // Should return the same cached value + result1.GetReturnValue().Should().Be(result2.GetReturnValue()); + + // Should start with expected base name + result1.GetReturnValue().Should().StartWith(expectedBase); + + // Should have GUID suffix (underscore + 32 hex chars) + result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); + + // Total length should not exceed Windows limit + result1.GetReturnValue().Length.Should().BeLessOrEqualTo(214 + 1 + 32); // 247 max + + // If input was longer than 214, verify truncation + if (compatLayerValue?.Length > 214) + { + var pipeName = result1.GetReturnValue(); + var baseNamePart = pipeName.Substring(0, pipeName.LastIndexOf('_')); + baseNamePart.Length.Should().Be(214); + } + } + + [Fact] + public void CalculateDogStatsDPipeName_HandlesException_ReturnsFallback() + { + // Arrange + var state = new CallTargetState(); + var expectedException = new InvalidOperationException("Test exception"); + var fallbackValue = "fallback_dogstatsd_pipe"; + + // Act - Pass exception to OnMethodEnd + var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + instance: null, + returnValue: fallbackValue, + exception: expectedException, + in state); + + // Assert - Should return the fallback value when exception is present + result.GetReturnValue().Should().Be(fallbackValue); + } +} +#endif From bfeee23380fff33370b536a04d1132d1468a688e Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 16:56:04 -0500 Subject: [PATCH 04/38] Minor cleanup --- tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs | 1 - .../Serverless/ServerlessCompatIntegrationTests.cs | 6 ------ 2 files changed, 7 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 78df4e309fef..e56b169691f8 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -562,6 +562,5 @@ internal static Raw CreateUpdatedFromManualConfig( } } } - } } diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 0232f5f1fa34..9b0762a2acec 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -51,9 +51,6 @@ public void CalculateTracePipeName_GeneratesValidUniquePipeName(string compatLay // Should have GUID suffix (underscore + 32 hex chars) result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); - // Total length should not exceed Windows limit (base + underscore + GUID) - result1.GetReturnValue().Length.Should().BeLessOrEqualTo(214 + 1 + 32); // 247 max - // If input was longer than 214, verify truncation if (compatLayerValue?.Length > 214) { @@ -119,9 +116,6 @@ public void CalculateDogStatsDPipeName_GeneratesValidUniquePipeName(string compa // Should have GUID suffix (underscore + 32 hex chars) result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); - // Total length should not exceed Windows limit - result1.GetReturnValue().Length.Should().BeLessOrEqualTo(214 + 1 + 32); // 247 max - // If input was longer than 214, verify truncation if (compatLayerValue?.Length > 214) { From 9bdde5b7ec9963ac08e3df7f9ea784172880f6b3 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 17:10:16 -0500 Subject: [PATCH 05/38] Target compat layer specifically --- ..._CalculateDogStatsDPipeName_Integration.cs | 27 +++++++--- ...ayer_CalculateTracePipeName_Integration.cs | 27 +++++++--- .../Configuration/ExporterSettings.cs | 50 ++++++++++++++++++- 3 files changed, 90 insertions(+), 14 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 839e316a9945..a0a99beeab33 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -56,17 +56,32 @@ internal static CallTargetReturn OnMethodEnd( try { - // Lazy generation: generate unique pipe name once when compat layer first calls this method + // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) + // Use lazy caching to avoid repeated lookups if (_cachedDogStatsDPipeName == null) { lock (_lock) { if (_cachedDogStatsDPipeName == null) { - _cachedDogStatsDPipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - returnValue, - "dd_dogstatsd", - "DogStatsD"); + var tracerInstance = Tracer.Instance; + var exporterSettings = tracerInstance?.Settings?.Exporter; + _cachedDogStatsDPipeName = exporterSettings?.MetricsPipeName; + + if (string.IsNullOrEmpty(_cachedDogStatsDPipeName)) + { + // Fallback: if tracer doesn't have a pipe name, generate one here + // This shouldn't happen in normal flow, but provides safety + _cachedDogStatsDPipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + returnValue, + "dd_dogstatsd", + "DogStatsD"); + Log.Warning("ServerlessCompat integration: Tracer DogStatsD pipe name not available, generated fallback: {PipeName}", _cachedDogStatsDPipeName); + } + else + { + Log.Information("ServerlessCompat integration: Using tracer's DogStatsD pipe name: {TracerPipeName}", _cachedDogStatsDPipeName); + } } } } @@ -81,7 +96,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error generating DogStatsD pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 9e6a4e253860..60361e14562f 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -56,17 +56,32 @@ internal static CallTargetReturn OnMethodEnd( try { - // Lazy generation: generate unique pipe name once when compat layer first calls this method + // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) + // Use lazy caching to avoid repeated lookups if (_cachedTracePipeName == null) { lock (_lock) { if (_cachedTracePipeName == null) { - _cachedTracePipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - returnValue, - "dd_trace", - "trace"); + var tracerInstance = Tracer.Instance; + var exporterSettings = tracerInstance?.Settings?.Exporter; + _cachedTracePipeName = exporterSettings?.TracesPipeName; + + if (string.IsNullOrEmpty(_cachedTracePipeName)) + { + // Fallback: if tracer doesn't have a pipe name, generate one here + // This shouldn't happen in normal flow, but provides safety + _cachedTracePipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + returnValue, + "dd_trace", + "trace"); + Log.Warning("ServerlessCompat integration: Tracer pipe name not available, generated fallback: {PipeName}", _cachedTracePipeName); + } + else + { + Log.Information("ServerlessCompat integration: Using tracer's pipe name: {TracerPipeName}", _cachedTracePipeName); + } } } } @@ -81,7 +96,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error generating trace pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index e56b169691f8..8df385cbb9ab 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -87,9 +87,30 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); + // Generate unique pipe names for Azure Functions (when not using AAS Site Extension) if not explicitly configured + // This ensures multi-function scenarios don't conflict when using the compat layer + // If names are explicitly configured, use them as-is + var tracesPipeName = rawSettings.TracesPipeName; + var metricsPipeName = rawSettings.MetricsPipeName; + + if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension()) + { + if (string.IsNullOrEmpty(tracesPipeName)) + { + tracesPipeName = GenerateUniquePipeName("dd_trace"); + Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); + } + + if (string.IsNullOrEmpty(metricsPipeName)) + { + metricsPipeName = GenerateUniquePipeName("dd_dogstatsd"); + Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); + } + } + var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, - tracesPipeName: rawSettings.TracesPipeName, + tracesPipeName: tracesPipeName, agentHost: rawSettings.TraceAgentHost, agentPort: rawSettings.TraceAgentPort, tracesUnixDomainSocketPath: rawSettings.TracesUnixDomainSocketPath); @@ -104,7 +125,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi traceAgentUrl: rawSettings.TraceAgentUri, agentHost: rawSettings.TraceAgentHost, dogStatsdPort: rawSettings.DogStatsdPort, - metricsPipeName: rawSettings.MetricsPipeName, + metricsPipeName: metricsPipeName, metricsUnixDomainSocketPath: rawSettings.MetricsUnixDomainSocketPath); MetricsHostname = metricsSettings.Hostname; @@ -562,5 +583,30 @@ internal static Raw CreateUpdatedFromManualConfig( } } } + + /// + /// Generates a unique pipe name by appending a GUID to the base name. + /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. + /// + /// The base name for the pipe + /// A unique pipe name in the format {base}_{guid} + private static string GenerateUniquePipeName(string baseName) + { + // Validate base pipe name length before appending GUID + // Windows pipe path format: \\.\pipe\{base}_{guid} + // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 + const int maxBaseLength = 214; + + if (baseName.Length > maxBaseLength) + { + Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); + baseName = baseName.Substring(0, maxBaseLength); + } + + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) + var uniqueName = $"{baseName}_{guid}"; + + return uniqueName; + } } } From 3ae52853d4b5fd99d66da3f1d0bd8bf1df888204 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 17:48:50 -0500 Subject: [PATCH 06/38] Fix compilation and StyleCop errors --- tracer/missing-nullability-files.csv | 3 + ..._CalculateDogStatsDPipeName_Integration.cs | 27 +++---- ...ayer_CalculateTracePipeName_Integration.cs | 27 +++---- .../ServerlessCompatPipeNameHelper.cs | 4 +- .../Configuration/ExporterSettings.cs | 70 ++++++++++++------- 5 files changed, 64 insertions(+), 67 deletions(-) diff --git a/tracer/missing-nullability-files.csv b/tracer/missing-nullability-files.csv index d88b90d0d9ec..502da507fa0e 100644 --- a/tracer/missing-nullability-files.csv +++ b/tracer/missing-nullability-files.csv @@ -452,6 +452,9 @@ src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/EnvironmentVariablesSc src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/ProcessStartIntegration.cs src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/ProcessStartTags.cs src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RabbitMQ/RabbitMQConstants.cs +src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs src/Datadog.Trace/Debugger/Configurations/Models/Capture.cs src/Datadog.Trace/Debugger/Configurations/Models/DebuggerExpression.cs src/Datadog.Trace/Debugger/Configurations/Models/EvaluateAt.cs diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index a0a99beeab33..40281cc727d8 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -28,10 +28,10 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless InstrumentationCategory = InstrumentationCategory.Tracing)] [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public class CompatibilityLayer_CalculateDogStatsDPipeName_Integration + public sealed class CompatibilityLayer_CalculateDogStatsDPipeName_Integration { - private static string? _cachedDogStatsDPipeName; private static readonly object _lock = new object(); + private static string? _cachedDogStatsDPipeName; /// /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name @@ -64,29 +64,18 @@ internal static CallTargetReturn OnMethodEnd( { if (_cachedDogStatsDPipeName == null) { - var tracerInstance = Tracer.Instance; - var exporterSettings = tracerInstance?.Settings?.Exporter; - _cachedDogStatsDPipeName = exporterSettings?.MetricsPipeName; - - if (string.IsNullOrEmpty(_cachedDogStatsDPipeName)) - { - // Fallback: if tracer doesn't have a pipe name, generate one here - // This shouldn't happen in normal flow, but provides safety - _cachedDogStatsDPipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) + // Otherwise, generate a unique pipe name as fallback + _cachedDogStatsDPipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName + ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( returnValue, "dd_dogstatsd", "DogStatsD"); - Log.Warning("ServerlessCompat integration: Tracer DogStatsD pipe name not available, generated fallback: {PipeName}", _cachedDogStatsDPipeName); - } - else - { - Log.Information("ServerlessCompat integration: Using tracer's DogStatsD pipe name: {TracerPipeName}", _cachedDogStatsDPipeName); - } } } } - Log.Debug( + Logging.Log.Debug( "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, @@ -96,7 +85,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); + Logging.Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 60361e14562f..9218d646116f 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -28,10 +28,10 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless InstrumentationCategory = InstrumentationCategory.Tracing)] [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public class CompatibilityLayer_CalculateTracePipeName_Integration + public sealed class CompatibilityLayer_CalculateTracePipeName_Integration { - private static string? _cachedTracePipeName; private static readonly object _lock = new object(); + private static string? _cachedTracePipeName; /// /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name @@ -64,29 +64,18 @@ internal static CallTargetReturn OnMethodEnd( { if (_cachedTracePipeName == null) { - var tracerInstance = Tracer.Instance; - var exporterSettings = tracerInstance?.Settings?.Exporter; - _cachedTracePipeName = exporterSettings?.TracesPipeName; - - if (string.IsNullOrEmpty(_cachedTracePipeName)) - { - // Fallback: if tracer doesn't have a pipe name, generate one here - // This shouldn't happen in normal flow, but provides safety - _cachedTracePipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName( + // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) + // Otherwise, generate a unique pipe name as fallback + _cachedTracePipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName + ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( returnValue, "dd_trace", "trace"); - Log.Warning("ServerlessCompat integration: Tracer pipe name not available, generated fallback: {PipeName}", _cachedTracePipeName); - } - else - { - Log.Information("ServerlessCompat integration: Using tracer's pipe name: {TracerPipeName}", _cachedTracePipeName); - } } } } - Log.Debug( + Logging.Log.Debug( "ServerlessCompat integration: Overriding compat layer trace pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, @@ -96,7 +85,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); + Logging.Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 41c1cc5a4f8b..143af86492e8 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -33,14 +33,14 @@ internal static string GenerateUniquePipeName(string? compatLayerBaseName, strin if (baseName.Length > maxBaseLength) { - Log.Warning("{PipeType} pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", pipeType, maxBaseLength, baseName.Length); + Logging.Log.Warning("{PipeType} pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", pipeType, maxBaseLength, baseName.Length); baseName = baseName.Substring(0, maxBaseLength); } var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) var uniqueName = $"{baseName}_{guid}"; - Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); + Logging.Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); return uniqueName; } } diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 8df385cbb9ab..e73b8debc5c1 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -98,13 +98,15 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi if (string.IsNullOrEmpty(tracesPipeName)) { tracesPipeName = GenerateUniquePipeName("dd_trace"); - Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); + AzureFunctionsGeneratedTracesPipeName = tracesPipeName; + Logging.Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); } if (string.IsNullOrEmpty(metricsPipeName)) { metricsPipeName = GenerateUniquePipeName("dd_dogstatsd"); - Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); + AzureFunctionsGeneratedMetricsPipeName = metricsPipeName; + Logging.Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); } } @@ -139,6 +141,20 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi TracesPipeTimeoutMs = rawSettings.TracesPipeTimeoutMs; } + /// + /// Gets the generated trace pipe name for Azure Functions coordination. + /// This is set when running in Azure Functions without explicit pipe name configuration. + /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. + /// + internal static string? AzureFunctionsGeneratedTracesPipeName { get; private set; } + + /// + /// Gets the generated metrics pipe name for Azure Functions coordination. + /// This is set when running in Azure Functions without explicit pipe name configuration. + /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. + /// + internal static string? AzureFunctionsGeneratedMetricsPipeName { get; private set; } + /// /// Gets the Uri where the Tracer can connect to the Agent. /// Default is "http://localhost:8126". @@ -443,6 +459,31 @@ private void RecordTraceTransport(string transport, ConfigurationOrigins origin private readonly record struct MetricsTransportSettings(MetricsTransportType Transport, string Hostname = DefaultDogstatsdHostname, int DogStatsdPort = 0, string? UdsPath = null, string? PipeName = null); + /// + /// Generates a unique pipe name by appending a GUID to the base name. + /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. + /// + /// The base name for the pipe + /// A unique pipe name in the format {base}_{guid} + private static string GenerateUniquePipeName(string baseName) + { + // Validate base pipe name length before appending GUID + // Windows pipe path format: \\.\pipe\{base}_{guid} + // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 + const int maxBaseLength = 214; + + if (baseName.Length > maxBaseLength) + { + Logging.Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); + baseName = baseName.Substring(0, maxBaseLength); + } + + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) + var uniqueName = $"{baseName}_{guid}"; + + return uniqueName; + } + /// /// These contain the "raw" settings loaded from config. If these don't change, the exporter settings also won't change /// @@ -583,30 +624,5 @@ internal static Raw CreateUpdatedFromManualConfig( } } } - - /// - /// Generates a unique pipe name by appending a GUID to the base name. - /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. - /// - /// The base name for the pipe - /// A unique pipe name in the format {base}_{guid} - private static string GenerateUniquePipeName(string baseName) - { - // Validate base pipe name length before appending GUID - // Windows pipe path format: \\.\pipe\{base}_{guid} - // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 - const int maxBaseLength = 214; - - if (baseName.Length > maxBaseLength) - { - Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); - baseName = baseName.Substring(0, maxBaseLength); - } - - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) - var uniqueName = $"{baseName}_{guid}"; - - return uniqueName; - } } } From 9b6f2b013b02dac452c44e56798a365994d749ab Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 18:42:28 -0500 Subject: [PATCH 07/38] Now with generated files --- tracer/build/supported_calltargets.g.json | 44 ++++++++++++++ tracer/missing-nullability-files.csv | 3 - .../build/Datadog.Trace.Trimming.xml | 1 + ..._CalculateDogStatsDPipeName_Integration.cs | 8 ++- ...ayer_CalculateTracePipeName_Integration.cs | 8 ++- .../ServerlessCompatPipeNameHelper.cs | 9 ++- .../Configuration/ExporterSettings.cs | 57 ++++++++++--------- ...ntegrationIdExtensions_EnumExtensions.g.cs | 5 +- .../IntegrationNameToKeys.g.cs | 6 ++ ...ntegrationIdExtensions_EnumExtensions.g.cs | 5 +- .../IntegrationNameToKeys.g.cs | 6 ++ .../InstrumentationDefinitions.g.cs | 3 + ...ntegrationIdExtensions_EnumExtensions.g.cs | 5 +- .../IntegrationNameToKeys.g.cs | 6 ++ .../InstrumentationDefinitions.g.cs | 3 + ...ntegrationIdExtensions_EnumExtensions.g.cs | 5 +- .../IntegrationNameToKeys.g.cs | 6 ++ .../Generated/generated_calltargets.g.cpp | 2 + 18 files changed, 142 insertions(+), 40 deletions(-) diff --git a/tracer/build/supported_calltargets.g.json b/tracer/build/supported_calltargets.g.json index cd1e0ba03f82..a26724d17e2d 100644 --- a/tracer/build/supported_calltargets.g.json +++ b/tracer/build/supported_calltargets.g.json @@ -16459,6 +16459,50 @@ "IsAdoNetIntegration": false, "InstrumentationCategory": 1 }, + { + "IntegrationName": "ServerlessCompat", + "AssemblyName": "Datadog.Serverless.Compat", + "TargetTypeName": "Datadog.Serverless.CompatibilityLayer", + "TargetMethodName": "CalculateDogStatsDPipeName", + "TargetReturnType": "System.String", + "TargetParameterTypes": [], + "MinimumVersion": { + "Item1": 1, + "Item2": 0, + "Item3": 0 + }, + "MaximumVersion": { + "Item1": 2, + "Item2": 65535, + "Item3": 65535 + }, + "InstrumentationTypeName": "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration", + "IntegrationKind": 0, + "IsAdoNetIntegration": false, + "InstrumentationCategory": 1 + }, + { + "IntegrationName": "ServerlessCompat", + "AssemblyName": "Datadog.Serverless.Compat", + "TargetTypeName": "Datadog.Serverless.CompatibilityLayer", + "TargetMethodName": "CalculateTracePipeName", + "TargetReturnType": "System.String", + "TargetParameterTypes": [], + "MinimumVersion": { + "Item1": 1, + "Item2": 0, + "Item3": 0 + }, + "MaximumVersion": { + "Item1": 2, + "Item2": 65535, + "Item3": 65535 + }, + "InstrumentationTypeName": "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration", + "IntegrationKind": 0, + "IsAdoNetIntegration": false, + "InstrumentationCategory": 1 + }, { "IntegrationName": "ServiceStackRedis", "AssemblyName": "ServiceStack.Redis", diff --git a/tracer/missing-nullability-files.csv b/tracer/missing-nullability-files.csv index 502da507fa0e..d88b90d0d9ec 100644 --- a/tracer/missing-nullability-files.csv +++ b/tracer/missing-nullability-files.csv @@ -452,9 +452,6 @@ src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/EnvironmentVariablesSc src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/ProcessStartIntegration.cs src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Process/ProcessStartTags.cs src/Datadog.Trace/ClrProfiler/AutoInstrumentation/RabbitMQ/RabbitMQConstants.cs -src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs -src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs -src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs src/Datadog.Trace/Debugger/Configurations/Models/Capture.cs src/Datadog.Trace/Debugger/Configurations/Models/DebuggerExpression.cs src/Datadog.Trace/Debugger/Configurations/Models/EvaluateAt.cs diff --git a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml index 5c07278816bf..a6d07d24ce3c 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -16,6 +16,7 @@ + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 40281cc727d8..738723134bd7 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -3,11 +3,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // +#nullable enable + #if NETCOREAPP using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; using Datadog.Trace.Configuration; +using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless { @@ -30,6 +33,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless [EditorBrowsable(EditorBrowsableState.Never)] public sealed class CompatibilityLayer_CalculateDogStatsDPipeName_Integration { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration)); private static readonly object _lock = new object(); private static string? _cachedDogStatsDPipeName; @@ -75,7 +79,7 @@ internal static CallTargetReturn OnMethodEnd( } } - Logging.Log.Debug( + Log.Debug( "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, @@ -85,7 +89,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Logging.Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error overriding DogStatsD pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 9218d646116f..2b3367a9ee48 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -3,11 +3,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // +#nullable enable + #if NETCOREAPP using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; using Datadog.Trace.Configuration; +using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless { @@ -30,6 +33,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless [EditorBrowsable(EditorBrowsableState.Never)] public sealed class CompatibilityLayer_CalculateTracePipeName_Integration { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(CompatibilityLayer_CalculateTracePipeName_Integration)); private static readonly object _lock = new object(); private static string? _cachedTracePipeName; @@ -75,7 +79,7 @@ internal static CallTargetReturn OnMethodEnd( } } - Logging.Log.Debug( + Log.Debug( "ServerlessCompat integration: Overriding compat layer trace pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, @@ -85,7 +89,7 @@ internal static CallTargetReturn OnMethodEnd( } catch (Exception ex) { - Logging.Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); + Log.Error(ex, "ServerlessCompat integration: Error overriding trace pipe name"); } // Fallback to compat layer's original value diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 143af86492e8..71d0cb78b248 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -3,8 +3,11 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // +#nullable enable + #if NETCOREAPP using System; +using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless { @@ -14,6 +17,8 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless /// internal static class ServerlessCompatPipeNameHelper { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(ServerlessCompatPipeNameHelper)); + /// /// Generates a unique pipe name by appending a GUID to the base name. /// Validates and truncates the base name if necessary to ensure the full pipe path stays within Windows limits. @@ -33,14 +38,14 @@ internal static string GenerateUniquePipeName(string? compatLayerBaseName, strin if (baseName.Length > maxBaseLength) { - Logging.Log.Warning("{PipeType} pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", pipeType, maxBaseLength, baseName.Length); + Log.Warning("{PipeType} pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", pipeType, maxBaseLength, baseName.Length); baseName = baseName.Substring(0, maxBaseLength); } var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) var uniqueName = $"{baseName}_{guid}"; - Logging.Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); + Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); return uniqueName; } } diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index e73b8debc5c1..b58c41c2883f 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -13,6 +13,7 @@ using Datadog.Trace.Agent; using Datadog.Trace.Configuration.ConfigurationSources; using Datadog.Trace.Configuration.Telemetry; +using Datadog.Trace.Logging; using Datadog.Trace.SourceGenerators; using Datadog.Trace.Telemetry; using Datadog.Trace.Telemetry.Metrics; @@ -26,6 +27,8 @@ namespace Datadog.Trace.Configuration /// public sealed partial class ExporterSettings { + private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(ExporterSettings)); + /// /// Allows overriding of file system access for tests. /// @@ -99,14 +102,14 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi { tracesPipeName = GenerateUniquePipeName("dd_trace"); AzureFunctionsGeneratedTracesPipeName = tracesPipeName; - Logging.Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); + Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); } if (string.IsNullOrEmpty(metricsPipeName)) { metricsPipeName = GenerateUniquePipeName("dd_dogstatsd"); AzureFunctionsGeneratedMetricsPipeName = metricsPipeName; - Logging.Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); + Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); } } @@ -254,6 +257,31 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return string.IsNullOrEmpty(traceHostname) ? DefaultDogstatsdHostname : traceHostname; } + /// + /// Generates a unique pipe name by appending a GUID to the base name. + /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. + /// + /// The base name for the pipe + /// A unique pipe name in the format {base}_{guid} + private static string GenerateUniquePipeName(string baseName) + { + // Validate base pipe name length before appending GUID + // Windows pipe path format: \\.\pipe\{base}_{guid} + // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 + const int maxBaseLength = 214; + + if (baseName.Length > maxBaseLength) + { + Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); + baseName = baseName.Substring(0, maxBaseLength); + } + + var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) + var uniqueName = $"{baseName}_{guid}"; + + return uniqueName; + } + private MetricsTransportSettings ConfigureMetricsTransport(string? metricsUrl, string? traceAgentUrl, string? agentHost, int dogStatsdPort, string? metricsPipeName, string? metricsUnixDomainSocketPath) { if (!string.IsNullOrEmpty(metricsUrl) && TryGetMetricsUriAndTransport(metricsUrl!, out var settingsFromUri)) @@ -459,31 +487,6 @@ private void RecordTraceTransport(string transport, ConfigurationOrigins origin private readonly record struct MetricsTransportSettings(MetricsTransportType Transport, string Hostname = DefaultDogstatsdHostname, int DogStatsdPort = 0, string? UdsPath = null, string? PipeName = null); - /// - /// Generates a unique pipe name by appending a GUID to the base name. - /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. - /// - /// The base name for the pipe - /// A unique pipe name in the format {base}_{guid} - private static string GenerateUniquePipeName(string baseName) - { - // Validate base pipe name length before appending GUID - // Windows pipe path format: \\.\pipe\{base}_{guid} - // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 - const int maxBaseLength = 214; - - if (baseName.Length > maxBaseLength) - { - Logging.Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); - baseName = baseName.Substring(0, maxBaseLength); - } - - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) - var uniqueName = $"{baseName}_{guid}"; - - return uniqueName; - } - /// /// These contain the "raw" settings loaded from config. If these don't change, the exporter settings also won't change /// diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 3c9c56bf7d70..cfc3e86ece7b 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 79; + public const int Length = 80; /// /// Returns the string representation of the value. @@ -109,6 +109,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict => nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), Datadog.Trace.Configuration.IntegrationId.Hangfire => nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), Datadog.Trace.Configuration.IntegrationId.OpenFeature => nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat => nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), _ => value.ToString(), }; @@ -201,6 +202,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict, Datadog.Trace.Configuration.IntegrationId.Hangfire, Datadog.Trace.Configuration.IntegrationId.OpenFeature, + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, }; /// @@ -293,5 +295,6 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs index 937b0fffb12c..1082a62da2ba 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs @@ -259,6 +259,9 @@ public static string[] GetAllIntegrationEnabledKeys() => "DD_TRACE_OPENFEATURE_ENABLED", "DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", "DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", "DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE", + "DD_TRACE_SERVERLESSCOMPAT_ENABLED", "DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", "DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", "DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE", ]; /// /// Gets the configuration keys for the specified integration name. @@ -348,6 +351,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ENABLED", "DD_DatadogTraceVersionConflict_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ENABLED", ["DD_TRACE_Hangfire_ENABLED", "DD_Hangfire_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ENABLED", ["DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ENABLED", ["DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED"]), _ => GetIntegrationEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -439,6 +443,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_ENABLED", "DD_DatadogTraceVersionConflict_ANALYTICS_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_ENABLED", ["DD_TRACE_Hangfire_ANALYTICS_ENABLED", "DD_Hangfire_ANALYTICS_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", ["DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", ["DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED"]), _ => GetIntegrationAnalyticsEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -530,6 +535,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE", "DD_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_Hangfire_ANALYTICS_SAMPLE_RATE", "DD_Hangfire_ANALYTICS_SAMPLE_RATE"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE"]), _ => GetIntegrationAnalyticsSampleRateKeysFallback(integrationName) // we should never get here }; diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 3c9c56bf7d70..cfc3e86ece7b 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 79; + public const int Length = 80; /// /// Returns the string representation of the value. @@ -109,6 +109,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict => nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), Datadog.Trace.Configuration.IntegrationId.Hangfire => nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), Datadog.Trace.Configuration.IntegrationId.OpenFeature => nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat => nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), _ => value.ToString(), }; @@ -201,6 +202,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict, Datadog.Trace.Configuration.IntegrationId.Hangfire, Datadog.Trace.Configuration.IntegrationId.OpenFeature, + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, }; /// @@ -293,5 +295,6 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs index 937b0fffb12c..1082a62da2ba 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs @@ -259,6 +259,9 @@ public static string[] GetAllIntegrationEnabledKeys() => "DD_TRACE_OPENFEATURE_ENABLED", "DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", "DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", "DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE", + "DD_TRACE_SERVERLESSCOMPAT_ENABLED", "DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", "DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", "DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE", ]; /// /// Gets the configuration keys for the specified integration name. @@ -348,6 +351,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ENABLED", "DD_DatadogTraceVersionConflict_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ENABLED", ["DD_TRACE_Hangfire_ENABLED", "DD_Hangfire_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ENABLED", ["DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ENABLED", ["DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED"]), _ => GetIntegrationEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -439,6 +443,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_ENABLED", "DD_DatadogTraceVersionConflict_ANALYTICS_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_ENABLED", ["DD_TRACE_Hangfire_ANALYTICS_ENABLED", "DD_Hangfire_ANALYTICS_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", ["DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", ["DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED"]), _ => GetIntegrationAnalyticsEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -530,6 +535,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE", "DD_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_Hangfire_ANALYTICS_SAMPLE_RATE", "DD_Hangfire_ANALYTICS_SAMPLE_RATE"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE"]), _ => GetIntegrationAnalyticsSampleRateKeysFallback(integrationName) // we should never get here }; diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 378f71fa6a43..12685db7a87e 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -624,6 +624,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation" => Datadog.Trace.Configuration.IntegrationId.Serilog, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration" + => Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 3c9c56bf7d70..cfc3e86ece7b 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 79; + public const int Length = 80; /// /// Returns the string representation of the value. @@ -109,6 +109,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict => nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), Datadog.Trace.Configuration.IntegrationId.Hangfire => nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), Datadog.Trace.Configuration.IntegrationId.OpenFeature => nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat => nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), _ => value.ToString(), }; @@ -201,6 +202,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict, Datadog.Trace.Configuration.IntegrationId.Hangfire, Datadog.Trace.Configuration.IntegrationId.OpenFeature, + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, }; /// @@ -293,5 +295,6 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs index 937b0fffb12c..1082a62da2ba 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs @@ -259,6 +259,9 @@ public static string[] GetAllIntegrationEnabledKeys() => "DD_TRACE_OPENFEATURE_ENABLED", "DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", "DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", "DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE", + "DD_TRACE_SERVERLESSCOMPAT_ENABLED", "DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", "DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", "DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE", ]; /// /// Gets the configuration keys for the specified integration name. @@ -348,6 +351,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ENABLED", "DD_DatadogTraceVersionConflict_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ENABLED", ["DD_TRACE_Hangfire_ENABLED", "DD_Hangfire_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ENABLED", ["DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ENABLED", ["DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED"]), _ => GetIntegrationEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -439,6 +443,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_ENABLED", "DD_DatadogTraceVersionConflict_ANALYTICS_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_ENABLED", ["DD_TRACE_Hangfire_ANALYTICS_ENABLED", "DD_Hangfire_ANALYTICS_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", ["DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", ["DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED"]), _ => GetIntegrationAnalyticsEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -530,6 +535,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE", "DD_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_Hangfire_ANALYTICS_SAMPLE_RATE", "DD_Hangfire_ANALYTICS_SAMPLE_RATE"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE"]), _ => GetIntegrationAnalyticsSampleRateKeysFallback(integrationName) // we should never get here }; diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 81a152372fb7..9af0c3b70e9d 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -619,6 +619,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation" => Datadog.Trace.Configuration.IntegrationId.Serilog, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration" + => Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 3c9c56bf7d70..cfc3e86ece7b 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 79; + public const int Length = 80; /// /// Returns the string representation of the value. @@ -109,6 +109,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict => nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), Datadog.Trace.Configuration.IntegrationId.Hangfire => nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), Datadog.Trace.Configuration.IntegrationId.OpenFeature => nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat => nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), _ => value.ToString(), }; @@ -201,6 +202,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict, Datadog.Trace.Configuration.IntegrationId.Hangfire, Datadog.Trace.Configuration.IntegrationId.OpenFeature, + Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, }; /// @@ -293,5 +295,6 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.DatadogTraceVersionConflict), nameof(Datadog.Trace.Configuration.IntegrationId.Hangfire), nameof(Datadog.Trace.Configuration.IntegrationId.OpenFeature), + nameof(Datadog.Trace.Configuration.IntegrationId.ServerlessCompat), }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs index 937b0fffb12c..1082a62da2ba 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationNameToKeys.g.cs @@ -259,6 +259,9 @@ public static string[] GetAllIntegrationEnabledKeys() => "DD_TRACE_OPENFEATURE_ENABLED", "DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", "DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED", "DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", "DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE", + "DD_TRACE_SERVERLESSCOMPAT_ENABLED", "DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", "DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED", + "DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", "DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE", ]; /// /// Gets the configuration keys for the specified integration name. @@ -348,6 +351,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ENABLED", "DD_DatadogTraceVersionConflict_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ENABLED", ["DD_TRACE_Hangfire_ENABLED", "DD_Hangfire_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ENABLED", ["DD_TRACE_OpenFeature_ENABLED", "DD_OpenFeature_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ENABLED", ["DD_TRACE_ServerlessCompat_ENABLED", "DD_ServerlessCompat_ENABLED"]), _ => GetIntegrationEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -439,6 +443,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_ENABLED", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_ENABLED", "DD_DatadogTraceVersionConflict_ANALYTICS_ENABLED"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_ENABLED", ["DD_TRACE_Hangfire_ANALYTICS_ENABLED", "DD_Hangfire_ANALYTICS_ENABLED"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_ENABLED", ["DD_TRACE_OpenFeature_ANALYTICS_ENABLED", "DD_OpenFeature_ANALYTICS_ENABLED"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_ENABLED", ["DD_TRACE_ServerlessCompat_ANALYTICS_ENABLED", "DD_ServerlessCompat_ANALYTICS_ENABLED"]), _ => GetIntegrationAnalyticsEnabledKeysFallback(integrationName) // we should never get here }; /// @@ -530,6 +535,7 @@ public static System.Collections.Generic.KeyValuePair GetInteg "DatadogTraceVersionConflict" => new("DD_TRACE_DATADOGTRACEVERSIONCONFLICT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE", "DD_DatadogTraceVersionConflict_ANALYTICS_SAMPLE_RATE"]), "Hangfire" => new("DD_TRACE_HANGFIRE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_Hangfire_ANALYTICS_SAMPLE_RATE", "DD_Hangfire_ANALYTICS_SAMPLE_RATE"]), "OpenFeature" => new("DD_TRACE_OPENFEATURE_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_OpenFeature_ANALYTICS_SAMPLE_RATE", "DD_OpenFeature_ANALYTICS_SAMPLE_RATE"]), + "ServerlessCompat" => new("DD_TRACE_SERVERLESSCOMPAT_ANALYTICS_SAMPLE_RATE", ["DD_TRACE_ServerlessCompat_ANALYTICS_SAMPLE_RATE", "DD_ServerlessCompat_ANALYTICS_SAMPLE_RATE"]), _ => GetIntegrationAnalyticsSampleRateKeysFallback(integrationName) // we should never get here }; diff --git a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp index bff0c2b3a9ae..49df786ab77d 100644 --- a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp +++ b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp @@ -1100,6 +1100,8 @@ std::vector callTargets = {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,2,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Pipeline.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,1,4,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.LoggerConfiguration"),(WCHAR*)WStr("CreateLogger"),sig124,1,1,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation"),CallTargetKind::Default,1,15}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,12}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,12}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig002,5,4,0,0,6,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig003,6,6,0,0,10,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Microsoft.Data.SqlClient"),(WCHAR*)WStr("Microsoft.Data.SqlClient.SqlCommand"),(WCHAR*)WStr("ExecuteDbDataReader"),sig140,2,1,0,0,7,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteReaderWithBehaviorIntegration"),CallTargetKind::Default,1,15}, From b380a24cc98f00aa8a2cc32a73f8307e36614c54 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Feb 2026 19:15:29 -0500 Subject: [PATCH 08/38] Add named pipes to packages map --- tracer/build/_build/Honeypot/IntegrationGroups.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tracer/build/_build/Honeypot/IntegrationGroups.cs b/tracer/build/_build/Honeypot/IntegrationGroups.cs index a2b038ca450c..698ef688254f 100644 --- a/tracer/build/_build/Honeypot/IntegrationGroups.cs +++ b/tracer/build/_build/Honeypot/IntegrationGroups.cs @@ -129,7 +129,10 @@ static IntegrationMap() NugetPackages.Add("Datadog.Trace", new string[] { }); NugetPackages.Add("Datadog.Trace.Manual", new string[] { }); NugetPackages.Add("Datadog.Trace.OpenTracing", new string[] { }); - + + // Serverless + NugetPackages.Add("Datadog.Serverless.Compat", new string[] { }); + // Feature Flags NugetPackages.Add("Datadog.FeatureFlags.OpenFeature", new string[] { }); NugetPackages.Add("OpenFeature", new string[] { }); From 46cef639bb41500629938715d89b4ba5df8af272 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Feb 2026 09:31:35 -0500 Subject: [PATCH 09/38] Include serverless classes in .net standard 2.0 build --- ...CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs | 2 +- .../CompatibilityLayer_CalculateTracePipeName_Integration.cs | 2 +- .../Serverless/ServerlessCompatPipeNameHelper.cs | 2 +- .../Serverless/ServerlessCompatIntegrationTests.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 738723134bd7..72ba4c22b937 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -5,7 +5,7 @@ #nullable enable -#if NETCOREAPP +#if !NETFRAMEWORK using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 2b3367a9ee48..71c8fbbf5760 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -5,7 +5,7 @@ #nullable enable -#if NETCOREAPP +#if !NETFRAMEWORK using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 71d0cb78b248..2b247cd9deed 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -5,7 +5,7 @@ #nullable enable -#if NETCOREAPP +#if !NETFRAMEWORK using System; using Datadog.Trace.Logging; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 9b0762a2acec..45478cc37e69 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // -#if NETCOREAPP +#if !NETFRAMEWORK using System; using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; using Datadog.Trace.ClrProfiler.CallTarget; From b7346a66b7275e809ef467586be4061a5aad58cd Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Feb 2026 09:58:09 -0500 Subject: [PATCH 10/38] Update source-generated files for Serverless compat instrumentation Co-Authored-By: Claude Sonnet 4.5 --- .../InstrumentationDefinitions.g.cs | 3 +++ .../Generated/generated_calltargets.g.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 81a152372fb7..9af0c3b70e9d 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -619,6 +619,9 @@ internal static bool IsInstrumentedAssembly(string assemblyName) or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation" => Datadog.Trace.Configuration.IntegrationId.Serilog, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration" + or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration" + => Datadog.Trace.Configuration.IntegrationId.ServerlessCompat, "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0" => Datadog.Trace.Configuration.IntegrationId.ServiceStackRedis, diff --git a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp index 49df786ab77d..30a9f1082a6f 100644 --- a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp +++ b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp @@ -1100,8 +1100,8 @@ std::vector callTargets = {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,2,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Pipeline.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,1,4,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.LoggerConfiguration"),(WCHAR*)WStr("CreateLogger"),sig124,1,1,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation"),CallTargetKind::Default,1,15}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,12}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,12}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig002,5,4,0,0,6,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig003,6,6,0,0,10,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Microsoft.Data.SqlClient"),(WCHAR*)WStr("Microsoft.Data.SqlClient.SqlCommand"),(WCHAR*)WStr("ExecuteDbDataReader"),sig140,2,1,0,0,7,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteReaderWithBehaviorIntegration"),CallTargetKind::Default,1,15}, From 5b54c47b01c7ed580f9abd2a7b9ec5b3d9bc8e81 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Feb 2026 13:03:22 -0500 Subject: [PATCH 11/38] Modify unit tests to ignore compat values --- ..._CalculateDogStatsDPipeName_Integration.cs | 4 +- ...ayer_CalculateTracePipeName_Integration.cs | 4 +- .../ServerlessCompatPipeNameHelper.cs | 7 +- .../ServerlessCompatIntegrationTests.cs | 263 ++++++++++++------ 4 files changed, 180 insertions(+), 98 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 72ba4c22b937..c5b4a3cba8e5 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -69,10 +69,10 @@ internal static CallTargetReturn OnMethodEnd( if (_cachedDogStatsDPipeName == null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // Otherwise, generate a unique pipe name as fallback + // Otherwise, generate a unique pipe name with default base + // The tracer controls the pipe name, not the compat layer _cachedDogStatsDPipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - returnValue, "dd_dogstatsd", "DogStatsD"); } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 71c8fbbf5760..eda10345399f 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -69,10 +69,10 @@ internal static CallTargetReturn OnMethodEnd( if (_cachedTracePipeName == null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // Otherwise, generate a unique pipe name as fallback + // Otherwise, generate a unique pipe name with default base + // The tracer controls the pipe name, not the compat layer _cachedTracePipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - returnValue, "dd_trace", "trace"); } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 2b247cd9deed..87ae5abf3dc4 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -23,14 +23,11 @@ internal static class ServerlessCompatPipeNameHelper /// Generates a unique pipe name by appending a GUID to the base name. /// Validates and truncates the base name if necessary to ensure the full pipe path stays within Windows limits. /// - /// The base name calculated by the compat layer, or null - /// The default base name to use if compat layer returns null + /// The base name for the pipe /// The type of pipe for logging (e.g., "trace" or "DogStatsD") /// A unique pipe name in the format {base}_{guid} - internal static string GenerateUniquePipeName(string? compatLayerBaseName, string defaultBaseName, string pipeType) + internal static string GenerateUniquePipeName(string baseName, string pipeType) { - var baseName = compatLayerBaseName ?? defaultBaseName; - // Validate base pipe name length before appending GUID // Windows pipe path format: \\.\pipe\{base}_{guid} // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 45478cc37e69..0ef7ded3b390 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -3,10 +3,14 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // +#nullable enable + #if !NETFRAMEWORK using System; +using System.Reflection; using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; using FluentAssertions; using Xunit; @@ -14,134 +18,215 @@ namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless; public class ServerlessCompatIntegrationTests { - [Theory] - [InlineData(null, "dd_trace")] // Null base name should use default - [InlineData("custom_pipe", "custom_pipe")] // Custom base name should be used - [InlineData("short", "short")] // Short name should work - [InlineData("this_is_a_very_long_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_characters_before_appending_guid_suffix_extra_padding", "this_is_a_very_long_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_cha")] // Long name should be truncated to 214 chars - public void CalculateTracePipeName_GeneratesValidUniquePipeName(string compatLayerValue, string expectedBase) + [Fact] + public void TracePipeName_WithPreGeneratedName_ReturnsTracerValue() + { + // Arrange + ResetCachedPipeNames(); + const string preGeneratedName = "dd_trace_test123"; + const string compatLayerName = "dd_trace_compat456"; + SetExporterSettingsGeneratedNames(preGeneratedName, null); + + // Act + var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, + compatLayerName, + null!, + default); + + // Assert + result.GetReturnValue().Should().Be(preGeneratedName); + } + + [Fact] + public void TracePipeName_WithoutPreGeneratedName_GeneratesUniqueName() + { + // Arrange + ResetCachedPipeNames(); + const string compatLayerName = "dd_trace_compat456"; + SetExporterSettingsGeneratedNames(null, null); + + // Act + var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, + compatLayerName, + null!, + default); + + // Assert + var pipeName = result.GetReturnValue(); + pipeName.Should().NotBe(compatLayerName); + pipeName.Should().StartWith("dd_trace_"); + pipeName.Should().MatchRegex(@"^dd_trace_[a-f0-9]{32}$"); // base_guid format + } + + [Fact] + public void TracePipeName_CalledMultipleTimes_ReturnsCachedValue() { // Arrange - var state = new CallTargetState(); + ResetCachedPipeNames(); + SetExporterSettingsGeneratedNames(null, null); - // Act - First call generates the pipe name + // Act var result1 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - instance: null, - returnValue: compatLayerValue, - exception: null, - in state); + null!, + "compat_name_1", + null!, + default); - // Second call should return the same cached value var result2 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - instance: null, - returnValue: compatLayerValue, - exception: null, - in state); + null!, + "compat_name_2", + null!, + default); // Assert - result1.GetReturnValue().Should().NotBeNullOrEmpty(); - result2.GetReturnValue().Should().NotBeNullOrEmpty(); - - // Should return the same cached value result1.GetReturnValue().Should().Be(result2.GetReturnValue()); + } - // Should start with expected base name - result1.GetReturnValue().Should().StartWith(expectedBase); + [Fact] + public void DogStatsDPipeName_WithPreGeneratedName_ReturnsTracerValue() + { + // Arrange + ResetCachedPipeNames(); + const string preGeneratedName = "dd_dogstatsd_test123"; + const string compatLayerName = "dd_dogstatsd_compat456"; + SetExporterSettingsGeneratedNames(null, preGeneratedName); - // Should have GUID suffix (underscore + 32 hex chars) - result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); + // Act + var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, + compatLayerName, + null!, + default); - // If input was longer than 214, verify truncation - if (compatLayerValue?.Length > 214) - { - var pipeName = result1.GetReturnValue(); - var baseNamePart = pipeName.Substring(0, pipeName.LastIndexOf('_')); - baseNamePart.Length.Should().Be(214); - } + // Assert + result.GetReturnValue().Should().Be(preGeneratedName); } [Fact] - public void CalculateTracePipeName_HandlesException_ReturnsFallback() + public void DogStatsDPipeName_WithoutPreGeneratedName_GeneratesUniqueName() { // Arrange - var state = new CallTargetState(); - var expectedException = new InvalidOperationException("Test exception"); - var fallbackValue = "fallback_pipe_name"; + ResetCachedPipeNames(); + const string compatLayerName = "dd_dogstatsd_compat456"; + SetExporterSettingsGeneratedNames(null, null); - // Act - Pass exception to OnMethodEnd - var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - instance: null, - returnValue: fallbackValue, - exception: expectedException, - in state); + // Act + var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, + compatLayerName, + null!, + default); - // Assert - Should return the fallback value when exception is present - result.GetReturnValue().Should().Be(fallbackValue); + // Assert + var pipeName = result.GetReturnValue(); + pipeName.Should().NotBe(compatLayerName); + pipeName.Should().StartWith("dd_dogstatsd_"); + pipeName.Should().MatchRegex(@"^dd_dogstatsd_[a-f0-9]{32}$"); // base_guid format } - [Theory] - [InlineData(null, "dd_dogstatsd")] // Null base name should use default - [InlineData("custom_statsd", "custom_statsd")] // Custom base name should be used - [InlineData("short", "short")] // Short name should work - [InlineData("this_is_a_very_long_dogstatsd_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_214_characters_before_appending_the_guid_suffix", "this_is_a_very_long_dogstatsd_pipe_name_that_exceeds_the_maximum_allowed_length_for_windows_named_pipes_which_is_256_characters_total_including_the_prefix_and_we_need_to_make_sure_this_gets_truncated_properly_to_")] // Long name should be truncated to 214 chars - public void CalculateDogStatsDPipeName_GeneratesValidUniquePipeName(string compatLayerValue, string expectedBase) + [Fact] + public void DogStatsDPipeName_CalledMultipleTimes_ReturnsCachedValue() { // Arrange - var state = new CallTargetState(); + ResetCachedPipeNames(); + SetExporterSettingsGeneratedNames(null, null); - // Act - First call generates the pipe name + // Act var result1 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - instance: null, - returnValue: compatLayerValue, - exception: null, - in state); + null!, + "compat_name_1", + null!, + default); - // Second call should return the same cached value var result2 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - instance: null, - returnValue: compatLayerValue, - exception: null, - in state); + null!, + "compat_name_2", + null!, + default); // Assert - result1.GetReturnValue().Should().NotBeNullOrEmpty(); - result2.GetReturnValue().Should().NotBeNullOrEmpty(); - - // Should return the same cached value result1.GetReturnValue().Should().Be(result2.GetReturnValue()); + } - // Should start with expected base name - result1.GetReturnValue().Should().StartWith(expectedBase); + [Theory] + [InlineData("trace")] + [InlineData("dogstatsd")] + public void OnMethodEnd_WithException_PassesThroughOriginalValue(string pipeType) + { + // Arrange + ResetCachedPipeNames(); + const string originalValue = "original_pipe_name"; + var exception = new InvalidOperationException("Test exception"); - // Should have GUID suffix (underscore + 32 hex chars) - result1.GetReturnValue().Should().MatchRegex($"^{System.Text.RegularExpressions.Regex.Escape(expectedBase)}_[0-9a-f]{{32}}$"); + // Act + CallTargetReturn result = pipeType == "trace" + ? CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd(null!, originalValue, exception, default) + : CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd(null!, originalValue, exception, default); - // If input was longer than 214, verify truncation - if (compatLayerValue?.Length > 214) - { - var pipeName = result1.GetReturnValue(); - var baseNamePart = pipeName.Substring(0, pipeName.LastIndexOf('_')); - baseNamePart.Length.Should().Be(214); - } + // Assert + result.GetReturnValue().Should().Be(originalValue); + } + + [Theory] + [InlineData("dd_trace", "trace")] + [InlineData("dd_dogstatsd", "DogStatsD")] + public void GeneratedPipeName_HasCorrectFormat(string baseName, string pipeType) + { + // Act + var pipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, pipeType); + + // Assert + pipeName.Should().StartWith($"{baseName}_"); + pipeName.Should().MatchRegex($@"^{baseName}_[a-f0-9]{{32}}$"); // base_guid with 32 hex chars + pipeName.Length.Should().BeLessOrEqualTo(247); // 214 base + 1 underscore + 32 guid = 247 max } [Fact] - public void CalculateDogStatsDPipeName_HandlesException_ReturnsFallback() + public void GeneratedPipeName_WithLongBaseName_Truncates() { - // Arrange - var state = new CallTargetState(); - var expectedException = new InvalidOperationException("Test exception"); - var fallbackValue = "fallback_dogstatsd_pipe"; + // Arrange - create a base name longer than 214 characters + var longBaseName = new string('a', 220); - // Act - Pass exception to OnMethodEnd - var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - instance: null, - returnValue: fallbackValue, - exception: expectedException, - in state); + // Act + var pipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(longBaseName, "test"); + + // Assert + // Should be truncated to 214 + 1 underscore + 32 guid = 247 total + pipeName.Length.Should().Be(247); + pipeName.Should().MatchRegex(@"^a{214}_[a-f0-9]{32}$"); + } + + // Clear cached values between tests using reflection + private static void ResetCachedPipeNames() + { + var traceIntegrationType = typeof(CompatibilityLayer_CalculateTracePipeName_Integration); + var dogstatsdIntegrationType = typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration); + + var traceCacheField = traceIntegrationType.GetField("_cachedTracePipeName", BindingFlags.NonPublic | BindingFlags.Static); + var dogstatsdCacheField = dogstatsdIntegrationType.GetField("_cachedDogStatsDPipeName", BindingFlags.NonPublic | BindingFlags.Static); + + traceCacheField?.SetValue(null, null); + dogstatsdCacheField?.SetValue(null, null); + + // Also clear ExporterSettings generated names + var exporterSettingsType = typeof(ExporterSettings); + var tracesPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var metricsPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); + + tracesPipeNameProp?.SetValue(null, null); + metricsPipeNameProp?.SetValue(null, null); + } + + private static void SetExporterSettingsGeneratedNames(string? tracePipeName, string? metricsPipeName) + { + var exporterSettingsType = typeof(ExporterSettings); + var tracesPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var metricsPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); - // Assert - Should return the fallback value when exception is present - result.GetReturnValue().Should().Be(fallbackValue); + tracesPipeNameProp?.SetValue(null, tracePipeName); + metricsPipeNameProp?.SetValue(null, metricsPipeName); } } #endif From e4c217bd060233a9dda35a33f9f90cdfb55279e7 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Feb 2026 16:58:47 -0500 Subject: [PATCH 12/38] More test fixes --- .../Configuration/ExporterSettings.cs | 18 +- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- .../MetricsTelemetryCollector_Count.g.cs | 202 +++++++++--------- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- .../MetricsTelemetryCollector_Count.g.cs | 202 +++++++++--------- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- .../MetricsTelemetryCollector_Count.g.cs | 202 +++++++++--------- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- .../MetricsTelemetryCollector_Count.g.cs | 202 +++++++++--------- ...MetricsTelemetryCollector_CountShared.g.cs | 8 +- .../Metrics/IntegrationIdExtensions.cs | 1 + .../Telemetry/Metrics/MetricTags.cs | 3 +- 15 files changed, 473 insertions(+), 421 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index b58c41c2883f..eec76e893d67 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -29,6 +29,16 @@ public sealed partial class ExporterSettings { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(ExporterSettings)); + /// + /// Backing field for AzureFunctionsGeneratedTracesPipeName. + /// + private static string? _azureFunctionsGeneratedTracesPipeName; + + /// + /// Backing field for AzureFunctionsGeneratedMetricsPipeName. + /// + private static string? _azureFunctionsGeneratedMetricsPipeName; + /// /// Allows overriding of file system access for tests. /// @@ -101,14 +111,14 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi if (string.IsNullOrEmpty(tracesPipeName)) { tracesPipeName = GenerateUniquePipeName("dd_trace"); - AzureFunctionsGeneratedTracesPipeName = tracesPipeName; + _azureFunctionsGeneratedTracesPipeName = tracesPipeName; Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); } if (string.IsNullOrEmpty(metricsPipeName)) { metricsPipeName = GenerateUniquePipeName("dd_dogstatsd"); - AzureFunctionsGeneratedMetricsPipeName = metricsPipeName; + _azureFunctionsGeneratedMetricsPipeName = metricsPipeName; Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); } } @@ -149,14 +159,14 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi /// This is set when running in Azure Functions without explicit pipe name configuration. /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. /// - internal static string? AzureFunctionsGeneratedTracesPipeName { get; private set; } + internal static string? AzureFunctionsGeneratedTracesPipeName => _azureFunctionsGeneratedTracesPipeName; /// /// Gets the generated metrics pipe name for Azure Functions coordination. /// This is set when running in Azure Functions without explicit pipe name configuration. /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. /// - internal static string? AzureFunctionsGeneratedMetricsPipeName { get; private set; } + internal static string? AzureFunctionsGeneratedMetricsPipeName => _azureFunctionsGeneratedMetricsPipeName; /// /// Gets the Uri where the Tracer can connect to the Agent. diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs index bfaf729c064b..074a939c1ce9 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class CiVisibilityMetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs index e382010a658c..8cc8110fcc6a 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountLength = 656; + private const int CountLength = 658; /// /// Creates the buffer for the values. @@ -109,35 +109,36 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // spans_finished, index = 88 + new(new[] { "integration_name:serverlesscompat" }), + // spans_finished, index = 89 new(null), - // spans_enqueued_for_serialization, index = 89 + // spans_enqueued_for_serialization, index = 90 new(new[] { "reason:p0_keep" }), new(new[] { "reason:single_span_sampling" }), new(new[] { "reason:default" }), - // spans_dropped, index = 92 + // spans_dropped, index = 93 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_segments_created, index = 96 + // trace_segments_created, index = 97 new(new[] { "new_continued:new" }), new(new[] { "new_continued:continued" }), - // trace_chunks_enqueued_for_serialization, index = 98 + // trace_chunks_enqueued_for_serialization, index = 99 new(new[] { "reason:p0_keep" }), new(new[] { "reason:default" }), - // trace_chunks_dropped, index = 100 + // trace_chunks_dropped, index = 101 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_chunks_sent, index = 104 + // trace_chunks_sent, index = 105 new(null), - // trace_segments_closed, index = 105 + // trace_segments_closed, index = 106 new(null), - // trace_api.requests, index = 106 + // trace_api.requests, index = 107 new(null), - // trace_api.responses, index = 107 + // trace_api.responses, index = 108 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -160,33 +161,33 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // trace_api.errors, index = 129 + // trace_api.errors, index = 130 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // trace_partial_flush.count, index = 132 + // trace_partial_flush.count, index = 133 new(new[] { "reason:large_trace" }), new(new[] { "reason:single_span_ingestion" }), - // context_header_style.injected, index = 134 + // context_header_style.injected, index = 135 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header_style.extracted, index = 139 + // context_header_style.extracted, index = 140 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header.truncated, index = 144 + // context_header.truncated, index = 145 new(new[] { "truncation_reason:baggage_item_count_exceeded" }), new(new[] { "truncation_reason:baggage_byte_count_exceeded" }), - // context_header_style.malformed, index = 146 + // context_header_style.malformed, index = 147 new(new[] { "header_style:baggage" }), - // stats_api.requests, index = 147 + // stats_api.requests, index = 148 new(null), - // stats_api.responses, index = 148 + // stats_api.responses, index = 149 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -209,11 +210,11 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // stats_api.errors, index = 170 + // stats_api.errors, index = 171 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // otel.env.hiding, index = 173 + // otel.env.hiding, index = 174 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -304,7 +305,7 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.env.invalid, index = 263 + // otel.env.invalid, index = 264 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -395,30 +396,30 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.metrics_export_attempts, index = 353 + // otel.metrics_export_attempts, index = 354 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_successes, index = 357 + // otel.metrics_export_successes, index = 358 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_partial_successes, index = 361 + // otel.metrics_export_partial_successes, index = 362 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_failures, index = 365 + // otel.metrics_export_failures, index = 366 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // telemetry_api.requests, index = 369 + // telemetry_api.requests, index = 370 new(new[] { "endpoint:agent" }), new(new[] { "endpoint:agentless" }), - // telemetry_api.responses, index = 371 + // telemetry_api.responses, index = 372 new(new[] { "endpoint:agent", "status_code:200" }), new(new[] { "endpoint:agent", "status_code:201" }), new(new[] { "endpoint:agent", "status_code:202" }), @@ -463,18 +464,18 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "endpoint:agentless", "status_code:503" }), new(new[] { "endpoint:agentless", "status_code:504" }), new(new[] { "endpoint:agentless", "status_code:5xx" }), - // telemetry_api.errors, index = 415 + // telemetry_api.errors, index = 416 new(new[] { "endpoint:agent", "type:timeout" }), new(new[] { "endpoint:agent", "type:network" }), new(new[] { "endpoint:agent", "type:status_code" }), new(new[] { "endpoint:agentless", "type:timeout" }), new(new[] { "endpoint:agentless", "type:network" }), new(new[] { "endpoint:agentless", "type:status_code" }), - // version_conflict_tracers_created, index = 421 + // version_conflict_tracers_created, index = 422 new(null), - // unsupported_custom_instrumentation_services, index = 422 + // unsupported_custom_instrumentation_services, index = 423 new(null), - // direct_log_logs, index = 423 + // direct_log_logs, index = 424 new(new[] { "integration_name:datadog" }), new(new[] { "integration_name:opentracing" }), new(new[] { "integration_name:version_conflict" }), @@ -559,9 +560,10 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // direct_log_api.requests, index = 507 + new(new[] { "integration_name:serverlesscompat" }), + // direct_log_api.requests, index = 509 new(null), - // direct_log_api.responses, index = 508 + // direct_log_api.responses, index = 510 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -584,17 +586,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // direct_log_api.errors, index = 530 + // direct_log_api.errors, index = 532 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // waf.init, index = 533 + // waf.init, index = 535 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.updates, index = 535 + // waf.updates, index = 537 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.requests, index = 537 + // waf.requests, index = 539 new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), @@ -603,17 +605,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:true", "block_failure:false", "rate_limited:false", "input_truncated:true" }), - // waf.input_truncated, index = 545 + // waf.input_truncated, index = 547 new(new[] { "truncation_reason:string_too_long" }), new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), - // rasp.rule.eval, index = 548 + // rasp.rule.eval, index = 550 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.rule.match, index = 553 + // rasp.rule.match, index = 555 new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:sql_injection" }), @@ -629,29 +631,29 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 568 + // rasp.timeout, index = 570 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 573 + // instrum.user_auth.missing_user_id, index = 575 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // instrum.user_auth.missing_user_login, index = 577 + // instrum.user_auth.missing_user_login, index = 579 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // sdk.event, index = 581 + // sdk.event, index = 583 new(new[] { "event_type:login_success", "sdk_version:v1" }), new(new[] { "event_type:login_success", "sdk_version:v2" }), new(new[] { "event_type:login_failure", "sdk_version:v1" }), new(new[] { "event_type:login_failure", "sdk_version:v2" }), new(new[] { "event_type:custom", "sdk_version:v1" }), - // executed.source, index = 586 + // executed.source, index = 588 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -666,9 +668,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "source_type:http.request.uri" }), new(new[] { "source_type:grpc.request.body" }), new(new[] { "source_type:sql.row.value" }), - // executed.propagation, index = 600 + // executed.propagation, index = 602 new(null), - // executed.sink, index = 601 + // executed.sink, index = 603 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -696,9 +698,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "vulnerability_type:directory_listing_leak" }), new(new[] { "vulnerability_type:session_timeout" }), new(new[] { "vulnerability_type:email_html_injection" }), - // request.tainted, index = 628 + // request.tainted, index = 630 new(null), - // suppressed.vulnerabilities, index = 629 + // suppressed.vulnerabilities, index = 631 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -734,7 +736,7 @@ private static AggregatedMetric[] GetCountBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountEntryCounts { get; } - = new int[]{ 4, 84, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 84, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 85, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 85, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -750,285 +752,285 @@ public void RecordCountSpanCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.In public void RecordCountSpanFinished(int increment = 1) { - Interlocked.Add(ref _buffer.Count[88], increment); + Interlocked.Add(ref _buffer.Count[89], increment); } public void RecordCountSpanEnqueuedForSerialization(Datadog.Trace.Telemetry.Metrics.MetricTags.SpanEnqueueReason tag, int increment = 1) { - var index = 89 + (int)tag; + var index = 90 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountSpanDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 92 + (int)tag; + var index = 93 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceSegmentCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceContinuation tag, int increment = 1) { - var index = 96 + (int)tag; + var index = 97 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkEnqueued(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceChunkEnqueueReason tag, int increment = 1) { - var index = 98 + (int)tag; + var index = 99 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 100 + (int)tag; + var index = 101 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkSent(int increment = 1) { - Interlocked.Add(ref _buffer.Count[104], increment); + Interlocked.Add(ref _buffer.Count[105], increment); } public void RecordCountTraceSegmentsClosed(int increment = 1) { - Interlocked.Add(ref _buffer.Count[105], increment); + Interlocked.Add(ref _buffer.Count[106], increment); } public void RecordCountTraceApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[106], increment); + Interlocked.Add(ref _buffer.Count[107], increment); } public void RecordCountTraceApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 107 + (int)tag; + var index = 108 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 129 + (int)tag; + var index = 130 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTracePartialFlush(Datadog.Trace.Telemetry.Metrics.MetricTags.PartialFlushReason tag, int increment = 1) { - var index = 132 + (int)tag; + var index = 133 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleInjected(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 134 + (int)tag; + var index = 135 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleExtracted(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 139 + (int)tag; + var index = 140 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderTruncationReason tag, int increment = 1) { - var index = 144 + (int)tag; + var index = 145 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderMalformed(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderMalformed tag, int increment = 1) { - var index = 146 + (int)tag; + var index = 147 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[147], increment); + Interlocked.Add(ref _buffer.Count[148], increment); } public void RecordCountStatsApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 148 + (int)tag; + var index = 149 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 170 + (int)tag; + var index = 171 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigHiddenByDatadogConfig(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 173 + ((int)tag1 * 10) + (int)tag2; + var index = 174 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigInvalid(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 263 + ((int)tag1 * 10) + (int)tag2; + var index = 264 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportAttempts(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 353 + ((int)tag1 * 2) + (int)tag2; + var index = 354 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 357 + ((int)tag1 * 2) + (int)tag2; + var index = 358 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportPartialSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 361 + ((int)tag1 * 2) + (int)tag2; + var index = 362 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportFailures(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 365 + ((int)tag1 * 2) + (int)tag2; + var index = 366 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag, int increment = 1) { - var index = 369 + (int)tag; + var index = 370 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag2, int increment = 1) { - var index = 371 + ((int)tag1 * 22) + (int)tag2; + var index = 372 + ((int)tag1 * 22) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag2, int increment = 1) { - var index = 415 + ((int)tag1 * 3) + (int)tag2; + var index = 416 + ((int)tag1 * 3) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountVersionConflictTracerCreated(int increment = 1) { - Interlocked.Add(ref _buffer.Count[421], increment); + Interlocked.Add(ref _buffer.Count[422], increment); } public void RecordCountUnsupportedCustomInstrumentationServices(int increment = 1) { - Interlocked.Add(ref _buffer.Count[422], increment); + Interlocked.Add(ref _buffer.Count[423], increment); } public void RecordCountDirectLogLogs(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag, int increment = 1) { - var index = 423 + (int)tag; + var index = 424 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[507], increment); + Interlocked.Add(ref _buffer.Count[509], increment); } public void RecordCountDirectLogApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 508 + (int)tag; + var index = 510 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 532 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafInit(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 533 + (int)tag; + var index = 535 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafUpdates(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 537 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.WafAnalysis tag, int increment = 1) { - var index = 537 + (int)tag; + var index = 539 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountInputTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.TruncationReason tag, int increment = 1) { - var index = 545 + (int)tag; + var index = 547 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 548 + (int)tag; + var index = 550 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { - var index = 553 + (int)tag; + var index = 555 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 568 + (int)tag; + var index = 570 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 573 + (int)tag; + var index = 575 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 577 + (int)tag; + var index = 579 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountUserEventSdk(Datadog.Trace.Telemetry.Metrics.MetricTags.UserEventSdk tag, int increment = 1) { - var index = 581 + (int)tag; + var index = 583 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 588 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[600], increment); + Interlocked.Add(ref _buffer.Count[602], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 601 + (int)tag; + var index = 603 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[628], increment); + Interlocked.Add(ref _buffer.Count[630], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 629 + (int)tag; + var index = 631 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs index d60501e4f45d..82355f89f551 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs index bfaf729c064b..074a939c1ce9 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class CiVisibilityMetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs index e382010a658c..8cc8110fcc6a 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountLength = 656; + private const int CountLength = 658; /// /// Creates the buffer for the values. @@ -109,35 +109,36 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // spans_finished, index = 88 + new(new[] { "integration_name:serverlesscompat" }), + // spans_finished, index = 89 new(null), - // spans_enqueued_for_serialization, index = 89 + // spans_enqueued_for_serialization, index = 90 new(new[] { "reason:p0_keep" }), new(new[] { "reason:single_span_sampling" }), new(new[] { "reason:default" }), - // spans_dropped, index = 92 + // spans_dropped, index = 93 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_segments_created, index = 96 + // trace_segments_created, index = 97 new(new[] { "new_continued:new" }), new(new[] { "new_continued:continued" }), - // trace_chunks_enqueued_for_serialization, index = 98 + // trace_chunks_enqueued_for_serialization, index = 99 new(new[] { "reason:p0_keep" }), new(new[] { "reason:default" }), - // trace_chunks_dropped, index = 100 + // trace_chunks_dropped, index = 101 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_chunks_sent, index = 104 + // trace_chunks_sent, index = 105 new(null), - // trace_segments_closed, index = 105 + // trace_segments_closed, index = 106 new(null), - // trace_api.requests, index = 106 + // trace_api.requests, index = 107 new(null), - // trace_api.responses, index = 107 + // trace_api.responses, index = 108 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -160,33 +161,33 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // trace_api.errors, index = 129 + // trace_api.errors, index = 130 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // trace_partial_flush.count, index = 132 + // trace_partial_flush.count, index = 133 new(new[] { "reason:large_trace" }), new(new[] { "reason:single_span_ingestion" }), - // context_header_style.injected, index = 134 + // context_header_style.injected, index = 135 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header_style.extracted, index = 139 + // context_header_style.extracted, index = 140 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header.truncated, index = 144 + // context_header.truncated, index = 145 new(new[] { "truncation_reason:baggage_item_count_exceeded" }), new(new[] { "truncation_reason:baggage_byte_count_exceeded" }), - // context_header_style.malformed, index = 146 + // context_header_style.malformed, index = 147 new(new[] { "header_style:baggage" }), - // stats_api.requests, index = 147 + // stats_api.requests, index = 148 new(null), - // stats_api.responses, index = 148 + // stats_api.responses, index = 149 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -209,11 +210,11 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // stats_api.errors, index = 170 + // stats_api.errors, index = 171 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // otel.env.hiding, index = 173 + // otel.env.hiding, index = 174 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -304,7 +305,7 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.env.invalid, index = 263 + // otel.env.invalid, index = 264 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -395,30 +396,30 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.metrics_export_attempts, index = 353 + // otel.metrics_export_attempts, index = 354 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_successes, index = 357 + // otel.metrics_export_successes, index = 358 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_partial_successes, index = 361 + // otel.metrics_export_partial_successes, index = 362 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_failures, index = 365 + // otel.metrics_export_failures, index = 366 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // telemetry_api.requests, index = 369 + // telemetry_api.requests, index = 370 new(new[] { "endpoint:agent" }), new(new[] { "endpoint:agentless" }), - // telemetry_api.responses, index = 371 + // telemetry_api.responses, index = 372 new(new[] { "endpoint:agent", "status_code:200" }), new(new[] { "endpoint:agent", "status_code:201" }), new(new[] { "endpoint:agent", "status_code:202" }), @@ -463,18 +464,18 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "endpoint:agentless", "status_code:503" }), new(new[] { "endpoint:agentless", "status_code:504" }), new(new[] { "endpoint:agentless", "status_code:5xx" }), - // telemetry_api.errors, index = 415 + // telemetry_api.errors, index = 416 new(new[] { "endpoint:agent", "type:timeout" }), new(new[] { "endpoint:agent", "type:network" }), new(new[] { "endpoint:agent", "type:status_code" }), new(new[] { "endpoint:agentless", "type:timeout" }), new(new[] { "endpoint:agentless", "type:network" }), new(new[] { "endpoint:agentless", "type:status_code" }), - // version_conflict_tracers_created, index = 421 + // version_conflict_tracers_created, index = 422 new(null), - // unsupported_custom_instrumentation_services, index = 422 + // unsupported_custom_instrumentation_services, index = 423 new(null), - // direct_log_logs, index = 423 + // direct_log_logs, index = 424 new(new[] { "integration_name:datadog" }), new(new[] { "integration_name:opentracing" }), new(new[] { "integration_name:version_conflict" }), @@ -559,9 +560,10 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // direct_log_api.requests, index = 507 + new(new[] { "integration_name:serverlesscompat" }), + // direct_log_api.requests, index = 509 new(null), - // direct_log_api.responses, index = 508 + // direct_log_api.responses, index = 510 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -584,17 +586,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // direct_log_api.errors, index = 530 + // direct_log_api.errors, index = 532 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // waf.init, index = 533 + // waf.init, index = 535 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.updates, index = 535 + // waf.updates, index = 537 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.requests, index = 537 + // waf.requests, index = 539 new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), @@ -603,17 +605,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:true", "block_failure:false", "rate_limited:false", "input_truncated:true" }), - // waf.input_truncated, index = 545 + // waf.input_truncated, index = 547 new(new[] { "truncation_reason:string_too_long" }), new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), - // rasp.rule.eval, index = 548 + // rasp.rule.eval, index = 550 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.rule.match, index = 553 + // rasp.rule.match, index = 555 new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:sql_injection" }), @@ -629,29 +631,29 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 568 + // rasp.timeout, index = 570 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 573 + // instrum.user_auth.missing_user_id, index = 575 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // instrum.user_auth.missing_user_login, index = 577 + // instrum.user_auth.missing_user_login, index = 579 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // sdk.event, index = 581 + // sdk.event, index = 583 new(new[] { "event_type:login_success", "sdk_version:v1" }), new(new[] { "event_type:login_success", "sdk_version:v2" }), new(new[] { "event_type:login_failure", "sdk_version:v1" }), new(new[] { "event_type:login_failure", "sdk_version:v2" }), new(new[] { "event_type:custom", "sdk_version:v1" }), - // executed.source, index = 586 + // executed.source, index = 588 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -666,9 +668,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "source_type:http.request.uri" }), new(new[] { "source_type:grpc.request.body" }), new(new[] { "source_type:sql.row.value" }), - // executed.propagation, index = 600 + // executed.propagation, index = 602 new(null), - // executed.sink, index = 601 + // executed.sink, index = 603 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -696,9 +698,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "vulnerability_type:directory_listing_leak" }), new(new[] { "vulnerability_type:session_timeout" }), new(new[] { "vulnerability_type:email_html_injection" }), - // request.tainted, index = 628 + // request.tainted, index = 630 new(null), - // suppressed.vulnerabilities, index = 629 + // suppressed.vulnerabilities, index = 631 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -734,7 +736,7 @@ private static AggregatedMetric[] GetCountBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountEntryCounts { get; } - = new int[]{ 4, 84, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 84, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 85, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 85, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -750,285 +752,285 @@ public void RecordCountSpanCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.In public void RecordCountSpanFinished(int increment = 1) { - Interlocked.Add(ref _buffer.Count[88], increment); + Interlocked.Add(ref _buffer.Count[89], increment); } public void RecordCountSpanEnqueuedForSerialization(Datadog.Trace.Telemetry.Metrics.MetricTags.SpanEnqueueReason tag, int increment = 1) { - var index = 89 + (int)tag; + var index = 90 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountSpanDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 92 + (int)tag; + var index = 93 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceSegmentCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceContinuation tag, int increment = 1) { - var index = 96 + (int)tag; + var index = 97 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkEnqueued(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceChunkEnqueueReason tag, int increment = 1) { - var index = 98 + (int)tag; + var index = 99 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 100 + (int)tag; + var index = 101 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkSent(int increment = 1) { - Interlocked.Add(ref _buffer.Count[104], increment); + Interlocked.Add(ref _buffer.Count[105], increment); } public void RecordCountTraceSegmentsClosed(int increment = 1) { - Interlocked.Add(ref _buffer.Count[105], increment); + Interlocked.Add(ref _buffer.Count[106], increment); } public void RecordCountTraceApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[106], increment); + Interlocked.Add(ref _buffer.Count[107], increment); } public void RecordCountTraceApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 107 + (int)tag; + var index = 108 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 129 + (int)tag; + var index = 130 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTracePartialFlush(Datadog.Trace.Telemetry.Metrics.MetricTags.PartialFlushReason tag, int increment = 1) { - var index = 132 + (int)tag; + var index = 133 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleInjected(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 134 + (int)tag; + var index = 135 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleExtracted(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 139 + (int)tag; + var index = 140 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderTruncationReason tag, int increment = 1) { - var index = 144 + (int)tag; + var index = 145 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderMalformed(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderMalformed tag, int increment = 1) { - var index = 146 + (int)tag; + var index = 147 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[147], increment); + Interlocked.Add(ref _buffer.Count[148], increment); } public void RecordCountStatsApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 148 + (int)tag; + var index = 149 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 170 + (int)tag; + var index = 171 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigHiddenByDatadogConfig(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 173 + ((int)tag1 * 10) + (int)tag2; + var index = 174 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigInvalid(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 263 + ((int)tag1 * 10) + (int)tag2; + var index = 264 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportAttempts(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 353 + ((int)tag1 * 2) + (int)tag2; + var index = 354 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 357 + ((int)tag1 * 2) + (int)tag2; + var index = 358 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportPartialSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 361 + ((int)tag1 * 2) + (int)tag2; + var index = 362 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportFailures(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 365 + ((int)tag1 * 2) + (int)tag2; + var index = 366 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag, int increment = 1) { - var index = 369 + (int)tag; + var index = 370 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag2, int increment = 1) { - var index = 371 + ((int)tag1 * 22) + (int)tag2; + var index = 372 + ((int)tag1 * 22) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag2, int increment = 1) { - var index = 415 + ((int)tag1 * 3) + (int)tag2; + var index = 416 + ((int)tag1 * 3) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountVersionConflictTracerCreated(int increment = 1) { - Interlocked.Add(ref _buffer.Count[421], increment); + Interlocked.Add(ref _buffer.Count[422], increment); } public void RecordCountUnsupportedCustomInstrumentationServices(int increment = 1) { - Interlocked.Add(ref _buffer.Count[422], increment); + Interlocked.Add(ref _buffer.Count[423], increment); } public void RecordCountDirectLogLogs(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag, int increment = 1) { - var index = 423 + (int)tag; + var index = 424 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[507], increment); + Interlocked.Add(ref _buffer.Count[509], increment); } public void RecordCountDirectLogApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 508 + (int)tag; + var index = 510 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 532 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafInit(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 533 + (int)tag; + var index = 535 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafUpdates(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 537 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.WafAnalysis tag, int increment = 1) { - var index = 537 + (int)tag; + var index = 539 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountInputTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.TruncationReason tag, int increment = 1) { - var index = 545 + (int)tag; + var index = 547 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 548 + (int)tag; + var index = 550 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { - var index = 553 + (int)tag; + var index = 555 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 568 + (int)tag; + var index = 570 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 573 + (int)tag; + var index = 575 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 577 + (int)tag; + var index = 579 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountUserEventSdk(Datadog.Trace.Telemetry.Metrics.MetricTags.UserEventSdk tag, int increment = 1) { - var index = 581 + (int)tag; + var index = 583 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 588 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[600], increment); + Interlocked.Add(ref _buffer.Count[602], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 601 + (int)tag; + var index = 603 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[628], increment); + Interlocked.Add(ref _buffer.Count[630], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 629 + (int)tag; + var index = 631 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs index d60501e4f45d..82355f89f551 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs index bfaf729c064b..074a939c1ce9 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class CiVisibilityMetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs index e382010a658c..8cc8110fcc6a 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountLength = 656; + private const int CountLength = 658; /// /// Creates the buffer for the values. @@ -109,35 +109,36 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // spans_finished, index = 88 + new(new[] { "integration_name:serverlesscompat" }), + // spans_finished, index = 89 new(null), - // spans_enqueued_for_serialization, index = 89 + // spans_enqueued_for_serialization, index = 90 new(new[] { "reason:p0_keep" }), new(new[] { "reason:single_span_sampling" }), new(new[] { "reason:default" }), - // spans_dropped, index = 92 + // spans_dropped, index = 93 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_segments_created, index = 96 + // trace_segments_created, index = 97 new(new[] { "new_continued:new" }), new(new[] { "new_continued:continued" }), - // trace_chunks_enqueued_for_serialization, index = 98 + // trace_chunks_enqueued_for_serialization, index = 99 new(new[] { "reason:p0_keep" }), new(new[] { "reason:default" }), - // trace_chunks_dropped, index = 100 + // trace_chunks_dropped, index = 101 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_chunks_sent, index = 104 + // trace_chunks_sent, index = 105 new(null), - // trace_segments_closed, index = 105 + // trace_segments_closed, index = 106 new(null), - // trace_api.requests, index = 106 + // trace_api.requests, index = 107 new(null), - // trace_api.responses, index = 107 + // trace_api.responses, index = 108 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -160,33 +161,33 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // trace_api.errors, index = 129 + // trace_api.errors, index = 130 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // trace_partial_flush.count, index = 132 + // trace_partial_flush.count, index = 133 new(new[] { "reason:large_trace" }), new(new[] { "reason:single_span_ingestion" }), - // context_header_style.injected, index = 134 + // context_header_style.injected, index = 135 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header_style.extracted, index = 139 + // context_header_style.extracted, index = 140 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header.truncated, index = 144 + // context_header.truncated, index = 145 new(new[] { "truncation_reason:baggage_item_count_exceeded" }), new(new[] { "truncation_reason:baggage_byte_count_exceeded" }), - // context_header_style.malformed, index = 146 + // context_header_style.malformed, index = 147 new(new[] { "header_style:baggage" }), - // stats_api.requests, index = 147 + // stats_api.requests, index = 148 new(null), - // stats_api.responses, index = 148 + // stats_api.responses, index = 149 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -209,11 +210,11 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // stats_api.errors, index = 170 + // stats_api.errors, index = 171 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // otel.env.hiding, index = 173 + // otel.env.hiding, index = 174 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -304,7 +305,7 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.env.invalid, index = 263 + // otel.env.invalid, index = 264 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -395,30 +396,30 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.metrics_export_attempts, index = 353 + // otel.metrics_export_attempts, index = 354 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_successes, index = 357 + // otel.metrics_export_successes, index = 358 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_partial_successes, index = 361 + // otel.metrics_export_partial_successes, index = 362 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_failures, index = 365 + // otel.metrics_export_failures, index = 366 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // telemetry_api.requests, index = 369 + // telemetry_api.requests, index = 370 new(new[] { "endpoint:agent" }), new(new[] { "endpoint:agentless" }), - // telemetry_api.responses, index = 371 + // telemetry_api.responses, index = 372 new(new[] { "endpoint:agent", "status_code:200" }), new(new[] { "endpoint:agent", "status_code:201" }), new(new[] { "endpoint:agent", "status_code:202" }), @@ -463,18 +464,18 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "endpoint:agentless", "status_code:503" }), new(new[] { "endpoint:agentless", "status_code:504" }), new(new[] { "endpoint:agentless", "status_code:5xx" }), - // telemetry_api.errors, index = 415 + // telemetry_api.errors, index = 416 new(new[] { "endpoint:agent", "type:timeout" }), new(new[] { "endpoint:agent", "type:network" }), new(new[] { "endpoint:agent", "type:status_code" }), new(new[] { "endpoint:agentless", "type:timeout" }), new(new[] { "endpoint:agentless", "type:network" }), new(new[] { "endpoint:agentless", "type:status_code" }), - // version_conflict_tracers_created, index = 421 + // version_conflict_tracers_created, index = 422 new(null), - // unsupported_custom_instrumentation_services, index = 422 + // unsupported_custom_instrumentation_services, index = 423 new(null), - // direct_log_logs, index = 423 + // direct_log_logs, index = 424 new(new[] { "integration_name:datadog" }), new(new[] { "integration_name:opentracing" }), new(new[] { "integration_name:version_conflict" }), @@ -559,9 +560,10 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // direct_log_api.requests, index = 507 + new(new[] { "integration_name:serverlesscompat" }), + // direct_log_api.requests, index = 509 new(null), - // direct_log_api.responses, index = 508 + // direct_log_api.responses, index = 510 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -584,17 +586,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // direct_log_api.errors, index = 530 + // direct_log_api.errors, index = 532 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // waf.init, index = 533 + // waf.init, index = 535 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.updates, index = 535 + // waf.updates, index = 537 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.requests, index = 537 + // waf.requests, index = 539 new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), @@ -603,17 +605,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:true", "block_failure:false", "rate_limited:false", "input_truncated:true" }), - // waf.input_truncated, index = 545 + // waf.input_truncated, index = 547 new(new[] { "truncation_reason:string_too_long" }), new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), - // rasp.rule.eval, index = 548 + // rasp.rule.eval, index = 550 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.rule.match, index = 553 + // rasp.rule.match, index = 555 new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:sql_injection" }), @@ -629,29 +631,29 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 568 + // rasp.timeout, index = 570 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 573 + // instrum.user_auth.missing_user_id, index = 575 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // instrum.user_auth.missing_user_login, index = 577 + // instrum.user_auth.missing_user_login, index = 579 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // sdk.event, index = 581 + // sdk.event, index = 583 new(new[] { "event_type:login_success", "sdk_version:v1" }), new(new[] { "event_type:login_success", "sdk_version:v2" }), new(new[] { "event_type:login_failure", "sdk_version:v1" }), new(new[] { "event_type:login_failure", "sdk_version:v2" }), new(new[] { "event_type:custom", "sdk_version:v1" }), - // executed.source, index = 586 + // executed.source, index = 588 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -666,9 +668,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "source_type:http.request.uri" }), new(new[] { "source_type:grpc.request.body" }), new(new[] { "source_type:sql.row.value" }), - // executed.propagation, index = 600 + // executed.propagation, index = 602 new(null), - // executed.sink, index = 601 + // executed.sink, index = 603 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -696,9 +698,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "vulnerability_type:directory_listing_leak" }), new(new[] { "vulnerability_type:session_timeout" }), new(new[] { "vulnerability_type:email_html_injection" }), - // request.tainted, index = 628 + // request.tainted, index = 630 new(null), - // suppressed.vulnerabilities, index = 629 + // suppressed.vulnerabilities, index = 631 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -734,7 +736,7 @@ private static AggregatedMetric[] GetCountBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountEntryCounts { get; } - = new int[]{ 4, 84, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 84, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 85, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 85, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -750,285 +752,285 @@ public void RecordCountSpanCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.In public void RecordCountSpanFinished(int increment = 1) { - Interlocked.Add(ref _buffer.Count[88], increment); + Interlocked.Add(ref _buffer.Count[89], increment); } public void RecordCountSpanEnqueuedForSerialization(Datadog.Trace.Telemetry.Metrics.MetricTags.SpanEnqueueReason tag, int increment = 1) { - var index = 89 + (int)tag; + var index = 90 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountSpanDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 92 + (int)tag; + var index = 93 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceSegmentCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceContinuation tag, int increment = 1) { - var index = 96 + (int)tag; + var index = 97 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkEnqueued(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceChunkEnqueueReason tag, int increment = 1) { - var index = 98 + (int)tag; + var index = 99 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 100 + (int)tag; + var index = 101 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkSent(int increment = 1) { - Interlocked.Add(ref _buffer.Count[104], increment); + Interlocked.Add(ref _buffer.Count[105], increment); } public void RecordCountTraceSegmentsClosed(int increment = 1) { - Interlocked.Add(ref _buffer.Count[105], increment); + Interlocked.Add(ref _buffer.Count[106], increment); } public void RecordCountTraceApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[106], increment); + Interlocked.Add(ref _buffer.Count[107], increment); } public void RecordCountTraceApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 107 + (int)tag; + var index = 108 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 129 + (int)tag; + var index = 130 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTracePartialFlush(Datadog.Trace.Telemetry.Metrics.MetricTags.PartialFlushReason tag, int increment = 1) { - var index = 132 + (int)tag; + var index = 133 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleInjected(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 134 + (int)tag; + var index = 135 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleExtracted(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 139 + (int)tag; + var index = 140 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderTruncationReason tag, int increment = 1) { - var index = 144 + (int)tag; + var index = 145 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderMalformed(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderMalformed tag, int increment = 1) { - var index = 146 + (int)tag; + var index = 147 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[147], increment); + Interlocked.Add(ref _buffer.Count[148], increment); } public void RecordCountStatsApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 148 + (int)tag; + var index = 149 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 170 + (int)tag; + var index = 171 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigHiddenByDatadogConfig(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 173 + ((int)tag1 * 10) + (int)tag2; + var index = 174 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigInvalid(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 263 + ((int)tag1 * 10) + (int)tag2; + var index = 264 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportAttempts(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 353 + ((int)tag1 * 2) + (int)tag2; + var index = 354 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 357 + ((int)tag1 * 2) + (int)tag2; + var index = 358 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportPartialSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 361 + ((int)tag1 * 2) + (int)tag2; + var index = 362 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportFailures(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 365 + ((int)tag1 * 2) + (int)tag2; + var index = 366 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag, int increment = 1) { - var index = 369 + (int)tag; + var index = 370 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag2, int increment = 1) { - var index = 371 + ((int)tag1 * 22) + (int)tag2; + var index = 372 + ((int)tag1 * 22) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag2, int increment = 1) { - var index = 415 + ((int)tag1 * 3) + (int)tag2; + var index = 416 + ((int)tag1 * 3) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountVersionConflictTracerCreated(int increment = 1) { - Interlocked.Add(ref _buffer.Count[421], increment); + Interlocked.Add(ref _buffer.Count[422], increment); } public void RecordCountUnsupportedCustomInstrumentationServices(int increment = 1) { - Interlocked.Add(ref _buffer.Count[422], increment); + Interlocked.Add(ref _buffer.Count[423], increment); } public void RecordCountDirectLogLogs(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag, int increment = 1) { - var index = 423 + (int)tag; + var index = 424 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[507], increment); + Interlocked.Add(ref _buffer.Count[509], increment); } public void RecordCountDirectLogApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 508 + (int)tag; + var index = 510 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 532 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafInit(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 533 + (int)tag; + var index = 535 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafUpdates(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 537 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.WafAnalysis tag, int increment = 1) { - var index = 537 + (int)tag; + var index = 539 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountInputTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.TruncationReason tag, int increment = 1) { - var index = 545 + (int)tag; + var index = 547 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 548 + (int)tag; + var index = 550 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { - var index = 553 + (int)tag; + var index = 555 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 568 + (int)tag; + var index = 570 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 573 + (int)tag; + var index = 575 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 577 + (int)tag; + var index = 579 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountUserEventSdk(Datadog.Trace.Telemetry.Metrics.MetricTags.UserEventSdk tag, int increment = 1) { - var index = 581 + (int)tag; + var index = 583 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 588 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[600], increment); + Interlocked.Add(ref _buffer.Count[602], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 601 + (int)tag; + var index = 603 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[628], increment); + Interlocked.Add(ref _buffer.Count[630], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 629 + (int)tag; + var index = 631 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs index d60501e4f45d..82355f89f551 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs index bfaf729c064b..074a939c1ce9 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class CiVisibilityMetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs index e382010a658c..8cc8110fcc6a 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_Count.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountLength = 656; + private const int CountLength = 658; /// /// Creates the buffer for the values. @@ -109,35 +109,36 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // spans_finished, index = 88 + new(new[] { "integration_name:serverlesscompat" }), + // spans_finished, index = 89 new(null), - // spans_enqueued_for_serialization, index = 89 + // spans_enqueued_for_serialization, index = 90 new(new[] { "reason:p0_keep" }), new(new[] { "reason:single_span_sampling" }), new(new[] { "reason:default" }), - // spans_dropped, index = 92 + // spans_dropped, index = 93 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_segments_created, index = 96 + // trace_segments_created, index = 97 new(new[] { "new_continued:new" }), new(new[] { "new_continued:continued" }), - // trace_chunks_enqueued_for_serialization, index = 98 + // trace_chunks_enqueued_for_serialization, index = 99 new(new[] { "reason:p0_keep" }), new(new[] { "reason:default" }), - // trace_chunks_dropped, index = 100 + // trace_chunks_dropped, index = 101 new(new[] { "reason:p0_drop" }), new(new[] { "reason:overfull_buffer" }), new(new[] { "reason:serialization_error" }), new(new[] { "reason:api_error" }), - // trace_chunks_sent, index = 104 + // trace_chunks_sent, index = 105 new(null), - // trace_segments_closed, index = 105 + // trace_segments_closed, index = 106 new(null), - // trace_api.requests, index = 106 + // trace_api.requests, index = 107 new(null), - // trace_api.responses, index = 107 + // trace_api.responses, index = 108 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -160,33 +161,33 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // trace_api.errors, index = 129 + // trace_api.errors, index = 130 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // trace_partial_flush.count, index = 132 + // trace_partial_flush.count, index = 133 new(new[] { "reason:large_trace" }), new(new[] { "reason:single_span_ingestion" }), - // context_header_style.injected, index = 134 + // context_header_style.injected, index = 135 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header_style.extracted, index = 139 + // context_header_style.extracted, index = 140 new(new[] { "header_style:tracecontext" }), new(new[] { "header_style:datadog" }), new(new[] { "header_style:b3multi" }), new(new[] { "header_style:b3single" }), new(new[] { "header_style:baggage" }), - // context_header.truncated, index = 144 + // context_header.truncated, index = 145 new(new[] { "truncation_reason:baggage_item_count_exceeded" }), new(new[] { "truncation_reason:baggage_byte_count_exceeded" }), - // context_header_style.malformed, index = 146 + // context_header_style.malformed, index = 147 new(new[] { "header_style:baggage" }), - // stats_api.requests, index = 147 + // stats_api.requests, index = 148 new(null), - // stats_api.responses, index = 148 + // stats_api.responses, index = 149 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -209,11 +210,11 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // stats_api.errors, index = 170 + // stats_api.errors, index = 171 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // otel.env.hiding, index = 173 + // otel.env.hiding, index = 174 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -304,7 +305,7 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.env.invalid, index = 263 + // otel.env.invalid, index = 264 new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_log_level" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_metrics_exporter" }), new(new[] { "config_datadog:dd_trace_debug", "config_opentelemetry:otel_propagators" }), @@ -395,30 +396,30 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:otel_traces_sampler_arg" }), new(new[] { "config_datadog:unknown", "config_opentelemetry:unknown" }), - // otel.metrics_export_attempts, index = 353 + // otel.metrics_export_attempts, index = 354 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_successes, index = 357 + // otel.metrics_export_successes, index = 358 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_partial_successes, index = 361 + // otel.metrics_export_partial_successes, index = 362 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // otel.metrics_export_failures, index = 365 + // otel.metrics_export_failures, index = 366 new(new[] { "protocol:grpc", "encoding:protobuf" }), new(new[] { "protocol:grpc", "encoding:json" }), new(new[] { "protocol:http", "encoding:protobuf" }), new(new[] { "protocol:http", "encoding:json" }), - // telemetry_api.requests, index = 369 + // telemetry_api.requests, index = 370 new(new[] { "endpoint:agent" }), new(new[] { "endpoint:agentless" }), - // telemetry_api.responses, index = 371 + // telemetry_api.responses, index = 372 new(new[] { "endpoint:agent", "status_code:200" }), new(new[] { "endpoint:agent", "status_code:201" }), new(new[] { "endpoint:agent", "status_code:202" }), @@ -463,18 +464,18 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "endpoint:agentless", "status_code:503" }), new(new[] { "endpoint:agentless", "status_code:504" }), new(new[] { "endpoint:agentless", "status_code:5xx" }), - // telemetry_api.errors, index = 415 + // telemetry_api.errors, index = 416 new(new[] { "endpoint:agent", "type:timeout" }), new(new[] { "endpoint:agent", "type:network" }), new(new[] { "endpoint:agent", "type:status_code" }), new(new[] { "endpoint:agentless", "type:timeout" }), new(new[] { "endpoint:agentless", "type:network" }), new(new[] { "endpoint:agentless", "type:status_code" }), - // version_conflict_tracers_created, index = 421 + // version_conflict_tracers_created, index = 422 new(null), - // unsupported_custom_instrumentation_services, index = 422 + // unsupported_custom_instrumentation_services, index = 423 new(null), - // direct_log_logs, index = 423 + // direct_log_logs, index = 424 new(new[] { "integration_name:datadog" }), new(new[] { "integration_name:opentracing" }), new(new[] { "integration_name:version_conflict" }), @@ -559,9 +560,10 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "integration_name:emailhtmlinjection" }), new(new[] { "integration_name:protobuf" }), new(new[] { "integration_name:hangfire" }), - // direct_log_api.requests, index = 507 + new(new[] { "integration_name:serverlesscompat" }), + // direct_log_api.requests, index = 509 new(null), - // direct_log_api.responses, index = 508 + // direct_log_api.responses, index = 510 new(new[] { "status_code:200" }), new(new[] { "status_code:201" }), new(new[] { "status_code:202" }), @@ -584,17 +586,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "status_code:503" }), new(new[] { "status_code:504" }), new(new[] { "status_code:5xx" }), - // direct_log_api.errors, index = 530 + // direct_log_api.errors, index = 532 new(new[] { "type:timeout" }), new(new[] { "type:network" }), new(new[] { "type:status_code" }), - // waf.init, index = 533 + // waf.init, index = 535 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.updates, index = 535 + // waf.updates, index = 537 new(new[] { "waf_version", "event_rules_version", "success:true" }), new(new[] { "waf_version", "event_rules_version", "success:false" }), - // waf.requests, index = 537 + // waf.requests, index = 539 new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:false" }), @@ -603,17 +605,17 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:false", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:true", "request_blocked:true", "waf_timeout:false", "block_failure:false", "rate_limited:false", "input_truncated:true" }), new(new[] { "waf_version", "event_rules_version", "rule_triggered:false", "request_blocked:false", "waf_timeout:true", "block_failure:false", "rate_limited:false", "input_truncated:true" }), - // waf.input_truncated, index = 545 + // waf.input_truncated, index = 547 new(new[] { "truncation_reason:string_too_long" }), new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), - // rasp.rule.eval, index = 548 + // rasp.rule.eval, index = 550 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.rule.match, index = 553 + // rasp.rule.match, index = 555 new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:sql_injection" }), @@ -629,29 +631,29 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 568 + // rasp.timeout, index = 570 new(new[] { "waf_version", "event_rules_version", "rule_type:lfi" }), new(new[] { "waf_version", "event_rules_version", "rule_type:ssrf" }), new(new[] { "waf_version", "event_rules_version", "rule_type:sql_injection" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:shell" }), new(new[] { "waf_version", "event_rules_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 573 + // instrum.user_auth.missing_user_id, index = 575 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // instrum.user_auth.missing_user_login, index = 577 + // instrum.user_auth.missing_user_login, index = 579 new(new[] { "framework:aspnetcore_identity", "event_type:login_success" }), new(new[] { "framework:aspnetcore_identity", "event_type:login_failure" }), new(new[] { "framework:aspnetcore_identity", "event_type:signup" }), new(new[] { "framework:unknown", "event_type:signup" }), - // sdk.event, index = 581 + // sdk.event, index = 583 new(new[] { "event_type:login_success", "sdk_version:v1" }), new(new[] { "event_type:login_success", "sdk_version:v2" }), new(new[] { "event_type:login_failure", "sdk_version:v1" }), new(new[] { "event_type:login_failure", "sdk_version:v2" }), new(new[] { "event_type:custom", "sdk_version:v1" }), - // executed.source, index = 586 + // executed.source, index = 588 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -666,9 +668,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "source_type:http.request.uri" }), new(new[] { "source_type:grpc.request.body" }), new(new[] { "source_type:sql.row.value" }), - // executed.propagation, index = 600 + // executed.propagation, index = 602 new(null), - // executed.sink, index = 601 + // executed.sink, index = 603 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -696,9 +698,9 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "vulnerability_type:directory_listing_leak" }), new(new[] { "vulnerability_type:session_timeout" }), new(new[] { "vulnerability_type:email_html_injection" }), - // request.tainted, index = 628 + // request.tainted, index = 630 new(null), - // suppressed.vulnerabilities, index = 629 + // suppressed.vulnerabilities, index = 631 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -734,7 +736,7 @@ private static AggregatedMetric[] GetCountBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountEntryCounts { get; } - = new int[]{ 4, 84, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 84, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 85, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 1, 22, 3, 90, 90, 4, 4, 4, 4, 2, 44, 6, 1, 1, 85, 1, 22, 3, 2, 2, 8, 3, 5, 15, 5, 4, 4, 5, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -750,285 +752,285 @@ public void RecordCountSpanCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.In public void RecordCountSpanFinished(int increment = 1) { - Interlocked.Add(ref _buffer.Count[88], increment); + Interlocked.Add(ref _buffer.Count[89], increment); } public void RecordCountSpanEnqueuedForSerialization(Datadog.Trace.Telemetry.Metrics.MetricTags.SpanEnqueueReason tag, int increment = 1) { - var index = 89 + (int)tag; + var index = 90 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountSpanDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 92 + (int)tag; + var index = 93 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceSegmentCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceContinuation tag, int increment = 1) { - var index = 96 + (int)tag; + var index = 97 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkEnqueued(Datadog.Trace.Telemetry.Metrics.MetricTags.TraceChunkEnqueueReason tag, int increment = 1) { - var index = 98 + (int)tag; + var index = 99 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkDropped(Datadog.Trace.Telemetry.Metrics.MetricTags.DropReason tag, int increment = 1) { - var index = 100 + (int)tag; + var index = 101 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceChunkSent(int increment = 1) { - Interlocked.Add(ref _buffer.Count[104], increment); + Interlocked.Add(ref _buffer.Count[105], increment); } public void RecordCountTraceSegmentsClosed(int increment = 1) { - Interlocked.Add(ref _buffer.Count[105], increment); + Interlocked.Add(ref _buffer.Count[106], increment); } public void RecordCountTraceApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[106], increment); + Interlocked.Add(ref _buffer.Count[107], increment); } public void RecordCountTraceApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 107 + (int)tag; + var index = 108 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTraceApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 129 + (int)tag; + var index = 130 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTracePartialFlush(Datadog.Trace.Telemetry.Metrics.MetricTags.PartialFlushReason tag, int increment = 1) { - var index = 132 + (int)tag; + var index = 133 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleInjected(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 134 + (int)tag; + var index = 135 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderStyleExtracted(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderStyle tag, int increment = 1) { - var index = 139 + (int)tag; + var index = 140 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderTruncationReason tag, int increment = 1) { - var index = 144 + (int)tag; + var index = 145 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountContextHeaderMalformed(Datadog.Trace.Telemetry.Metrics.MetricTags.ContextHeaderMalformed tag, int increment = 1) { - var index = 146 + (int)tag; + var index = 147 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[147], increment); + Interlocked.Add(ref _buffer.Count[148], increment); } public void RecordCountStatsApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 148 + (int)tag; + var index = 149 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountStatsApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 170 + (int)tag; + var index = 171 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigHiddenByDatadogConfig(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 173 + ((int)tag1 * 10) + (int)tag2; + var index = 174 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountOpenTelemetryConfigInvalid(Datadog.Trace.Telemetry.Metrics.MetricTags.DatadogConfiguration tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.OpenTelemetryConfiguration tag2, int increment = 1) { - var index = 263 + ((int)tag1 * 10) + (int)tag2; + var index = 264 + ((int)tag1 * 10) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportAttempts(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 353 + ((int)tag1 * 2) + (int)tag2; + var index = 354 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 357 + ((int)tag1 * 2) + (int)tag2; + var index = 358 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportPartialSuccesses(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 361 + ((int)tag1 * 2) + (int)tag2; + var index = 362 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMetricsExportFailures(Datadog.Trace.Telemetry.Metrics.MetricTags.Protocol tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.MetricEncoding tag2, int increment = 1) { - var index = 365 + ((int)tag1 * 2) + (int)tag2; + var index = 366 + ((int)tag1 * 2) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag, int increment = 1) { - var index = 369 + (int)tag; + var index = 370 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag2, int increment = 1) { - var index = 371 + ((int)tag1 * 22) + (int)tag2; + var index = 372 + ((int)tag1 * 22) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountTelemetryApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.TelemetryEndpoint tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag2, int increment = 1) { - var index = 415 + ((int)tag1 * 3) + (int)tag2; + var index = 416 + ((int)tag1 * 3) + (int)tag2; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountVersionConflictTracerCreated(int increment = 1) { - Interlocked.Add(ref _buffer.Count[421], increment); + Interlocked.Add(ref _buffer.Count[422], increment); } public void RecordCountUnsupportedCustomInstrumentationServices(int increment = 1) { - Interlocked.Add(ref _buffer.Count[422], increment); + Interlocked.Add(ref _buffer.Count[423], increment); } public void RecordCountDirectLogLogs(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag, int increment = 1) { - var index = 423 + (int)tag; + var index = 424 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiRequests(int increment = 1) { - Interlocked.Add(ref _buffer.Count[507], increment); + Interlocked.Add(ref _buffer.Count[509], increment); } public void RecordCountDirectLogApiResponses(Datadog.Trace.Telemetry.Metrics.MetricTags.StatusCode tag, int increment = 1) { - var index = 508 + (int)tag; + var index = 510 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountDirectLogApiErrors(Datadog.Trace.Telemetry.Metrics.MetricTags.ApiError tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 532 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafInit(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 533 + (int)tag; + var index = 535 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafUpdates(Datadog.Trace.Telemetry.Metrics.MetricTags.WafStatus tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 537 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountWafRequests(Datadog.Trace.Telemetry.Metrics.MetricTags.WafAnalysis tag, int increment = 1) { - var index = 537 + (int)tag; + var index = 539 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountInputTruncated(Datadog.Trace.Telemetry.Metrics.MetricTags.TruncationReason tag, int increment = 1) { - var index = 545 + (int)tag; + var index = 547 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 548 + (int)tag; + var index = 550 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { - var index = 553 + (int)tag; + var index = 555 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 568 + (int)tag; + var index = 570 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 573 + (int)tag; + var index = 575 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 577 + (int)tag; + var index = 579 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountUserEventSdk(Datadog.Trace.Telemetry.Metrics.MetricTags.UserEventSdk tag, int increment = 1) { - var index = 581 + (int)tag; + var index = 583 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 588 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[600], increment); + Interlocked.Add(ref _buffer.Count[602], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 601 + (int)tag; + var index = 603 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[628], increment); + Interlocked.Add(ref _buffer.Count[630], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 629 + (int)tag; + var index = 631 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs index d60501e4f45d..82355f89f551 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_CountShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal sealed partial class MetricsTelemetryCollector { - private const int CountSharedLength = 336; + private const int CountSharedLength = 340; /// /// Creates the buffer for the values. @@ -356,6 +356,10 @@ private static AggregatedMetric[] GetCountSharedBuffer() new(new[] { "integration_name:hangfire", "error_type:invoker" }), new(new[] { "integration_name:hangfire", "error_type:execution" }), new(new[] { "integration_name:hangfire", "error_type:missing_member" }), + new(new[] { "integration_name:serverlesscompat", "error_type:duck_typing" }), + new(new[] { "integration_name:serverlesscompat", "error_type:invoker" }), + new(new[] { "integration_name:serverlesscompat", "error_type:execution" }), + new(new[] { "integration_name:serverlesscompat", "error_type:missing_member" }), }; /// @@ -364,7 +368,7 @@ private static AggregatedMetric[] GetCountSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] CountSharedEntryCounts { get; } - = new int[]{ 336, }; + = new int[]{ 340, }; public void RecordCountSharedIntegrationsError(Datadog.Trace.Telemetry.Metrics.MetricTags.IntegrationName tag1, Datadog.Trace.Telemetry.Metrics.MetricTags.InstrumentationError tag2, int increment = 1) { diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs index 9fe5ee486075..3e2d7e976cab 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs @@ -92,6 +92,7 @@ public static MetricTags.IntegrationName GetMetricTag(this IntegrationId integra IntegrationId.Hangfire => MetricTags.IntegrationName.Hangfire, IntegrationId.DatadogTraceVersionConflict => MetricTags.IntegrationName.VersionConflict, IntegrationId.OpenFeature => MetricTags.IntegrationName.OpenFeature, + IntegrationId.ServerlessCompat => MetricTags.IntegrationName.ServerlessCompat, _ => throw new InvalidOperationException($"Unknown IntegrationID {integrationId}"), // dangerous, but we test it will never be called }; } diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs index 5a48f96cab4e..aabd0713525d 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs @@ -277,7 +277,8 @@ internal enum IntegrationName [Description("integration_name:datadogtracemanual")] DatadogTraceManual, [Description("integration_name:emailhtmlinjection")] EmailHtmlInjection, [Description("integration_name:protobuf")] Protobuf, - [Description("integration_name:hangfire")] Hangfire + [Description("integration_name:hangfire")] Hangfire, + [Description("integration_name:serverlesscompat")] ServerlessCompat } public enum InstrumentationError From 4ae14059ce3e978632725bd878120a813f2a8ba6 Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 11 Feb 2026 16:23:57 -0500 Subject: [PATCH 13/38] Fix test helpers to use backing fields for ExporterSettings pipe names --- .../ServerlessCompatIntegrationTests.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 0ef7ded3b390..2c9c49e779cc 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -210,23 +210,23 @@ private static void ResetCachedPipeNames() traceCacheField?.SetValue(null, null); dogstatsdCacheField?.SetValue(null, null); - // Also clear ExporterSettings generated names + // Also clear ExporterSettings generated names (backing fields) var exporterSettingsType = typeof(ExporterSettings); - var tracesPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); - var metricsPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var tracesPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var metricsPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); - tracesPipeNameProp?.SetValue(null, null); - metricsPipeNameProp?.SetValue(null, null); + tracesPipeNameField?.SetValue(null, null); + metricsPipeNameField?.SetValue(null, null); } private static void SetExporterSettingsGeneratedNames(string? tracePipeName, string? metricsPipeName) { var exporterSettingsType = typeof(ExporterSettings); - var tracesPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); - var metricsPipeNameProp = exporterSettingsType.GetProperty("AzureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var tracesPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var metricsPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); - tracesPipeNameProp?.SetValue(null, tracePipeName); - metricsPipeNameProp?.SetValue(null, metricsPipeName); + tracesPipeNameField?.SetValue(null, tracePipeName); + metricsPipeNameField?.SetValue(null, metricsPipeName); } } #endif From 4295303a919816dbd973a1e4e7ac93ed8baaea56 Mon Sep 17 00:00:00 2001 From: Lewis Date: Mon, 2 Mar 2026 17:02:17 -0500 Subject: [PATCH 14/38] Fix ExporterSettings readonly test by making Azure Functions pipe name fields static readonly with env-var-based initializers --- .../Configuration/ExporterSettings.cs | 64 ++++++++++++------- .../ServerlessCompatIntegrationTests.cs | 30 ++++----- 2 files changed, 55 insertions(+), 39 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index eec76e893d67..adbeffdf5b65 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -31,13 +31,19 @@ public sealed partial class ExporterSettings /// /// Backing field for AzureFunctionsGeneratedTracesPipeName. + /// Initialized statically by checking environment variables directly. + /// Only generates a name when running in Azure Functions without AAS Site Extension + /// and without an explicit DD_TRACE_PIPE_NAME configuration. /// - private static string? _azureFunctionsGeneratedTracesPipeName; + private static readonly string? _azureFunctionsGeneratedTracesPipeName = InitAzureFunctionsTracesPipeName(); /// /// Backing field for AzureFunctionsGeneratedMetricsPipeName. + /// Initialized statically by checking environment variables directly. + /// Only generates a name when running in Azure Functions without AAS Site Extension + /// and without an explicit DD_DOGSTATSD_PIPE_NAME configuration. /// - private static string? _azureFunctionsGeneratedMetricsPipeName; + private static readonly string? _azureFunctionsGeneratedMetricsPipeName = InitAzureFunctionsMetricsPipeName(); /// /// Allows overriding of file system access for tests. @@ -100,28 +106,10 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); - // Generate unique pipe names for Azure Functions (when not using AAS Site Extension) if not explicitly configured - // This ensures multi-function scenarios don't conflict when using the compat layer - // If names are explicitly configured, use them as-is - var tracesPipeName = rawSettings.TracesPipeName; - var metricsPipeName = rawSettings.MetricsPipeName; - - if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension()) - { - if (string.IsNullOrEmpty(tracesPipeName)) - { - tracesPipeName = GenerateUniquePipeName("dd_trace"); - _azureFunctionsGeneratedTracesPipeName = tracesPipeName; - Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", tracesPipeName); - } - - if (string.IsNullOrEmpty(metricsPipeName)) - { - metricsPipeName = GenerateUniquePipeName("dd_dogstatsd"); - _azureFunctionsGeneratedMetricsPipeName = metricsPipeName; - Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", metricsPipeName); - } - } + // Use statically-generated pipe names for Azure Functions if no explicit config was provided. + // The static fields are initialized once at type-load time via InitAzureFunctions*PipeName(). + var tracesPipeName = !string.IsNullOrEmpty(rawSettings.TracesPipeName) ? rawSettings.TracesPipeName : _azureFunctionsGeneratedTracesPipeName; + var metricsPipeName = !string.IsNullOrEmpty(rawSettings.MetricsPipeName) ? rawSettings.MetricsPipeName : _azureFunctionsGeneratedMetricsPipeName; var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, @@ -267,6 +255,34 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return string.IsNullOrEmpty(traceHostname) ? DefaultDogstatsdHostname : traceHostname; } + private static string? InitAzureFunctionsTracesPipeName() + { + if (Util.EnvironmentHelpers.IsAzureFunctions() + && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() + && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName))) + { + var name = GenerateUniquePipeName("dd_trace"); + Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", name); + return name; + } + + return null; + } + + private static string? InitAzureFunctionsMetricsPipeName() + { + if (Util.EnvironmentHelpers.IsAzureFunctions() + && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() + && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName))) + { + var name = GenerateUniquePipeName("dd_dogstatsd"); + Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", name); + return name; + } + + return null; + } + /// /// Generates a unique pipe name by appending a GUID to the base name. /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 2c9c49e779cc..3a2dc8ecab4d 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -10,7 +10,6 @@ using System.Reflection; using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; using Datadog.Trace.ClrProfiler.CallTarget; -using Datadog.Trace.Configuration; using FluentAssertions; using Xunit; @@ -198,7 +197,9 @@ public void GeneratedPipeName_WithLongBaseName_Truncates() pipeName.Should().MatchRegex(@"^a{214}_[a-f0-9]{32}$"); } - // Clear cached values between tests using reflection + // Clear cached values between tests using reflection. + // The integration classes cache their resolved pipe name in a static field; + // resetting these allows each test to start fresh. private static void ResetCachedPipeNames() { var traceIntegrationType = typeof(CompatibilityLayer_CalculateTracePipeName_Integration); @@ -209,24 +210,23 @@ private static void ResetCachedPipeNames() traceCacheField?.SetValue(null, null); dogstatsdCacheField?.SetValue(null, null); - - // Also clear ExporterSettings generated names (backing fields) - var exporterSettingsType = typeof(ExporterSettings); - var tracesPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); - var metricsPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); - - tracesPipeNameField?.SetValue(null, null); - metricsPipeNameField?.SetValue(null, null); } + // Pre-populate the integration cache fields directly to simulate + // having a pre-generated pipe name (e.g. from ExporterSettings). + // The ExporterSettings backing fields are static readonly and cannot be + // set via reflection, so we set the integration-level cache instead, + // which is what the integration checks first. private static void SetExporterSettingsGeneratedNames(string? tracePipeName, string? metricsPipeName) { - var exporterSettingsType = typeof(ExporterSettings); - var tracesPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedTracesPipeName", BindingFlags.NonPublic | BindingFlags.Static); - var metricsPipeNameField = exporterSettingsType.GetField("_azureFunctionsGeneratedMetricsPipeName", BindingFlags.NonPublic | BindingFlags.Static); + var traceIntegrationType = typeof(CompatibilityLayer_CalculateTracePipeName_Integration); + var dogstatsdIntegrationType = typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration); + + var traceCacheField = traceIntegrationType.GetField("_cachedTracePipeName", BindingFlags.NonPublic | BindingFlags.Static); + var dogstatsdCacheField = dogstatsdIntegrationType.GetField("_cachedDogStatsDPipeName", BindingFlags.NonPublic | BindingFlags.Static); - tracesPipeNameField?.SetValue(null, tracePipeName); - metricsPipeNameField?.SetValue(null, metricsPipeName); + traceCacheField?.SetValue(null, tracePipeName); + dogstatsdCacheField?.SetValue(null, metricsPipeName); } } #endif From 79a4b5e6167fcfdd5eced91b501f55572717359f Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 4 Mar 2026 14:39:11 -0500 Subject: [PATCH 15/38] Widen ServerlessCompat version range to 0.0.0 and add trimming entries Lower MinimumVersion from 1.0.0 to 0.0.0 for the CalculateTracePipeName and CalculateDogStatsDPipeName integrations so the dev (0.0.0) compat assembly is also instrumented. Add missing trimming XML entries for types newly referenced by the tracer. Co-Authored-By: Claude Opus 4.6 --- .../build/Datadog.Trace.Trimming.xml | 7 +++++++ ...tibilityLayer_CalculateDogStatsDPipeName_Integration.cs | 5 ++++- ...ompatibilityLayer_CalculateTracePipeName_Integration.cs | 5 ++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml index a6d07d24ce3c..794b281f9e3f 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -163,6 +163,7 @@ + @@ -533,6 +534,7 @@ + @@ -567,12 +569,14 @@ + + @@ -586,6 +590,7 @@ + @@ -595,6 +600,7 @@ + @@ -1088,6 +1094,7 @@ + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index c5b4a3cba8e5..479fa46cf8af 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -18,6 +18,9 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateDogStatsDPipeName method. /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, /// ensuring the tracer's runtime metrics and the compat layer use the same pipe name. + /// Version range 0.0.0–2.*.* matches all versions, including the 0.0.0 dev build. + /// If the target method doesn't exist (e.g. older/newer compat assembly), the native profiler + /// silently skips instrumentation — no exception is thrown. /// [InstrumentMethod( AssemblyName = "Datadog.Serverless.Compat", @@ -25,7 +28,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless MethodName = "CalculateDogStatsDPipeName", ReturnTypeName = ClrNames.String, ParameterTypeNames = new string[0], - MinimumVersion = "1.0.0", + MinimumVersion = "0.0.0", MaximumVersion = "2.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), InstrumentationCategory = InstrumentationCategory.Tracing)] diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index eda10345399f..30022cef8e78 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -18,6 +18,9 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateTracePipeName method. /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, /// ensuring both the tracer and the compat layer use the same pipe name for communication. + /// Version range 0.0.0–2.*.* matches all versions, including the 0.0.0 dev build. + /// If the target method doesn't exist (e.g. older/newer compat assembly), the native profiler + /// silently skips instrumentation — no exception is thrown. /// [InstrumentMethod( AssemblyName = "Datadog.Serverless.Compat", @@ -25,7 +28,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless MethodName = "CalculateTracePipeName", ReturnTypeName = ClrNames.String, ParameterTypeNames = new string[0], - MinimumVersion = "1.0.0", + MinimumVersion = "0.0.0", MaximumVersion = "2.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), InstrumentationCategory = InstrumentationCategory.Tracing)] From 2bda3a7643aef3ea0b09cbf2a49ffa5446500ccc Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 4 Mar 2026 16:22:42 -0500 Subject: [PATCH 16/38] Regenerate calltargets and trimming files for MinimumVersion 0.0.0 Co-Authored-By: Claude Opus 4.6 --- tracer/build/supported_calltargets.g.json | 4 ++-- .../build/Datadog.Trace.Trimming.xml | 7 ------- .../Generated/generated_calltargets.g.cpp | 4 ++-- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/tracer/build/supported_calltargets.g.json b/tracer/build/supported_calltargets.g.json index a26724d17e2d..01e09470efd5 100644 --- a/tracer/build/supported_calltargets.g.json +++ b/tracer/build/supported_calltargets.g.json @@ -16467,7 +16467,7 @@ "TargetReturnType": "System.String", "TargetParameterTypes": [], "MinimumVersion": { - "Item1": 1, + "Item1": 0, "Item2": 0, "Item3": 0 }, @@ -16489,7 +16489,7 @@ "TargetReturnType": "System.String", "TargetParameterTypes": [], "MinimumVersion": { - "Item1": 1, + "Item1": 0, "Item2": 0, "Item3": 0 }, diff --git a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml index 794b281f9e3f..a6d07d24ce3c 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -163,7 +163,6 @@ - @@ -534,7 +533,6 @@ - @@ -569,14 +567,12 @@ - - @@ -590,7 +586,6 @@ - @@ -600,7 +595,6 @@ - @@ -1094,7 +1088,6 @@ - diff --git a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp index 30a9f1082a6f..a228a62c2c76 100644 --- a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp +++ b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp @@ -1100,8 +1100,8 @@ std::vector callTargets = {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,2,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Pipeline.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,1,4,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.LoggerConfiguration"),(WCHAR*)WStr("CreateLogger"),sig124,1,1,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation"),CallTargetKind::Default,1,15}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,1,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,0,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,0,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig002,5,4,0,0,6,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig003,6,6,0,0,10,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Microsoft.Data.SqlClient"),(WCHAR*)WStr("Microsoft.Data.SqlClient.SqlCommand"),(WCHAR*)WStr("ExecuteDbDataReader"),sig140,2,1,0,0,7,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteReaderWithBehaviorIntegration"),CallTargetKind::Default,1,15}, From b8a2f7eec9d5bbffd249b40908dfff0d4321d6e8 Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 4 Mar 2026 16:30:59 -0500 Subject: [PATCH 17/38] Deduplicate pipe name generation, remove double-logging, use collection expressions - Remove duplicated GenerateUniquePipeName from ExporterSettings, delegate to ServerlessCompatPipeNameHelper - Remove #if !NETFRAMEWORK guard from helper (no .NET Core-only APIs used) - Remove redundant Log.Information from helper (callers already log) - Use [] instead of new string[0] for ParameterTypeNames per project convention Co-Authored-By: Claude Opus 4.6 --- ..._CalculateDogStatsDPipeName_Integration.cs | 2 +- ...ayer_CalculateTracePipeName_Integration.cs | 2 +- .../ServerlessCompatPipeNameHelper.cs | 3 --- .../Configuration/ExporterSettings.cs | 24 +------------------ 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 479fa46cf8af..5d7a76e6d62c 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -27,7 +27,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless TypeName = "Datadog.Serverless.CompatibilityLayer", MethodName = "CalculateDogStatsDPipeName", ReturnTypeName = ClrNames.String, - ParameterTypeNames = new string[0], + ParameterTypeNames = [], MinimumVersion = "0.0.0", MaximumVersion = "2.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 30022cef8e78..f7e350efc28b 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -27,7 +27,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless TypeName = "Datadog.Serverless.CompatibilityLayer", MethodName = "CalculateTracePipeName", ReturnTypeName = ClrNames.String, - ParameterTypeNames = new string[0], + ParameterTypeNames = [], MinimumVersion = "0.0.0", MaximumVersion = "2.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 87ae5abf3dc4..208477f65454 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -5,7 +5,6 @@ #nullable enable -#if !NETFRAMEWORK using System; using Datadog.Trace.Logging; @@ -42,9 +41,7 @@ internal static string GenerateUniquePipeName(string baseName, string pipeType) var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) var uniqueName = $"{baseName}_{guid}"; - Log.Information("ServerlessCompat integration: Generated unique {PipeType} pipe name: {PipeName}", pipeType, uniqueName); return uniqueName; } } } -#endif diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index adbeffdf5b65..f9000c80427a 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -283,30 +283,8 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return null; } - /// - /// Generates a unique pipe name by appending a GUID to the base name. - /// Used in Azure Functions to avoid conflicts when multiple functions run in the same hosting plan. - /// - /// The base name for the pipe - /// A unique pipe name in the format {base}_{guid} private static string GenerateUniquePipeName(string baseName) - { - // Validate base pipe name length before appending GUID - // Windows pipe path format: \\.\pipe\{base}_{guid} - // Max total: 256 - 9 (\\.\pipe\) - 1 (underscore) - 32 (GUID) = 214 - const int maxBaseLength = 214; - - if (baseName.Length > maxBaseLength) - { - Log.Warning("Pipe base name exceeds {MaxLength} characters ({ActualLength}). Truncating to allow for GUID suffix.", maxBaseLength, baseName.Length); - baseName = baseName.Substring(0, maxBaseLength); - } - - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) - var uniqueName = $"{baseName}_{guid}"; - - return uniqueName; - } + => ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); private MetricsTransportSettings ConfigureMetricsTransport(string? metricsUrl, string? traceAgentUrl, string? agentHost, int dogStatsdPort, string? metricsPipeName, string? metricsUnixDomainSocketPath) { From e3c299c80ba4e0c8fd2dcebc873a606c65b4460b Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 5 Mar 2026 11:18:35 -0500 Subject: [PATCH 18/38] Add unit tests for ServerlessCompat pipe name generation and integrations - ServerlessCompatPipeNameHelper: format, truncation, uniqueness - Integration OnMethodEnd: exception passthrough, caching, override behavior - ExporterSettings: constructor pipe name selection, generated name format Co-Authored-By: Claude Opus 4.6 --- .../ServerlessCompatIntegrationTests.cs | 122 ++++++++++++++++++ .../ServerlessCompatPipeNameHelperTests.cs | 64 +++++++++ ...ExporterSettingsAzureFunctionsPipeTests.cs | 107 +++++++++++++++ 3 files changed, 293 insertions(+) create mode 100644 tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs create mode 100644 tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs create mode 100644 tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs diff --git a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs new file mode 100644 index 000000000000..5518c4ed32de --- /dev/null +++ b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -0,0 +1,122 @@ +// +// 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 + +#if !NETFRAMEWORK + +using System; +using System.Reflection; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; +using Datadog.Trace.ClrProfiler.CallTarget; +using FluentAssertions; +using Xunit; + +namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless +{ + public class ServerlessCompatIntegrationTests : IDisposable + { + public ServerlessCompatIntegrationTests() + { + // Reset static caches before each test + ResetStaticField(typeof(CompatibilityLayer_CalculateTracePipeName_Integration), "_cachedTracePipeName"); + ResetStaticField(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration), "_cachedDogStatsDPipeName"); + } + + public void Dispose() + { + // Reset static caches after each test to avoid poisoning other tests + ResetStaticField(typeof(CompatibilityLayer_CalculateTracePipeName_Integration), "_cachedTracePipeName"); + ResetStaticField(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration), "_cachedDogStatsDPipeName"); + } + + [Fact] + public void TracePipe_OnMethodEnd_ReturnsOriginalValue_WhenExceptionIsNonNull() + { + var originalValue = "compat_pipe"; + var exception = new InvalidOperationException("test"); + var state = CallTargetState.GetDefault(); + + var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, originalValue, exception, in state); + + result.GetReturnValue().Should().Be(originalValue); + } + + [Fact] + public void DogStatsDPipe_OnMethodEnd_ReturnsOriginalValue_WhenExceptionIsNonNull() + { + var originalValue = "compat_pipe"; + var exception = new InvalidOperationException("test"); + var state = CallTargetState.GetDefault(); + + var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, originalValue, exception, in state); + + result.GetReturnValue().Should().Be(originalValue); + } + + [Fact] + public void TracePipe_OnMethodEnd_ReturnsCachedPipeName_AcrossMultipleInvocations() + { + var state = CallTargetState.GetDefault(); + + var first = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, "compat1", null!, in state); + + var second = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, "compat2", null!, in state); + + first.GetReturnValue().Should().Be(second.GetReturnValue()); + } + + [Fact] + public void DogStatsDPipe_OnMethodEnd_ReturnsCachedPipeName_AcrossMultipleInvocations() + { + var state = CallTargetState.GetDefault(); + + var first = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, "compat1", null!, in state); + + var second = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, "compat2", null!, in state); + + first.GetReturnValue().Should().Be(second.GetReturnValue()); + } + + [Fact] + public void TracePipe_OnMethodEnd_OverridesCompatLayerValue() + { + var compatValue = "compat_trace_pipe"; + var state = CallTargetState.GetDefault(); + + var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( + null!, compatValue, null!, in state); + + result.GetReturnValue().Should().NotBe(compatValue); + result.GetReturnValue().Should().NotBeNullOrEmpty(); + } + + [Fact] + public void DogStatsDPipe_OnMethodEnd_OverridesCompatLayerValue() + { + var compatValue = "compat_dogstatsd_pipe"; + var state = CallTargetState.GetDefault(); + + var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( + null!, compatValue, null!, in state); + + result.GetReturnValue().Should().NotBe(compatValue); + result.GetReturnValue().Should().NotBeNullOrEmpty(); + } + + private static void ResetStaticField(Type type, string fieldName) + { + var field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic); + field?.SetValue(null, null); + } + } +} +#endif diff --git a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs new file mode 100644 index 000000000000..31468667e9e6 --- /dev/null +++ b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs @@ -0,0 +1,64 @@ +// +// 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 Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; +using FluentAssertions; +using Xunit; + +namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless +{ + public class ServerlessCompatPipeNameHelperTests + { + [Theory] + [InlineData("")] + [InlineData("x")] + [InlineData("dd_trace")] + [InlineData("dd_dogstatsd")] + public void GenerateUniquePipeName_ReturnsCorrectFormat(string baseName) + { + var result = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "test"); + + // Format: {baseName}_{32-char-hex-guid} + result.Should().StartWith(baseName + "_"); + var guidPart = result.Substring(baseName.Length + 1); + guidPart.Should().HaveLength(32); + Guid.TryParse(guidPart, out _).Should().BeTrue(); + } + + [Fact] + public void GenerateUniquePipeName_TruncatesBaseNameExceeding214Chars() + { + var longBase = new string('a', 215); + + var result = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(longBase, "test"); + + // Truncated to 214 + "_" + 32-char guid = 247 total + result.Should().HaveLength(214 + 1 + 32); + } + + [Fact] + public void GenerateUniquePipeName_BaseNameAtLimit_IsNotTruncated() + { + var exactBase = new string('a', 214); + + var result = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(exactBase, "test"); + + result.Should().StartWith(exactBase + "_"); + result.Should().HaveLength(214 + 1 + 32); + } + + [Fact] + public void GenerateUniquePipeName_ProducesDifferentNamesPerCall() + { + var first = ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_trace", "test"); + var second = ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_trace", "test"); + + first.Should().NotBe(second); + } + } +} diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs new file mode 100644 index 000000000000..4866dd9e1002 --- /dev/null +++ b/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs @@ -0,0 +1,107 @@ +// +// 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.Collections.Specialized; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Configuration.Telemetry; +using FluentAssertions; +using Xunit; +using MetricsTransportType = Datadog.Trace.Vendors.StatsdClient.Transport.TransportType; + +namespace Datadog.Trace.Tests.Configuration +{ + public class ExporterSettingsAzureFunctionsPipeTests + { + [Theory] + [InlineData("my_explicit_pipe", "my_explicit_pipe")] + [InlineData("", null)] + [InlineData(null, null)] + public void Constructor_SelectsCorrectTracesPipeName(string? explicitPipeName, string? expectedPipeName) + { + var config = new NameValueCollection(); + if (explicitPipeName is not null) + { + config.Add(ConfigurationKeys.TracesPipeName, explicitPipeName); + } + + var source = new NameValueConfigurationSource(config); + var settings = new ExporterSettings(source, _ => false, NullConfigurationTelemetry.Instance); + + if (expectedPipeName is not null) + { + settings.TracesPipeName.Should().Be(expectedPipeName); + settings.TracesTransport.Should().Be(TracesTransportType.WindowsNamedPipe); + } + else + { + // When no explicit pipe name and no Azure Functions generated name, + // pipe name should be null or the Azure Functions generated value + var azureFuncName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName; + settings.TracesPipeName.Should().Be(azureFuncName); + } + } + + [Theory] + [InlineData("my_explicit_pipe", "my_explicit_pipe")] + [InlineData("", null)] + [InlineData(null, null)] + public void Constructor_SelectsCorrectMetricsPipeName(string? explicitPipeName, string? expectedPipeName) + { + var config = new NameValueCollection(); + if (explicitPipeName is not null) + { + config.Add(ConfigurationKeys.MetricsPipeName, explicitPipeName); + } + + var source = new NameValueConfigurationSource(config); + var settings = new ExporterSettings(source, _ => false, NullConfigurationTelemetry.Instance); + + if (expectedPipeName is not null) + { + settings.MetricsPipeName.Should().Be(expectedPipeName); + settings.MetricsTransport.Should().Be(MetricsTransportType.NamedPipe); + } + else + { + var azureFuncName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName; + settings.MetricsPipeName.Should().Be(azureFuncName); + } + } + + // Note: AzureFunctionsGeneratedPipeName_IsSet_WhenInAzureFunctionsWithoutExplicitConfig + // and AzureFunctionsGeneratedPipeName_IsNull_WhenExplicitPipeNameConfigured cannot be + // reliably tested as unit tests because the static fields are initialized at type-load + // time from real environment variables (WEBSITE_SITE_NAME, FUNCTIONS_WORKER_RUNTIME, + // FUNCTIONS_EXTENSION_VERSION). By the time tests run, ExporterSettings is already loaded. + // These scenarios are covered by the Azure Functions integration tests instead. + + [Fact] + public void AzureFunctionsGeneratedTracesPipeName_IsNullOrValidFormat() + { + // We can't control the env vars at type-load time, but we can verify + // that whatever value was generated (or not) has the correct format + var name = ExporterSettings.AzureFunctionsGeneratedTracesPipeName; + if (name is not null) + { + name.Should().StartWith("dd_trace_"); + name.Should().HaveLength("dd_trace_".Length + 32); + } + } + + [Fact] + public void AzureFunctionsGeneratedMetricsPipeName_IsNullOrValidFormat() + { + var name = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName; + if (name is not null) + { + name.Should().StartWith("dd_dogstatsd_"); + name.Should().HaveLength("dd_dogstatsd_".Length + 32); + } + } + } +} From bf996103149a1c135104df3d1fdd1f317f049a57 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Mar 2026 10:05:51 -0500 Subject: [PATCH 19/38] Gate pipe transport on compat layer presence and version Check for the compat binary and DLL on disk before generating pipe names in ExporterSettings static init. This prevents the tracer from switching to pipe transport when no compat layer is deployed to listen on the pipe. The version check allows 0.0.0 (dev builds) or >= 1.4.0 (first release with named pipe support). Also fix integration fallbacks to pass through the compat layer's return value instead of generating a new random GUID when no pre-generated pipe name exists. Co-Authored-By: Claude Opus 4.6 --- ..._CalculateDogStatsDPipeName_Integration.cs | 8 +-- ...ayer_CalculateTracePipeName_Integration.cs | 8 +-- .../Configuration/ExporterSettings.cs | 64 ++++++++++++++++++- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 5d7a76e6d62c..518c1b56dfe4 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -72,12 +72,10 @@ internal static CallTargetReturn OnMethodEnd( if (_cachedDogStatsDPipeName == null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // Otherwise, generate a unique pipe name with default base - // The tracer controls the pipe name, not the compat layer + // If no pre-generated name exists (e.g. explicit config or compat check failed), + // pass through the compat layer's own pipe name _cachedDogStatsDPipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName - ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - "dd_dogstatsd", - "DogStatsD"); + ?? returnValue; } } } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index f7e350efc28b..7f5c89d53a3d 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -72,12 +72,10 @@ internal static CallTargetReturn OnMethodEnd( if (_cachedTracePipeName == null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // Otherwise, generate a unique pipe name with default base - // The tracer controls the pipe name, not the compat layer + // If no pre-generated name exists (e.g. explicit config or compat check failed), + // pass through the compat layer's own pipe name _cachedTracePipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName - ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName( - "dd_trace", - "trace"); + ?? returnValue; } } } diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index f9000c80427a..2b974bf1f30b 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -10,6 +10,8 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; using Datadog.Trace.Agent; using Datadog.Trace.Configuration.ConfigurationSources; using Datadog.Trace.Configuration.Telemetry; @@ -259,7 +261,8 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName))) + && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName)) + && IsCompatLayerAvailableWithPipeSupport()) { var name = GenerateUniquePipeName("dd_trace"); Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", name); @@ -273,7 +276,8 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName))) + && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName)) + && IsCompatLayerAvailableWithPipeSupport()) { var name = GenerateUniquePipeName("dd_dogstatsd"); Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", name); @@ -283,6 +287,62 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return null; } + /// + /// Checks whether the Datadog Serverless Compat layer is deployed and has a version + /// that supports named pipe transport. This is called during static initialization + /// (before the compat assembly is loaded) so it checks files on disk rather than + /// loaded assemblies. + /// + private static bool IsCompatLayerAvailableWithPipeSupport() + { + try + { + // Named pipes are Windows-only + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return false; + } + + // Check that the compat binary exists — it's what actually listens on the named pipe + // Check that the compat DLL exists and has a version that supports named pipes. + // Named pipe support was added in compat version 1.4.0 (dev builds use 0.0.0). + const string compatBinaryPath = @"C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe"; + var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Datadog.Serverless.Compat.dll"); + if (!File.Exists(compatBinaryPath) || !File.Exists(compatDllPath)) + { + Log.Debug("Did not find Serverless Compatability Layer or related DLLs.", compatDllPath); + return false; + } + + var assemblyName = AssemblyName.GetAssemblyName(compatDllPath); + var version = assemblyName.Version; + + if (version == null) + { + Log.Warning("Could not read Serverless Compatability Layer details at {Path}, using fallback agent communication methods. (No Named Pipes)", compatDllPath); + return false; + } + + // Allow 0.0.0 (dev builds) or >= 1.4.0 (first release with pipe support) + var minVersion = new Version(1, 4, 0); + var devVersion = new Version(0, 0, 0); + + if (version == devVersion || version >= minVersion) + { + Log.Debug("Compat layer version {Version} supports named pipes.", version); + return true; + } + + Log.Debug("Compat layer version {Version} does not support named pipes (requires v{MinVersion} or greater. Using fallback communication methods.)", version, minVersion); + return false; + } + catch (Exception ex) + { + Log.Warning(ex, "Failed to determine Serverless Compatability layer availability or Named Pipe Support."); + return false; + } + } + private static string GenerateUniquePipeName(string baseName) => ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); From 197cabfa8027f5d2dffd94c11e7a2969acba0051 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Mar 2026 10:45:38 -0500 Subject: [PATCH 20/38] Fix compilation errors in IsCompatLayerAvailableWithPipeSupport - Wrap RuntimeInformation.IsOSPlatform in #if !NETFRAMEWORK (net461 doesn't have it) - Add null-coalescing for AppDomain.CurrentDomain.BaseDirectory (nullable warning) - Remove unused argument from Log.Debug call (DDLOG003 analyzer error) Co-Authored-By: Claude Opus 4.6 --- tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 2b974bf1f30b..d66c3cdb47af 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -298,19 +298,21 @@ private static bool IsCompatLayerAvailableWithPipeSupport() try { // Named pipes are Windows-only +#if !NETFRAMEWORK if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return false; } +#endif // Check that the compat binary exists — it's what actually listens on the named pipe // Check that the compat DLL exists and has a version that supports named pipes. // Named pipe support was added in compat version 1.4.0 (dev builds use 0.0.0). const string compatBinaryPath = @"C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe"; - var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Datadog.Serverless.Compat.dll"); + var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? string.Empty, "Datadog.Serverless.Compat.dll"); if (!File.Exists(compatBinaryPath) || !File.Exists(compatDllPath)) { - Log.Debug("Did not find Serverless Compatability Layer or related DLLs.", compatDllPath); + Log.Debug("Did not find Serverless Compatability Layer or related DLLs."); return false; } From e924fc81b23fdeef67e88dff6b2a3619b5111246 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Mar 2026 11:37:36 -0500 Subject: [PATCH 21/38] Generate unique pipe name in integrations when no pre-generated name exists When ExporterSettings hasn't pre-generated a pipe name, the integrations now generate one via ServerlessCompatPipeNameHelper instead of falling back to the compat layer's value. Also use realistic GUID-format pipe names in test fixtures to match actual compat layer behavior. Co-Authored-By: Claude Opus 4.6 --- ...tyLayer_CalculateDogStatsDPipeName_Integration.cs | 4 ++-- ...bilityLayer_CalculateTracePipeName_Integration.cs | 4 ++-- .../Serverless/ServerlessCompatIntegrationTests.cs | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 518c1b56dfe4..7ec5991a725c 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -73,9 +73,9 @@ internal static CallTargetReturn OnMethodEnd( { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) // If no pre-generated name exists (e.g. explicit config or compat check failed), - // pass through the compat layer's own pipe name + // generate a unique name so both tracer and compat layer agree on the same pipe _cachedDogStatsDPipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName - ?? returnValue; + ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_dogstatsd", "DogStatsD"); } } } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 7f5c89d53a3d..e9c967523d4f 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -73,9 +73,9 @@ internal static CallTargetReturn OnMethodEnd( { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) // If no pre-generated name exists (e.g. explicit config or compat check failed), - // pass through the compat layer's own pipe name + // generate a unique name so both tracer and compat layer agree on the same pipe _cachedTracePipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName - ?? returnValue; + ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_trace", "trace"); } } } diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 3a2dc8ecab4d..1fdd4cfad811 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -22,8 +22,8 @@ public void TracePipeName_WithPreGeneratedName_ReturnsTracerValue() { // Arrange ResetCachedPipeNames(); - const string preGeneratedName = "dd_trace_test123"; - const string compatLayerName = "dd_trace_compat456"; + const string preGeneratedName = "dd_trace_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const string compatLayerName = "dd_trace_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; SetExporterSettingsGeneratedNames(preGeneratedName, null); // Act @@ -42,7 +42,7 @@ public void TracePipeName_WithoutPreGeneratedName_GeneratesUniqueName() { // Arrange ResetCachedPipeNames(); - const string compatLayerName = "dd_trace_compat456"; + const string compatLayerName = "dd_trace_00000000000000000000000000000000"; SetExporterSettingsGeneratedNames(null, null); // Act @@ -88,8 +88,8 @@ public void DogStatsDPipeName_WithPreGeneratedName_ReturnsTracerValue() { // Arrange ResetCachedPipeNames(); - const string preGeneratedName = "dd_dogstatsd_test123"; - const string compatLayerName = "dd_dogstatsd_compat456"; + const string preGeneratedName = "dd_dogstatsd_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const string compatLayerName = "dd_dogstatsd_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; SetExporterSettingsGeneratedNames(null, preGeneratedName); // Act @@ -108,7 +108,7 @@ public void DogStatsDPipeName_WithoutPreGeneratedName_GeneratesUniqueName() { // Arrange ResetCachedPipeNames(); - const string compatLayerName = "dd_dogstatsd_compat456"; + const string compatLayerName = "dd_dogstatsd_00000000000000000000000000000000"; SetExporterSettingsGeneratedNames(null, null); // Act From ca3e07a7f4f1f91662c10d04a13f1fa67202bd60 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Mar 2026 13:23:17 -0500 Subject: [PATCH 22/38] Fix typos, apply code standards, and deduplicate tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix "Compatability" → "Compatibility" typo (3 occurrences) - Use `is null` / `is not null` instead of `== null` / `!= null` - Use `StringUtil.IsNullOrEmpty()` instead of `string.IsNullOrEmpty()` - Remove duplicate test file in Datadog.Trace.Tests - Remove tests already covered by ServerlessCompatPipeNameHelperTests - Fix SA1508 blank line before closing brace in PlatformKeys Co-Authored-By: Claude Opus 4.6 --- ..._CalculateDogStatsDPipeName_Integration.cs | 6 +- ...ayer_CalculateTracePipeName_Integration.cs | 6 +- .../Configuration/ExporterSettings.cs | 16 +-- .../ServerlessCompatIntegrationTests.cs | 29 ----- .../ServerlessCompatIntegrationTests.cs | 122 ------------------ 5 files changed, 14 insertions(+), 165 deletions(-) delete mode 100644 tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 7ec5991a725c..78dde6468773 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -55,7 +55,7 @@ internal static CallTargetReturn OnMethodEnd( Exception exception, in CallTargetState state) { - if (exception != null) + if (exception is not null) { // If there was an exception, pass it through return new CallTargetReturn(returnValue); @@ -65,11 +65,11 @@ internal static CallTargetReturn OnMethodEnd( { // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) // Use lazy caching to avoid repeated lookups - if (_cachedDogStatsDPipeName == null) + if (_cachedDogStatsDPipeName is null) { lock (_lock) { - if (_cachedDogStatsDPipeName == null) + if (_cachedDogStatsDPipeName is null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) // If no pre-generated name exists (e.g. explicit config or compat check failed), diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index e9c967523d4f..401f9b256560 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -55,7 +55,7 @@ internal static CallTargetReturn OnMethodEnd( Exception exception, in CallTargetState state) { - if (exception != null) + if (exception is not null) { // If there was an exception, pass it through return new CallTargetReturn(returnValue); @@ -65,11 +65,11 @@ internal static CallTargetReturn OnMethodEnd( { // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) // Use lazy caching to avoid repeated lookups - if (_cachedTracePipeName == null) + if (_cachedTracePipeName is null) { lock (_lock) { - if (_cachedTracePipeName == null) + if (_cachedTracePipeName is null) { // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) // If no pre-generated name exists (e.g. explicit config or compat check failed), diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index d66c3cdb47af..55825398f3e6 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -110,8 +110,8 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi // Use statically-generated pipe names for Azure Functions if no explicit config was provided. // The static fields are initialized once at type-load time via InitAzureFunctions*PipeName(). - var tracesPipeName = !string.IsNullOrEmpty(rawSettings.TracesPipeName) ? rawSettings.TracesPipeName : _azureFunctionsGeneratedTracesPipeName; - var metricsPipeName = !string.IsNullOrEmpty(rawSettings.MetricsPipeName) ? rawSettings.MetricsPipeName : _azureFunctionsGeneratedMetricsPipeName; + var tracesPipeName = !StringUtil.IsNullOrEmpty(rawSettings.TracesPipeName) ? rawSettings.TracesPipeName : _azureFunctionsGeneratedTracesPipeName; + var metricsPipeName = !StringUtil.IsNullOrEmpty(rawSettings.MetricsPipeName) ? rawSettings.MetricsPipeName : _azureFunctionsGeneratedMetricsPipeName; var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, @@ -261,7 +261,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName)) + && StringUtil.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName)) && IsCompatLayerAvailableWithPipeSupport()) { var name = GenerateUniquePipeName("dd_trace"); @@ -276,7 +276,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && string.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName)) + && StringUtil.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName)) && IsCompatLayerAvailableWithPipeSupport()) { var name = GenerateUniquePipeName("dd_dogstatsd"); @@ -312,16 +312,16 @@ private static bool IsCompatLayerAvailableWithPipeSupport() var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? string.Empty, "Datadog.Serverless.Compat.dll"); if (!File.Exists(compatBinaryPath) || !File.Exists(compatDllPath)) { - Log.Debug("Did not find Serverless Compatability Layer or related DLLs."); + Log.Debug("Did not find Serverless Compatibility Layer or related DLLs."); return false; } var assemblyName = AssemblyName.GetAssemblyName(compatDllPath); var version = assemblyName.Version; - if (version == null) + if (version is null) { - Log.Warning("Could not read Serverless Compatability Layer details at {Path}, using fallback agent communication methods. (No Named Pipes)", compatDllPath); + Log.Warning("Could not read Serverless Compatibility Layer details at {Path}, using fallback agent communication methods. (No Named Pipes)", compatDllPath); return false; } @@ -340,7 +340,7 @@ private static bool IsCompatLayerAvailableWithPipeSupport() } catch (Exception ex) { - Log.Warning(ex, "Failed to determine Serverless Compatability layer availability or Named Pipe Support."); + Log.Warning(ex, "Failed to determine Serverless Compatibility layer availability or Named Pipe Support."); return false; } } diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 1fdd4cfad811..6dbb0297c4d8 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -168,35 +168,6 @@ public void OnMethodEnd_WithException_PassesThroughOriginalValue(string pipeType result.GetReturnValue().Should().Be(originalValue); } - [Theory] - [InlineData("dd_trace", "trace")] - [InlineData("dd_dogstatsd", "DogStatsD")] - public void GeneratedPipeName_HasCorrectFormat(string baseName, string pipeType) - { - // Act - var pipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, pipeType); - - // Assert - pipeName.Should().StartWith($"{baseName}_"); - pipeName.Should().MatchRegex($@"^{baseName}_[a-f0-9]{{32}}$"); // base_guid with 32 hex chars - pipeName.Length.Should().BeLessOrEqualTo(247); // 214 base + 1 underscore + 32 guid = 247 max - } - - [Fact] - public void GeneratedPipeName_WithLongBaseName_Truncates() - { - // Arrange - create a base name longer than 214 characters - var longBaseName = new string('a', 220); - - // Act - var pipeName = ServerlessCompatPipeNameHelper.GenerateUniquePipeName(longBaseName, "test"); - - // Assert - // Should be truncated to 214 + 1 underscore + 32 guid = 247 total - pipeName.Length.Should().Be(247); - pipeName.Should().MatchRegex(@"^a{214}_[a-f0-9]{32}$"); - } - // Clear cached values between tests using reflection. // The integration classes cache their resolved pipe name in a static field; // resetting these allows each test to start fresh. diff --git a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs deleted file mode 100644 index 5518c4ed32de..000000000000 --- a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ /dev/null @@ -1,122 +0,0 @@ -// -// 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 - -#if !NETFRAMEWORK - -using System; -using System.Reflection; -using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; -using Datadog.Trace.ClrProfiler.CallTarget; -using FluentAssertions; -using Xunit; - -namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless -{ - public class ServerlessCompatIntegrationTests : IDisposable - { - public ServerlessCompatIntegrationTests() - { - // Reset static caches before each test - ResetStaticField(typeof(CompatibilityLayer_CalculateTracePipeName_Integration), "_cachedTracePipeName"); - ResetStaticField(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration), "_cachedDogStatsDPipeName"); - } - - public void Dispose() - { - // Reset static caches after each test to avoid poisoning other tests - ResetStaticField(typeof(CompatibilityLayer_CalculateTracePipeName_Integration), "_cachedTracePipeName"); - ResetStaticField(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration), "_cachedDogStatsDPipeName"); - } - - [Fact] - public void TracePipe_OnMethodEnd_ReturnsOriginalValue_WhenExceptionIsNonNull() - { - var originalValue = "compat_pipe"; - var exception = new InvalidOperationException("test"); - var state = CallTargetState.GetDefault(); - - var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, originalValue, exception, in state); - - result.GetReturnValue().Should().Be(originalValue); - } - - [Fact] - public void DogStatsDPipe_OnMethodEnd_ReturnsOriginalValue_WhenExceptionIsNonNull() - { - var originalValue = "compat_pipe"; - var exception = new InvalidOperationException("test"); - var state = CallTargetState.GetDefault(); - - var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, originalValue, exception, in state); - - result.GetReturnValue().Should().Be(originalValue); - } - - [Fact] - public void TracePipe_OnMethodEnd_ReturnsCachedPipeName_AcrossMultipleInvocations() - { - var state = CallTargetState.GetDefault(); - - var first = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, "compat1", null!, in state); - - var second = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, "compat2", null!, in state); - - first.GetReturnValue().Should().Be(second.GetReturnValue()); - } - - [Fact] - public void DogStatsDPipe_OnMethodEnd_ReturnsCachedPipeName_AcrossMultipleInvocations() - { - var state = CallTargetState.GetDefault(); - - var first = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, "compat1", null!, in state); - - var second = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, "compat2", null!, in state); - - first.GetReturnValue().Should().Be(second.GetReturnValue()); - } - - [Fact] - public void TracePipe_OnMethodEnd_OverridesCompatLayerValue() - { - var compatValue = "compat_trace_pipe"; - var state = CallTargetState.GetDefault(); - - var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, compatValue, null!, in state); - - result.GetReturnValue().Should().NotBe(compatValue); - result.GetReturnValue().Should().NotBeNullOrEmpty(); - } - - [Fact] - public void DogStatsDPipe_OnMethodEnd_OverridesCompatLayerValue() - { - var compatValue = "compat_dogstatsd_pipe"; - var state = CallTargetState.GetDefault(); - - var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, compatValue, null!, in state); - - result.GetReturnValue().Should().NotBe(compatValue); - result.GetReturnValue().Should().NotBeNullOrEmpty(); - } - - private static void ResetStaticField(Type type, string fieldName) - { - var field = type.GetField(fieldName, BindingFlags.Static | BindingFlags.NonPublic); - field?.SetValue(null, null); - } - } -} -#endif From 06132ae9b18e20ea0da0f457e5da814bc5451804 Mon Sep 17 00:00:00 2001 From: Lewis Date: Fri, 6 Mar 2026 13:57:08 -0500 Subject: [PATCH 23/38] Use DD_TRACE_PIPE_NAME and DD_DOGSTATSD_PIPE_NAME as base names for unique pipe generation Instead of skipping pipe generation when an explicit pipe name is configured, use the configured value as the base name with a GUID suffix appended. This allows users to customize the pipe base name while still getting per-instance isolation on shared Azure Functions hosting plans. If no explicit pipe name is set, falls back to "dd_trace" / "dd_dogstatsd". Co-Authored-By: Claude Opus 4.6 --- .../Configuration/ExporterSettings.cs | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 55825398f3e6..9ad957ed5af5 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -108,10 +108,12 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); - // Use statically-generated pipe names for Azure Functions if no explicit config was provided. - // The static fields are initialized once at type-load time via InitAzureFunctions*PipeName(). - var tracesPipeName = !StringUtil.IsNullOrEmpty(rawSettings.TracesPipeName) ? rawSettings.TracesPipeName : _azureFunctionsGeneratedTracesPipeName; - var metricsPipeName = !StringUtil.IsNullOrEmpty(rawSettings.MetricsPipeName) ? rawSettings.MetricsPipeName : _azureFunctionsGeneratedMetricsPipeName; + // Use statically-generated pipe names for Azure Functions if available. + // The generated names already incorporate any explicit DD_TRACE_PIPE_NAME / DD_DOGSTATSD_PIPE_NAME + // as the base, with a unique GUID suffix appended. This ensures each function instance gets + // its own pipe even when sharing a hosting plan. + var tracesPipeName = _azureFunctionsGeneratedTracesPipeName ?? rawSettings.TracesPipeName; + var metricsPipeName = _azureFunctionsGeneratedMetricsPipeName ?? rawSettings.MetricsPipeName; var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, @@ -261,11 +263,16 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && StringUtil.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName)) && IsCompatLayerAvailableWithPipeSupport()) { - var name = GenerateUniquePipeName("dd_trace"); - Log.Information("Azure Functions environment detected with no explicit trace pipe name. Generated unique pipe name: {TracesPipeName}", name); + var baseName = Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName); + if (StringUtil.IsNullOrEmpty(baseName)) + { + baseName = "dd_trace"; + } + + var name = GenerateUniquePipeName(baseName!); + Log.Information("Azure Functions environment detected. Using trace pipe base name '{BaseName}', generated unique pipe name: {TracesPipeName}", baseName, name); return name; } @@ -276,11 +283,16 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && StringUtil.IsNullOrEmpty(Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName)) && IsCompatLayerAvailableWithPipeSupport()) { - var name = GenerateUniquePipeName("dd_dogstatsd"); - Log.Information("Azure Functions environment detected with no explicit metrics pipe name. Generated unique pipe name: {MetricsPipeName}", name); + var baseName = Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName); + if (StringUtil.IsNullOrEmpty(baseName)) + { + baseName = "dd_dogstatsd"; + } + + var name = GenerateUniquePipeName(baseName!); + Log.Information("Azure Functions environment detected. Using metrics pipe base name '{BaseName}', generated unique pipe name: {MetricsPipeName}", baseName, name); return name; } From 976857b7712ff9f40afbb821010fe99c6b71ebb4 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 12:09:12 -0400 Subject: [PATCH 24/38] Remove lazy caching and redundant pipe name generation from pipe name integrations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CalculateDogStatsDPipeName and CalculateTracePipeName are each only called once during Start(), so caching is unnecessary. The fallback to generate a new unique name is also removed since ExporterSettings always pre-generates the pipe name before these instrumentations fire, and generating a name the tracer doesn't know about is pointless — fall back to the compat layer's own value instead. Co-Authored-By: Claude Opus 4.6 (1M context) --- ..._CalculateDogStatsDPipeName_Integration.cs | 28 +++++-------------- ...ayer_CalculateTracePipeName_Integration.cs | 28 +++++-------------- 2 files changed, 14 insertions(+), 42 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 78dde6468773..7aa6bd4e9f58 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -37,11 +37,9 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless public sealed class CompatibilityLayer_CalculateDogStatsDPipeName_Integration { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration)); - private static readonly object _lock = new object(); - private static string? _cachedDogStatsDPipeName; /// - /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name + /// OnMethodEnd callback - intercepts the return value and overrides it with a unique pipe name /// /// Type of the target /// Instance value, aka `this` of the instrumented method (null for static methods) @@ -63,30 +61,18 @@ internal static CallTargetReturn OnMethodEnd( try { - // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) - // Use lazy caching to avoid repeated lookups - if (_cachedDogStatsDPipeName is null) - { - lock (_lock) - { - if (_cachedDogStatsDPipeName is null) - { - // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // If no pre-generated name exists (e.g. explicit config or compat check failed), - // generate a unique name so both tracer and compat layer agree on the same pipe - _cachedDogStatsDPipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName - ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_dogstatsd", "DogStatsD"); - } - } - } + // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) + // If no pre-generated name exists, fall back to the compat layer's own calculated name + // since the tracer won't know about any name we generate here anyway + var pipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, - _cachedDogStatsDPipeName); + pipeName); - return new CallTargetReturn(_cachedDogStatsDPipeName); + return new CallTargetReturn(pipeName); } catch (Exception ex) { diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index 401f9b256560..a3d8fbe916ce 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -37,11 +37,9 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless public sealed class CompatibilityLayer_CalculateTracePipeName_Integration { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(CompatibilityLayer_CalculateTracePipeName_Integration)); - private static readonly object _lock = new object(); - private static string? _cachedTracePipeName; /// - /// OnMethodEnd callback - intercepts the return value and overrides it with a lazily-generated unique pipe name + /// OnMethodEnd callback - intercepts the return value and overrides it with a unique pipe name /// /// Type of the target /// Instance value, aka `this` of the instrumented method (null for static methods) @@ -63,30 +61,18 @@ internal static CallTargetReturn OnMethodEnd( try { - // Get the tracer's pipe name (generated in ExporterSettings if on Windows with no explicit config) - // Use lazy caching to avoid repeated lookups - if (_cachedTracePipeName is null) - { - lock (_lock) - { - if (_cachedTracePipeName is null) - { - // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // If no pre-generated name exists (e.g. explicit config or compat check failed), - // generate a unique name so both tracer and compat layer agree on the same pipe - _cachedTracePipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName - ?? ServerlessCompatPipeNameHelper.GenerateUniquePipeName("dd_trace", "trace"); - } - } - } + // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) + // If no pre-generated name exists, fall back to the compat layer's own calculated name + // since the tracer won't know about any name we generate here anyway + var pipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer trace pipe name. " + "Compat layer calculated: {CompatPipeName}, Tracer using: {TracerPipeName}", returnValue, - _cachedTracePipeName); + pipeName); - return new CallTargetReturn(_cachedTracePipeName); + return new CallTargetReturn(pipeName); } catch (Exception ex) { From 0829237f9c6a5f00ad5079e1aa61764f2b6ce91b Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 14:13:08 -0400 Subject: [PATCH 25/38] Move Azure Functions pipe name generation from static init to instance constructor Replace static field initializers that read env vars directly with instance methods that use rawSettings.TracesPipeName/MetricsPipeName, respecting all config sources (env vars, config files, etc.) instead of only environment variables. Record the calculated pipe names in telemetry. Integrations now read pipe names from Tracer.Instance.Settings.Exporter instead of removed static properties. Co-Authored-By: Claude Opus 4.6 (1M context) --- ..._CalculateDogStatsDPipeName_Integration.cs | 9 ++-- ...ayer_CalculateTracePipeName_Integration.cs | 9 ++-- .../Configuration/ExporterSettings.cs | 53 +++++-------------- ...ExporterSettingsAzureFunctionsPipeTests.cs | 47 ++++------------ 4 files changed, 30 insertions(+), 88 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 7aa6bd4e9f58..904e383d5046 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -9,7 +9,6 @@ using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; -using Datadog.Trace.Configuration; using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless @@ -61,10 +60,10 @@ internal static CallTargetReturn OnMethodEnd( try { - // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // If no pre-generated name exists, fall back to the compat layer's own calculated name - // since the tracer won't know about any name we generate here anyway - var pipeName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName ?? returnValue; + // Use the tracer's configured pipe name, which in Azure Functions will be the + // unique name generated by ExporterSettings. Fall back to the compat layer's + // own calculated name if the tracer isn't initialized yet. + var pipeName = Tracer.Instance.Settings?.Exporter?.MetricsPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index a3d8fbe916ce..ff32131c428a 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -9,7 +9,6 @@ using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; -using Datadog.Trace.Configuration; using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless @@ -61,10 +60,10 @@ internal static CallTargetReturn OnMethodEnd( try { - // Use the pipe name pre-generated by ExporterSettings if available (Azure Functions scenario) - // If no pre-generated name exists, fall back to the compat layer's own calculated name - // since the tracer won't know about any name we generate here anyway - var pipeName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName ?? returnValue; + // Use the tracer's configured pipe name, which in Azure Functions will be the + // unique name generated by ExporterSettings. Fall back to the compat layer's + // own calculated name if the tracer isn't initialized yet. + var pipeName = Tracer.Instance.Settings?.Exporter?.TracesPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer trace pipe name. " + diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 9ad957ed5af5..9aab89c04bec 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -31,22 +31,6 @@ public sealed partial class ExporterSettings { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(ExporterSettings)); - /// - /// Backing field for AzureFunctionsGeneratedTracesPipeName. - /// Initialized statically by checking environment variables directly. - /// Only generates a name when running in Azure Functions without AAS Site Extension - /// and without an explicit DD_TRACE_PIPE_NAME configuration. - /// - private static readonly string? _azureFunctionsGeneratedTracesPipeName = InitAzureFunctionsTracesPipeName(); - - /// - /// Backing field for AzureFunctionsGeneratedMetricsPipeName. - /// Initialized statically by checking environment variables directly. - /// Only generates a name when running in Azure Functions without AAS Site Extension - /// and without an explicit DD_DOGSTATSD_PIPE_NAME configuration. - /// - private static readonly string? _azureFunctionsGeneratedMetricsPipeName = InitAzureFunctionsMetricsPipeName(); - /// /// Allows overriding of file system access for tests. /// @@ -108,12 +92,11 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi ValidationWarnings = new List(); - // Use statically-generated pipe names for Azure Functions if available. - // The generated names already incorporate any explicit DD_TRACE_PIPE_NAME / DD_DOGSTATSD_PIPE_NAME - // as the base, with a unique GUID suffix appended. This ensures each function instance gets - // its own pipe even when sharing a hosting plan. - var tracesPipeName = _azureFunctionsGeneratedTracesPipeName ?? rawSettings.TracesPipeName; - var metricsPipeName = _azureFunctionsGeneratedMetricsPipeName ?? rawSettings.MetricsPipeName; + // In Azure Functions (without AAS Site Extension), generate unique pipe names so each + // function instance gets its own pipe even when sharing a hosting plan. The generated names + // use the user-configured base name (from any config source) with a unique GUID suffix. + var tracesPipeName = GetAzureFunctionsTracesPipeName(rawSettings) ?? rawSettings.TracesPipeName; + var metricsPipeName = GetAzureFunctionsMetricsPipeName(rawSettings) ?? rawSettings.MetricsPipeName; var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, @@ -146,20 +129,6 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi TracesPipeTimeoutMs = rawSettings.TracesPipeTimeoutMs; } - /// - /// Gets the generated trace pipe name for Azure Functions coordination. - /// This is set when running in Azure Functions without explicit pipe name configuration. - /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. - /// - internal static string? AzureFunctionsGeneratedTracesPipeName => _azureFunctionsGeneratedTracesPipeName; - - /// - /// Gets the generated metrics pipe name for Azure Functions coordination. - /// This is set when running in Azure Functions without explicit pipe name configuration. - /// Used by ServerlessCompat instrumentation to coordinate pipe names with compat layer. - /// - internal static string? AzureFunctionsGeneratedMetricsPipeName => _azureFunctionsGeneratedMetricsPipeName; - /// /// Gets the Uri where the Tracer can connect to the Agent. /// Default is "http://localhost:8126". @@ -259,13 +228,13 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return string.IsNullOrEmpty(traceHostname) ? DefaultDogstatsdHostname : traceHostname; } - private static string? InitAzureFunctionsTracesPipeName() + private string? GetAzureFunctionsTracesPipeName(Raw rawSettings) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() && IsCompatLayerAvailableWithPipeSupport()) { - var baseName = Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TracesPipeName); + var baseName = rawSettings.TracesPipeName; if (StringUtil.IsNullOrEmpty(baseName)) { baseName = "dd_trace"; @@ -273,19 +242,20 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) var name = GenerateUniquePipeName(baseName!); Log.Information("Azure Functions environment detected. Using trace pipe base name '{BaseName}', generated unique pipe name: {TracesPipeName}", baseName, name); + _telemetry.Record(ConfigurationKeys.TracesPipeName, name, recordValue: true, ConfigurationOrigins.Calculated); return name; } return null; } - private static string? InitAzureFunctionsMetricsPipeName() + private string? GetAzureFunctionsMetricsPipeName(Raw rawSettings) { if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() && IsCompatLayerAvailableWithPipeSupport()) { - var baseName = Util.EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MetricsPipeName); + var baseName = rawSettings.MetricsPipeName; if (StringUtil.IsNullOrEmpty(baseName)) { baseName = "dd_dogstatsd"; @@ -293,6 +263,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) var name = GenerateUniquePipeName(baseName!); Log.Information("Azure Functions environment detected. Using metrics pipe base name '{BaseName}', generated unique pipe name: {MetricsPipeName}", baseName, name); + _telemetry.Record(ConfigurationKeys.MetricsPipeName, name, recordValue: true, ConfigurationOrigins.Calculated); return name; } @@ -301,7 +272,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) /// /// Checks whether the Datadog Serverless Compat layer is deployed and has a version - /// that supports named pipe transport. This is called during static initialization + /// that supports named pipe transport. This is called during construction /// (before the compat assembly is loaded) so it checks files on disk rather than /// loaded assemblies. /// diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs index 4866dd9e1002..7a6ceae89df2 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/ExporterSettingsAzureFunctionsPipeTests.cs @@ -39,10 +39,11 @@ public void Constructor_SelectsCorrectTracesPipeName(string? explicitPipeName, s } else { - // When no explicit pipe name and no Azure Functions generated name, - // pipe name should be null or the Azure Functions generated value - var azureFuncName = ExporterSettings.AzureFunctionsGeneratedTracesPipeName; - settings.TracesPipeName.Should().Be(azureFuncName); + // When no explicit pipe name is configured and not in Azure Functions, + // pipe transport is not used so TracesPipeName should be null. + // In Azure Functions, the constructor generates a unique name which + // is covered by integration tests. + settings.TracesPipeName.Should().BeNull(); } } @@ -68,39 +69,11 @@ public void Constructor_SelectsCorrectMetricsPipeName(string? explicitPipeName, } else { - var azureFuncName = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName; - settings.MetricsPipeName.Should().Be(azureFuncName); - } - } - - // Note: AzureFunctionsGeneratedPipeName_IsSet_WhenInAzureFunctionsWithoutExplicitConfig - // and AzureFunctionsGeneratedPipeName_IsNull_WhenExplicitPipeNameConfigured cannot be - // reliably tested as unit tests because the static fields are initialized at type-load - // time from real environment variables (WEBSITE_SITE_NAME, FUNCTIONS_WORKER_RUNTIME, - // FUNCTIONS_EXTENSION_VERSION). By the time tests run, ExporterSettings is already loaded. - // These scenarios are covered by the Azure Functions integration tests instead. - - [Fact] - public void AzureFunctionsGeneratedTracesPipeName_IsNullOrValidFormat() - { - // We can't control the env vars at type-load time, but we can verify - // that whatever value was generated (or not) has the correct format - var name = ExporterSettings.AzureFunctionsGeneratedTracesPipeName; - if (name is not null) - { - name.Should().StartWith("dd_trace_"); - name.Should().HaveLength("dd_trace_".Length + 32); - } - } - - [Fact] - public void AzureFunctionsGeneratedMetricsPipeName_IsNullOrValidFormat() - { - var name = ExporterSettings.AzureFunctionsGeneratedMetricsPipeName; - if (name is not null) - { - name.Should().StartWith("dd_dogstatsd_"); - name.Should().HaveLength("dd_dogstatsd_".Length + 32); + // When no explicit pipe name is configured and not in Azure Functions, + // pipe transport is not used so MetricsPipeName should be null. + // In Azure Functions, the constructor generates a unique name which + // is covered by integration tests. + settings.MetricsPipeName.Should().BeNull(); } } } From 8c925c3e6e236378df847ef94415ca5ac6b62c80 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 14:17:06 -0400 Subject: [PATCH 26/38] Hoist Azure Functions check into constructor and consolidate pipe name generation Check the Azure Functions/compat layer condition once in the constructor instead of duplicating it in two separate methods. Consolidate the two per-pipe methods into a single GenerateUniquePipeName overload. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Configuration/ExporterSettings.cs | 62 +++++++------------ 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 9aab89c04bec..21b611fe3bfd 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -95,8 +95,21 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi // In Azure Functions (without AAS Site Extension), generate unique pipe names so each // function instance gets its own pipe even when sharing a hosting plan. The generated names // use the user-configured base name (from any config source) with a unique GUID suffix. - var tracesPipeName = GetAzureFunctionsTracesPipeName(rawSettings) ?? rawSettings.TracesPipeName; - var metricsPipeName = GetAzureFunctionsMetricsPipeName(rawSettings) ?? rawSettings.MetricsPipeName; + string? tracesPipeName; + string? metricsPipeName; + + if (Util.EnvironmentHelpers.IsAzureFunctions() + && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() + && IsCompatLayerAvailableWithPipeSupport()) + { + tracesPipeName = GenerateUniquePipeName(rawSettings.TracesPipeName, "dd_trace", ConfigurationKeys.TracesPipeName); + metricsPipeName = GenerateUniquePipeName(rawSettings.MetricsPipeName, "dd_dogstatsd", ConfigurationKeys.MetricsPipeName); + } + else + { + tracesPipeName = rawSettings.TracesPipeName; + metricsPipeName = rawSettings.MetricsPipeName; + } var traceSettings = GetTraceTransport( agentUri: rawSettings.TraceAgentUri, @@ -228,46 +241,13 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) return string.IsNullOrEmpty(traceHostname) ? DefaultDogstatsdHostname : traceHostname; } - private string? GetAzureFunctionsTracesPipeName(Raw rawSettings) - { - if (Util.EnvironmentHelpers.IsAzureFunctions() - && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && IsCompatLayerAvailableWithPipeSupport()) - { - var baseName = rawSettings.TracesPipeName; - if (StringUtil.IsNullOrEmpty(baseName)) - { - baseName = "dd_trace"; - } - - var name = GenerateUniquePipeName(baseName!); - Log.Information("Azure Functions environment detected. Using trace pipe base name '{BaseName}', generated unique pipe name: {TracesPipeName}", baseName, name); - _telemetry.Record(ConfigurationKeys.TracesPipeName, name, recordValue: true, ConfigurationOrigins.Calculated); - return name; - } - - return null; - } - - private string? GetAzureFunctionsMetricsPipeName(Raw rawSettings) + private string GenerateUniquePipeName(string? configuredBaseName, string defaultBaseName, string configKey) { - if (Util.EnvironmentHelpers.IsAzureFunctions() - && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && IsCompatLayerAvailableWithPipeSupport()) - { - var baseName = rawSettings.MetricsPipeName; - if (StringUtil.IsNullOrEmpty(baseName)) - { - baseName = "dd_dogstatsd"; - } - - var name = GenerateUniquePipeName(baseName!); - Log.Information("Azure Functions environment detected. Using metrics pipe base name '{BaseName}', generated unique pipe name: {MetricsPipeName}", baseName, name); - _telemetry.Record(ConfigurationKeys.MetricsPipeName, name, recordValue: true, ConfigurationOrigins.Calculated); - return name; - } - - return null; + var baseName = StringUtil.IsNullOrEmpty(configuredBaseName) ? defaultBaseName : configuredBaseName!; + var name = GenerateUniquePipeName(baseName); + Log.Information("Azure Functions environment detected. Using pipe base name '{BaseName}', generated unique pipe name: {PipeName}", baseName, name); + _telemetry.Record(configKey, name, recordValue: true, ConfigurationOrigins.Calculated); + return name; } /// From ded3bd48750eb9683e5ff1e992937627f4f9c5f8 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 14:33:44 -0400 Subject: [PATCH 27/38] Move IsCompatLayerAvailableWithPipeSupport to ServerlessCompatPipeNameHelper and make testable Move compat layer detection out of ExporterSettings into ServerlessCompatPipeNameHelper alongside the related pipe name logic. Extract I/O dependencies (file existence, assembly version) as delegates so version-checking logic can be fully unit tested. Add support for DD_SERVERLESS_COMPAT_PATH env var to override the default binary path, matching the compat layer's own behavior. Add comprehensive tests for all branches: version checks, file missing, null version, exceptions. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ServerlessCompatPipeNameHelper.cs | 73 +++++++++++ .../Configuration/ExporterSettings.cs | 67 +--------- .../ServerlessCompatPipeNameHelperTests.cs | 123 ++++++++++++++++++ 3 files changed, 198 insertions(+), 65 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 208477f65454..4042ce5bc81e 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -6,6 +6,9 @@ #nullable enable using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless @@ -43,5 +46,75 @@ internal static string GenerateUniquePipeName(string baseName, string pipeType) return uniqueName; } + + /// + /// Checks whether the Datadog Serverless Compat layer is deployed and has a version + /// that supports named pipe transport. This is called during ExporterSettings construction + /// (before the compat assembly is loaded) so it checks files on disk rather than + /// loaded assemblies. + /// + internal static bool IsCompatLayerAvailableWithPipeSupport() + => IsCompatLayerAvailableWithPipeSupport(File.Exists, path => AssemblyName.GetAssemblyName(path).Version); + + /// + /// Testable overload that accepts I/O dependencies as delegates. + /// + internal static bool IsCompatLayerAvailableWithPipeSupport( + Func fileExists, + Func getAssemblyVersion) + { + try + { + // Named pipes are Windows-only +#if !NETFRAMEWORK + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return false; + } +#endif + + // Check that the compat binary exists — it's what actually listens on the named pipe. + // DD_SERVERLESS_COMPAT_PATH overrides the default binary location + // (matches CompatibilityLayer.cs in datadog-serverless-compat-dotnet). + const string defaultCompatBinaryPath = @"C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe"; + var compatBinaryPath = Util.EnvironmentHelpers.GetEnvironmentVariable("DD_SERVERLESS_COMPAT_PATH") + ?? defaultCompatBinaryPath; + + // Check that the compat DLL exists and has a version that supports named pipes. + // Named pipe support was added in compat version 1.4.0 (dev builds use 0.0.0). + var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? string.Empty, "Datadog.Serverless.Compat.dll"); + if (!fileExists(compatBinaryPath) || !fileExists(compatDllPath)) + { + Log.Debug("Did not find Serverless Compatibility Layer or related DLLs."); + return false; + } + + var version = getAssemblyVersion(compatDllPath); + + if (version is null) + { + Log.Warning("Could not read Serverless Compatibility Layer details at {Path}, using fallback agent communication methods. (No Named Pipes)", compatDllPath); + return false; + } + + // Allow 0.0.0 (dev builds) or >= 1.4.0 (first release with pipe support) + var isDevBuild = version.Major == 0 && version.Minor == 0 && version.Build == 0; + var isSupported = version.Major > 1 || (version.Major == 1 && version.Minor >= 4); + + if (isDevBuild || isSupported) + { + Log.Debug("Compat layer version {Version} supports named pipes.", version); + return true; + } + + Log.Debug("Compat layer version {Version} does not support named pipes (requires v1.4.0 or greater. Using fallback communication methods.)", version); + return false; + } + catch (Exception ex) + { + Log.Warning(ex, "Failed to determine Serverless Compatibility layer availability or Named Pipe Support."); + return false; + } + } } } diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 21b611fe3bfd..11a32db6799a 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -10,8 +10,6 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; using Datadog.Trace.Agent; using Datadog.Trace.Configuration.ConfigurationSources; using Datadog.Trace.Configuration.Telemetry; @@ -100,7 +98,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && IsCompatLayerAvailableWithPipeSupport()) + && ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport()) { tracesPipeName = GenerateUniquePipeName(rawSettings.TracesPipeName, "dd_trace", ConfigurationKeys.TracesPipeName); metricsPipeName = GenerateUniquePipeName(rawSettings.MetricsPipeName, "dd_dogstatsd", ConfigurationKeys.MetricsPipeName); @@ -244,73 +242,12 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) private string GenerateUniquePipeName(string? configuredBaseName, string defaultBaseName, string configKey) { var baseName = StringUtil.IsNullOrEmpty(configuredBaseName) ? defaultBaseName : configuredBaseName!; - var name = GenerateUniquePipeName(baseName); + var name = ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); Log.Information("Azure Functions environment detected. Using pipe base name '{BaseName}', generated unique pipe name: {PipeName}", baseName, name); _telemetry.Record(configKey, name, recordValue: true, ConfigurationOrigins.Calculated); return name; } - /// - /// Checks whether the Datadog Serverless Compat layer is deployed and has a version - /// that supports named pipe transport. This is called during construction - /// (before the compat assembly is loaded) so it checks files on disk rather than - /// loaded assemblies. - /// - private static bool IsCompatLayerAvailableWithPipeSupport() - { - try - { - // Named pipes are Windows-only -#if !NETFRAMEWORK - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return false; - } -#endif - - // Check that the compat binary exists — it's what actually listens on the named pipe - // Check that the compat DLL exists and has a version that supports named pipes. - // Named pipe support was added in compat version 1.4.0 (dev builds use 0.0.0). - const string compatBinaryPath = @"C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe"; - var compatDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? string.Empty, "Datadog.Serverless.Compat.dll"); - if (!File.Exists(compatBinaryPath) || !File.Exists(compatDllPath)) - { - Log.Debug("Did not find Serverless Compatibility Layer or related DLLs."); - return false; - } - - var assemblyName = AssemblyName.GetAssemblyName(compatDllPath); - var version = assemblyName.Version; - - if (version is null) - { - Log.Warning("Could not read Serverless Compatibility Layer details at {Path}, using fallback agent communication methods. (No Named Pipes)", compatDllPath); - return false; - } - - // Allow 0.0.0 (dev builds) or >= 1.4.0 (first release with pipe support) - var minVersion = new Version(1, 4, 0); - var devVersion = new Version(0, 0, 0); - - if (version == devVersion || version >= minVersion) - { - Log.Debug("Compat layer version {Version} supports named pipes.", version); - return true; - } - - Log.Debug("Compat layer version {Version} does not support named pipes (requires v{MinVersion} or greater. Using fallback communication methods.)", version, minVersion); - return false; - } - catch (Exception ex) - { - Log.Warning(ex, "Failed to determine Serverless Compatibility layer availability or Named Pipe Support."); - return false; - } - } - - private static string GenerateUniquePipeName(string baseName) - => ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); - private MetricsTransportSettings ConfigureMetricsTransport(string? metricsUrl, string? traceAgentUrl, string? agentHost, int dogStatsdPort, string? metricsPipeName, string? metricsUnixDomainSocketPath) { if (!string.IsNullOrEmpty(metricsUrl) && TryGetMetricsUriAndTransport(metricsUrl!, out var settingsFromUri)) diff --git a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs index 31468667e9e6..c80fc0d9758f 100644 --- a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs +++ b/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs @@ -6,6 +6,7 @@ #nullable enable using System; +using System.Runtime.InteropServices; using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; using FluentAssertions; using Xunit; @@ -60,5 +61,127 @@ public void GenerateUniquePipeName_ProducesDifferentNamesPerCall() first.Should().NotBe(second); } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_DoesNotThrow() + { + // Should never throw regardless of environment — errors are caught internally + var act = () => ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport(); + + act.Should().NotThrow(); + } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenNotOnWindows() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // This test only validates non-Windows behavior + return; + } + + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport(); + + result.Should().BeFalse(); + } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatBinaryMissing() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + // Binary missing, DLL present + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: path => !path.EndsWith(".exe"), + getAssemblyVersion: _ => new Version(1, 4, 0)); + + result.Should().BeFalse(); + } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatDllMissing() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + // Binary present, DLL missing + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: path => !path.EndsWith(".dll"), + getAssemblyVersion: _ => new Version(1, 4, 0)); + + result.Should().BeFalse(); + } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionIsNull() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: _ => true, + getAssemblyVersion: _ => null); + + result.Should().BeFalse(); + } + + [Theory] + [InlineData(1, 3, 0)] + [InlineData(1, 0, 0)] + [InlineData(0, 1, 0)] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionTooOld(int major, int minor, int build) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: _ => true, + getAssemblyVersion: _ => new Version(major, minor, build)); + + result.Should().BeFalse(); + } + + [Theory] + [InlineData(0, 0, 0)] // dev build + [InlineData(1, 4, 0)] // minimum supported + [InlineData(1, 5, 0)] // above minimum + [InlineData(2, 0, 0)] // major version bump + public void IsCompatLayerAvailableWithPipeSupport_ReturnsTrue_WhenVersionSupported(int major, int minor, int build) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: _ => true, + getAssemblyVersion: _ => new Version(major, minor, build)); + + result.Should().BeTrue(); + } + + [Fact] + public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenGetVersionThrows() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( + fileExists: _ => true, + getAssemblyVersion: _ => throw new BadImageFormatException("not a valid assembly")); + + result.Should().BeFalse(); + } } } From bc51a8e944d8fa380aaba547690505f7ea8a89db Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 14:52:13 -0400 Subject: [PATCH 28/38] Fix build errors: add DD_SERVERLESS_COMPAT_PATH to ConfigurationKeys, fix ExporterSettings access path - Add DD_SERVERLESS_COMPAT_PATH to supported-configurations.yaml so the source generator creates ConfigurationKeys.ServerlessCompatPath - Fix integration classes to use the correct property path: Tracer.Instance.Settings.Manager.InitialExporterSettings - Restore using Datadog.Trace.Configuration (needed for IntegrationId) - Remove unused System.Reflection/InteropServices from ExporterSettings Co-Authored-By: Claude Opus 4.6 (1M context) --- ...ibilityLayer_CalculateDogStatsDPipeName_Integration.cs | 3 ++- ...mpatibilityLayer_CalculateTracePipeName_Integration.cs | 3 ++- .../Serverless/ServerlessCompatPipeNameHelper.cs | 2 +- .../Configuration/supported-configurations.yaml | 8 ++++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index 904e383d5046..ccdc4093b118 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -9,6 +9,7 @@ using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless @@ -63,7 +64,7 @@ internal static CallTargetReturn OnMethodEnd( // Use the tracer's configured pipe name, which in Azure Functions will be the // unique name generated by ExporterSettings. Fall back to the compat layer's // own calculated name if the tracer isn't initialized yet. - var pipeName = Tracer.Instance.Settings?.Exporter?.MetricsPipeName ?? returnValue; + var pipeName = Tracer.Instance.Settings?.Manager?.InitialExporterSettings?.MetricsPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer DogStatsD pipe name. " + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index ff32131c428a..ba45f49d5356 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -9,6 +9,7 @@ using System; using System.ComponentModel; using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; using Datadog.Trace.Logging; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless @@ -63,7 +64,7 @@ internal static CallTargetReturn OnMethodEnd( // Use the tracer's configured pipe name, which in Azure Functions will be the // unique name generated by ExporterSettings. Fall back to the compat layer's // own calculated name if the tracer isn't initialized yet. - var pipeName = Tracer.Instance.Settings?.Exporter?.TracesPipeName ?? returnValue; + var pipeName = Tracer.Instance.Settings?.Manager?.InitialExporterSettings?.TracesPipeName ?? returnValue; Log.Debug( "ServerlessCompat integration: Overriding compat layer trace pipe name. " + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index 4042ce5bc81e..c1e44d5d5316 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -77,7 +77,7 @@ internal static bool IsCompatLayerAvailableWithPipeSupport( // DD_SERVERLESS_COMPAT_PATH overrides the default binary location // (matches CompatibilityLayer.cs in datadog-serverless-compat-dotnet). const string defaultCompatBinaryPath = @"C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe"; - var compatBinaryPath = Util.EnvironmentHelpers.GetEnvironmentVariable("DD_SERVERLESS_COMPAT_PATH") + var compatBinaryPath = Util.EnvironmentHelpers.GetEnvironmentVariable(Configuration.ConfigurationKeys.ServerlessCompatPath) ?? defaultCompatBinaryPath; // Check that the compat DLL exists and has a version that supports named pipes. diff --git a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml index 2e28bea6e6c2..58122adca123 100644 --- a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml +++ b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml @@ -1468,6 +1468,14 @@ supportedConfigurations: Match all spans that start with "cart" without any limits and any operation name. "[{"service": "cart*"}]" + DD_SERVERLESS_COMPAT_PATH: + - implementation: A + type: string + default: null + const_name: ServerlessCompatPath + documentation: |- + Overrides the default path to the serverless compat layer binary. + Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. DD_SYMBOL_DATABASE_BATCH_SIZE_BYTES: - implementation: A type: int From 1df4f5a5fa1853e2bb180a5acff4132eb3d28f38 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 14:54:17 -0400 Subject: [PATCH 29/38] Update generated ConfigurationKeys files for DD_SERVERLESS_COMPAT_PATH Co-Authored-By: Claude Opus 4.6 (1M context) --- .../ConfigurationKeysGenerator/ConfigurationKeys.g.cs | 6 ++++++ .../ConfigurationKeysGenerator/ConfigurationKeys.g.cs | 6 ++++++ .../ConfigurationKeysGenerator/ConfigurationKeys.g.cs | 6 ++++++ .../ConfigurationKeysGenerator/ConfigurationKeys.g.cs | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 1926eaef1500..3528833e13d1 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -242,6 +242,12 @@ internal static partial class ConfigurationKeys /// public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; + /// + /// Overrides the default path to the serverless compat layer binary. + /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// + public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; + /// /// Configuration key for the application's default service name. /// Used as the service name for top-level spans, diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 1926eaef1500..3528833e13d1 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -242,6 +242,12 @@ internal static partial class ConfigurationKeys /// public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; + /// + /// Overrides the default path to the serverless compat layer binary. + /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// + public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; + /// /// Configuration key for the application's default service name. /// Used as the service name for top-level spans, diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 1926eaef1500..3528833e13d1 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -242,6 +242,12 @@ internal static partial class ConfigurationKeys /// public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; + /// + /// Overrides the default path to the serverless compat layer binary. + /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// + public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; + /// /// Configuration key for the application's default service name. /// Used as the service name for top-level spans, diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 1926eaef1500..3528833e13d1 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -242,6 +242,12 @@ internal static partial class ConfigurationKeys /// public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; + /// + /// Overrides the default path to the serverless compat layer binary. + /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// + public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; + /// /// Configuration key for the application's default service name. /// Used as the service name for top-level spans, From 64ced11b4b98649182f58622edba3bc390133d29 Mon Sep 17 00:00:00 2001 From: "E. Lewis" Date: Tue, 24 Mar 2026 14:56:19 -0400 Subject: [PATCH 30/38] Apply suggestions from code review + Maximum Version change Co-authored-by: Andrew Lock --- ...mpatibilityLayer_CalculateDogStatsDPipeName_Integration.cs | 2 +- .../CompatibilityLayer_CalculateTracePipeName_Integration.cs | 2 +- .../Serverless/ServerlessCompatPipeNameHelper.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index ccdc4093b118..ba91a336cb10 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -29,7 +29,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless ReturnTypeName = ClrNames.String, ParameterTypeNames = [], MinimumVersion = "0.0.0", - MaximumVersion = "2.*.*", + MaximumVersion = "1.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), InstrumentationCategory = InstrumentationCategory.Tracing)] [Browsable(false)] diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index ba45f49d5356..efb5baec71d0 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -29,7 +29,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless ReturnTypeName = ClrNames.String, ParameterTypeNames = [], MinimumVersion = "0.0.0", - MaximumVersion = "2.*.*", + MaximumVersion = "1.*.*", IntegrationName = nameof(IntegrationId.ServerlessCompat), InstrumentationCategory = InstrumentationCategory.Tracing)] [Browsable(false)] diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs index c1e44d5d5316..bbf709708641 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs @@ -41,8 +41,8 @@ internal static string GenerateUniquePipeName(string baseName, string pipeType) baseName = baseName.Substring(0, maxBaseLength); } - var guid = Guid.NewGuid().ToString("N"); // "N" format removes hyphens (32 chars) - var uniqueName = $"{baseName}_{guid}"; + // "N" format removes hyphens (32 chars) + var uniqueName = $"{baseName}_{Guid.NewGuid():N}"; return uniqueName; } From 72f274406fe7ec3c48391236b5a4d3693f7ce64e Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 15:07:13 -0400 Subject: [PATCH 31/38] Remove unnecessary null-forgiving operator on configuredBaseName StringUtil.IsNullOrEmpty has [NotNullWhen(false)] so the compiler already knows the value is non-null in the false branch. Co-Authored-By: Claude Opus 4.6 (1M context) --- tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 15e77af0cbe4..dc307fd9733b 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -349,7 +349,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) private string GenerateUniquePipeName(string? configuredBaseName, string defaultBaseName, string configKey) { - var baseName = StringUtil.IsNullOrEmpty(configuredBaseName) ? defaultBaseName : configuredBaseName!; + var baseName = StringUtil.IsNullOrEmpty(configuredBaseName) ? defaultBaseName : configuredBaseName; var name = ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); Log.Information("Azure Functions environment detected. Using pipe base name '{BaseName}', generated unique pipe name: {PipeName}", baseName, name); _telemetry.Record(configKey, name, recordValue: true, ConfigurationOrigins.Calculated); From 32b730da80dcd5befa799fac2836c2e06a4d89b9 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 15:25:19 -0400 Subject: [PATCH 32/38] Update generated native calltargets for MaximumVersion 1.*.*, add DD_SERVERLESS_COMPAT_PATH config key Update supported_calltargets.g.json and generated_calltargets.g.cpp to reflect MaximumVersion change from 2.*.* to 1.*.*. Add DD_SERVERLESS_COMPAT_PATH to supported-configurations.yaml and restore ConfigurationKeys usage in ServerlessCompatPipeNameHelper. Co-Authored-By: Claude Opus 4.6 (1M context) --- tracer/build/supported_calltargets.g.json | 4 ++-- .../Generated/generated_calltargets.g.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tracer/build/supported_calltargets.g.json b/tracer/build/supported_calltargets.g.json index 01e09470efd5..4c60c1d358a1 100644 --- a/tracer/build/supported_calltargets.g.json +++ b/tracer/build/supported_calltargets.g.json @@ -16472,7 +16472,7 @@ "Item3": 0 }, "MaximumVersion": { - "Item1": 2, + "Item1": 1, "Item2": 65535, "Item3": 65535 }, @@ -16494,7 +16494,7 @@ "Item3": 0 }, "MaximumVersion": { - "Item1": 2, + "Item1": 1, "Item2": 65535, "Item3": 65535 }, diff --git a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp index a228a62c2c76..6bb732cf32cc 100644 --- a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp +++ b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp @@ -1100,8 +1100,8 @@ std::vector callTargets = {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,2,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Pipeline.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,1,4,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.LoggerConfiguration"),(WCHAR*)WStr("CreateLogger"),sig124,1,1,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation"),CallTargetKind::Default,1,15}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,0,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,0,0,0,2,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig002,5,4,0,0,6,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig003,6,6,0,0,10,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Microsoft.Data.SqlClient"),(WCHAR*)WStr("Microsoft.Data.SqlClient.SqlCommand"),(WCHAR*)WStr("ExecuteDbDataReader"),sig140,2,1,0,0,7,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteReaderWithBehaviorIntegration"),CallTargetKind::Default,1,15}, From 9bebc26712d588325534545ec1eca54538da7e27 Mon Sep 17 00:00:00 2001 From: Lewis Date: Tue, 24 Mar 2026 17:33:39 -0400 Subject: [PATCH 33/38] Add DD_SERVERLESS_COMPAT_PATH to telemetry normalization rules Co-Authored-By: Claude Opus 4.6 (1M context) --- tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json b/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json index aa138013be49..5fbae23a78c6 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json @@ -346,6 +346,7 @@ "DD_DOGSTATSD_ARGS": "agent_dogstatsd_executable_args", "DD_DIAGNOSTIC_SOURCE_ENABLED": "trace_diagnostic_source_enabled", "DD_SITE": "site", + "DD_SERVERLESS_COMPAT_PATH": "serverless_compat_path", "DD_TRACE_HTTP_CLIENT_EXCLUDED_URL_SUBSTRINGS": "trace_http_client_excluded_urls", "DD_HTTP_SERVER_ERROR_STATUSES": "trace_http_server_error_statuses", "DD_HTTP_CLIENT_ERROR_STATUSES": "trace_http_client_error_statuses", From a168e9d22409952d3f9cb4ac20d2e6ed1f11b253 Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 25 Mar 2026 14:33:06 -0400 Subject: [PATCH 34/38] Bump Datadog.Serverless.Compat dependency to 1.4.0 Version 1.4.0 adds the CalculateTracePipeName and CalculateDogStatsDPipeName methods that the tracer instruments for named pipe coordination. Co-Authored-By: Claude Opus 4.6 (1M context) --- tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj b/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj index eaba4935aed2..0192bdc5d1b7 100644 --- a/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj +++ b/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj @@ -30,7 +30,7 @@ - + From d8195fc5b854739a988b403a6c515fc0355202da Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 25 Mar 2026 16:37:30 -0400 Subject: [PATCH 35/38] Fix stale docs, strengthen test assertions, and rewrite integration tests - Update version range comments from 2.*.* to 1.*.* in both integrations - Update DD_SERVERLESS_COMPAT_PATH documentation for linux default path - Rewrite ServerlessCompatIntegrationTests: remove reflection-based tests for removed cache fields, add Theory-based tests for exception passthrough and fallback behavior with exact value assertions Co-Authored-By: Claude Opus 4.6 (1M context) --- ..._CalculateDogStatsDPipeName_Integration.cs | 2 +- ...ayer_CalculateTracePipeName_Integration.cs | 2 +- .../supported-configurations.yaml | 5 +- .../ConfigurationKeys.g.cs | 5 +- .../ServerlessCompatIntegrationTests.cs | 175 +----------------- 5 files changed, 18 insertions(+), 171 deletions(-) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs index ba91a336cb10..1a16ebbdbe18 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateDogStatsDPipeName_Integration.cs @@ -18,7 +18,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateDogStatsDPipeName method. /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, /// ensuring the tracer's runtime metrics and the compat layer use the same pipe name. - /// Version range 0.0.0–2.*.* matches all versions, including the 0.0.0 dev build. + /// Version range 0.0.0–1.*.* matches all 0.x and 1.x versions, including the 0.0.0 dev build. /// If the target method doesn't exist (e.g. older/newer compat assembly), the native profiler /// silently skips instrumentation — no exception is thrown. /// diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs index efb5baec71d0..403370392b31 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/CompatibilityLayer_CalculateTracePipeName_Integration.cs @@ -18,7 +18,7 @@ namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless /// Instrumentation for Datadog.Serverless.CompatibilityLayer.CalculateTracePipeName method. /// This instrumentation overrides the return value with the tracer's pre-generated pipe name, /// ensuring both the tracer and the compat layer use the same pipe name for communication. - /// Version range 0.0.0–2.*.* matches all versions, including the 0.0.0 dev build. + /// Version range 0.0.0–1.*.* matches all 0.x and 1.x versions, including the 0.0.0 dev build. /// If the target method doesn't exist (e.g. older/newer compat assembly), the native profiler /// silently skips instrumentation — no exception is thrown. /// diff --git a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml index 2babf8b77f3e..066a822f9c25 100644 --- a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml +++ b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml @@ -1474,8 +1474,9 @@ supportedConfigurations: default: null const_name: ServerlessCompatPath documentation: |- - Overrides the default path to the serverless compat layer binary. - Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + Overrides the default path to the serverless compatability layer binary. + Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + Default value in linux is /bin/linux-amd64/datadog-serverless-compat. DD_SYMBOL_DATABASE_BATCH_SIZE_BYTES: - implementation: A type: int diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 3528833e13d1..fa1ea6534304 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -243,8 +243,9 @@ internal static partial class ConfigurationKeys public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; /// - /// Overrides the default path to the serverless compat layer binary. - /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Overrides the default path to the serverless compatability layer binary. + /// Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Default value in linux is /bin/linux-amd64/datadog-serverless-compat. /// public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs index 6dbb0297c4d8..6592d261ee91 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/Serverless/ServerlessCompatIntegrationTests.cs @@ -7,7 +7,6 @@ #if !NETFRAMEWORK using System; -using System.Reflection; using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; using Datadog.Trace.ClrProfiler.CallTarget; using FluentAssertions; @@ -17,187 +16,33 @@ namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless; public class ServerlessCompatIntegrationTests { - [Fact] - public void TracePipeName_WithPreGeneratedName_ReturnsTracerValue() - { - // Arrange - ResetCachedPipeNames(); - const string preGeneratedName = "dd_trace_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - const string compatLayerName = "dd_trace_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; - SetExporterSettingsGeneratedNames(preGeneratedName, null); - - // Act - var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, - compatLayerName, - null!, - default); - - // Assert - result.GetReturnValue().Should().Be(preGeneratedName); - } - - [Fact] - public void TracePipeName_WithoutPreGeneratedName_GeneratesUniqueName() - { - // Arrange - ResetCachedPipeNames(); - const string compatLayerName = "dd_trace_00000000000000000000000000000000"; - SetExporterSettingsGeneratedNames(null, null); - - // Act - var result = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, - compatLayerName, - null!, - default); - - // Assert - var pipeName = result.GetReturnValue(); - pipeName.Should().NotBe(compatLayerName); - pipeName.Should().StartWith("dd_trace_"); - pipeName.Should().MatchRegex(@"^dd_trace_[a-f0-9]{32}$"); // base_guid format - } - - [Fact] - public void TracePipeName_CalledMultipleTimes_ReturnsCachedValue() - { - // Arrange - ResetCachedPipeNames(); - SetExporterSettingsGeneratedNames(null, null); - - // Act - var result1 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, - "compat_name_1", - null!, - default); - - var result2 = CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd( - null!, - "compat_name_2", - null!, - default); - - // Assert - result1.GetReturnValue().Should().Be(result2.GetReturnValue()); - } - - [Fact] - public void DogStatsDPipeName_WithPreGeneratedName_ReturnsTracerValue() - { - // Arrange - ResetCachedPipeNames(); - const string preGeneratedName = "dd_dogstatsd_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - const string compatLayerName = "dd_dogstatsd_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; - SetExporterSettingsGeneratedNames(null, preGeneratedName); - - // Act - var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, - compatLayerName, - null!, - default); - - // Assert - result.GetReturnValue().Should().Be(preGeneratedName); - } - - [Fact] - public void DogStatsDPipeName_WithoutPreGeneratedName_GeneratesUniqueName() - { - // Arrange - ResetCachedPipeNames(); - const string compatLayerName = "dd_dogstatsd_00000000000000000000000000000000"; - SetExporterSettingsGeneratedNames(null, null); - - // Act - var result = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, - compatLayerName, - null!, - default); - - // Assert - var pipeName = result.GetReturnValue(); - pipeName.Should().NotBe(compatLayerName); - pipeName.Should().StartWith("dd_dogstatsd_"); - pipeName.Should().MatchRegex(@"^dd_dogstatsd_[a-f0-9]{32}$"); // base_guid format - } - - [Fact] - public void DogStatsDPipeName_CalledMultipleTimes_ReturnsCachedValue() - { - // Arrange - ResetCachedPipeNames(); - SetExporterSettingsGeneratedNames(null, null); - - // Act - var result1 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, - "compat_name_1", - null!, - default); - - var result2 = CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd( - null!, - "compat_name_2", - null!, - default); - - // Assert - result1.GetReturnValue().Should().Be(result2.GetReturnValue()); - } - [Theory] [InlineData("trace")] [InlineData("dogstatsd")] public void OnMethodEnd_WithException_PassesThroughOriginalValue(string pipeType) { - // Arrange - ResetCachedPipeNames(); const string originalValue = "original_pipe_name"; var exception = new InvalidOperationException("Test exception"); - // Act CallTargetReturn result = pipeType == "trace" ? CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd(null!, originalValue, exception, default) : CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd(null!, originalValue, exception, default); - // Assert result.GetReturnValue().Should().Be(originalValue); } - // Clear cached values between tests using reflection. - // The integration classes cache their resolved pipe name in a static field; - // resetting these allows each test to start fresh. - private static void ResetCachedPipeNames() - { - var traceIntegrationType = typeof(CompatibilityLayer_CalculateTracePipeName_Integration); - var dogstatsdIntegrationType = typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration); - - var traceCacheField = traceIntegrationType.GetField("_cachedTracePipeName", BindingFlags.NonPublic | BindingFlags.Static); - var dogstatsdCacheField = dogstatsdIntegrationType.GetField("_cachedDogStatsDPipeName", BindingFlags.NonPublic | BindingFlags.Static); - - traceCacheField?.SetValue(null, null); - dogstatsdCacheField?.SetValue(null, null); - } - - // Pre-populate the integration cache fields directly to simulate - // having a pre-generated pipe name (e.g. from ExporterSettings). - // The ExporterSettings backing fields are static readonly and cannot be - // set via reflection, so we set the integration-level cache instead, - // which is what the integration checks first. - private static void SetExporterSettingsGeneratedNames(string? tracePipeName, string? metricsPipeName) + [Theory] + [InlineData("trace", "dd_trace_from_compat_layer")] + [InlineData("dogstatsd", "dd_dogstatsd_from_compat_layer")] + public void OnMethodEnd_WhenTracerHasNoPipeName_FallsBackToReturnValue(string pipeType, string compatLayerName) { - var traceIntegrationType = typeof(CompatibilityLayer_CalculateTracePipeName_Integration); - var dogstatsdIntegrationType = typeof(CompatibilityLayer_CalculateDogStatsDPipeName_Integration); - - var traceCacheField = traceIntegrationType.GetField("_cachedTracePipeName", BindingFlags.NonPublic | BindingFlags.Static); - var dogstatsdCacheField = dogstatsdIntegrationType.GetField("_cachedDogStatsDPipeName", BindingFlags.NonPublic | BindingFlags.Static); + // In a unit test environment, Tracer.Instance won't have pipe names configured, + // so the integration should fall back to the compat layer's own calculated name. + CallTargetReturn result = pipeType == "trace" + ? CompatibilityLayer_CalculateTracePipeName_Integration.OnMethodEnd(null!, compatLayerName, null!, default) + : CompatibilityLayer_CalculateDogStatsDPipeName_Integration.OnMethodEnd(null!, compatLayerName, null!, default); - traceCacheField?.SetValue(null, tracePipeName); - dogstatsdCacheField?.SetValue(null, metricsPipeName); + result.GetReturnValue().Should().Be(compatLayerName); } } #endif From 6561d3034d664a5c44fbfdc66b3c9cf08078993f Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 25 Mar 2026 16:47:59 -0400 Subject: [PATCH 36/38] Move ServerlessCompatPipeNameHelper to Datadog.Trace.Serverless, fix typo, use SkipOn in tests - Move ServerlessCompatPipeNameHelper from ClrProfiler.AutoInstrumentation.Serverless to Datadog.Trace.Serverless to avoid Configuration depending on instrumentation code - Fix "compatability" -> "compatibility" typo in YAML documentation - Replace silent early-return platform guards with SkipOn/SkippableFact so Windows-only tests show as skipped instead of silently passing Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Configuration/ExporterSettings.cs | 4 +- .../supported-configurations.yaml | 2 +- .../ConfigurationKeys.g.cs | 5 +- .../ConfigurationKeys.g.cs | 2 +- .../ConfigurationKeys.g.cs | 5 +- .../ConfigurationKeys.g.cs | 5 +- .../ServerlessCompatPipeNameHelper.cs | 2 +- .../ServerlessCompatPipeNameHelperTests.cs | 56 ++++++------------- 8 files changed, 31 insertions(+), 50 deletions(-) rename tracer/src/Datadog.Trace/{ClrProfiler/AutoInstrumentation => }/Serverless/ServerlessCompatPipeNameHelper.cs (98%) rename tracer/test/Datadog.Trace.Tests/{ClrProfiler/AutoInstrumentation => }/Serverless/ServerlessCompatPipeNameHelperTests.cs (81%) diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index dc307fd9733b..b2bc8456e9c0 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -99,7 +99,7 @@ internal ExporterSettings(Raw rawSettings, Func fileExists, IConfi if (Util.EnvironmentHelpers.IsAzureFunctions() && !Util.EnvironmentHelpers.IsUsingAzureAppServicesSiteExtension() - && ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport()) + && Serverless.ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport()) { tracesPipeName = GenerateUniquePipeName(rawSettings.TracesPipeName, "dd_trace", ConfigurationKeys.TracesPipeName); metricsPipeName = GenerateUniquePipeName(rawSettings.MetricsPipeName, "dd_dogstatsd", ConfigurationKeys.MetricsPipeName); @@ -350,7 +350,7 @@ private static string GetMetricsHostNameFromAgentUri(Uri agentUri) private string GenerateUniquePipeName(string? configuredBaseName, string defaultBaseName, string configKey) { var baseName = StringUtil.IsNullOrEmpty(configuredBaseName) ? defaultBaseName : configuredBaseName; - var name = ClrProfiler.AutoInstrumentation.Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); + var name = Serverless.ServerlessCompatPipeNameHelper.GenerateUniquePipeName(baseName, "ExporterSettings"); Log.Information("Azure Functions environment detected. Using pipe base name '{BaseName}', generated unique pipe name: {PipeName}", baseName, name); _telemetry.Record(configKey, name, recordValue: true, ConfigurationOrigins.Calculated); return name; diff --git a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml index 066a822f9c25..eb7ebbe157df 100644 --- a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml +++ b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml @@ -1474,7 +1474,7 @@ supportedConfigurations: default: null const_name: ServerlessCompatPath documentation: |- - Overrides the default path to the serverless compatability layer binary. + Overrides the default path to the serverless compatibility layer binary. Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. Default value in linux is /bin/linux-amd64/datadog-serverless-compat. DD_SYMBOL_DATABASE_BATCH_SIZE_BYTES: diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 3528833e13d1..04a795504c87 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -243,8 +243,9 @@ internal static partial class ConfigurationKeys public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; /// - /// Overrides the default path to the serverless compat layer binary. - /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Overrides the default path to the serverless compatibility layer binary. + /// Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Default value in linux is /bin/linux-amd64/datadog-serverless-compat. /// public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index fa1ea6534304..04a795504c87 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -243,7 +243,7 @@ internal static partial class ConfigurationKeys public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; /// - /// Overrides the default path to the serverless compatability layer binary. + /// Overrides the default path to the serverless compatibility layer binary. /// Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. /// Default value in linux is /bin/linux-amd64/datadog-serverless-compat. /// diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 3528833e13d1..04a795504c87 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -243,8 +243,9 @@ internal static partial class ConfigurationKeys public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; /// - /// Overrides the default path to the serverless compat layer binary. - /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Overrides the default path to the serverless compatibility layer binary. + /// Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Default value in linux is /bin/linux-amd64/datadog-serverless-compat. /// public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs index 3528833e13d1..04a795504c87 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs @@ -243,8 +243,9 @@ internal static partial class ConfigurationKeys public const string RuntimeMetricsEnabled = "DD_RUNTIME_METRICS_ENABLED"; /// - /// Overrides the default path to the serverless compat layer binary. - /// Default value is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Overrides the default path to the serverless compatibility layer binary. + /// Default value in windows is C:\home\site\wwwroot\datadog\bin\windows-amd64\datadog-serverless-compat.exe. + /// Default value in linux is /bin/linux-amd64/datadog-serverless-compat. /// public const string ServerlessCompatPath = "DD_SERVERLESS_COMPAT_PATH"; diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs b/tracer/src/Datadog.Trace/Serverless/ServerlessCompatPipeNameHelper.cs similarity index 98% rename from tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs rename to tracer/src/Datadog.Trace/Serverless/ServerlessCompatPipeNameHelper.cs index bbf709708641..922a52fa1a54 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelper.cs +++ b/tracer/src/Datadog.Trace/Serverless/ServerlessCompatPipeNameHelper.cs @@ -11,7 +11,7 @@ using System.Runtime.InteropServices; using Datadog.Trace.Logging; -namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless +namespace Datadog.Trace.Serverless { /// /// Helper class for generating unique pipe names for serverless compat layer coordination. diff --git a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs b/tracer/test/Datadog.Trace.Tests/Serverless/ServerlessCompatPipeNameHelperTests.cs similarity index 81% rename from tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs rename to tracer/test/Datadog.Trace.Tests/Serverless/ServerlessCompatPipeNameHelperTests.cs index c80fc0d9758f..49deff467bd5 100644 --- a/tracer/test/Datadog.Trace.Tests/ClrProfiler/AutoInstrumentation/Serverless/ServerlessCompatPipeNameHelperTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Serverless/ServerlessCompatPipeNameHelperTests.cs @@ -6,12 +6,12 @@ #nullable enable using System; -using System.Runtime.InteropServices; -using Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless; +using Datadog.Trace.Serverless; +using Datadog.Trace.TestHelpers; using FluentAssertions; using Xunit; -namespace Datadog.Trace.Tests.ClrProfiler.AutoInstrumentation.Serverless +namespace Datadog.Trace.Tests.Serverless { public class ServerlessCompatPipeNameHelperTests { @@ -71,27 +71,20 @@ public void IsCompatLayerAvailableWithPipeSupport_DoesNotThrow() act.Should().NotThrow(); } - [Fact] + [SkippableFact] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenNotOnWindows() { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - // This test only validates non-Windows behavior - return; - } + SkipOn.Platform(SkipOn.PlatformValue.Windows); var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport(); result.Should().BeFalse(); } - [Fact] + [SkippableFact] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatBinaryMissing() { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); // Binary missing, DLL present var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( @@ -101,13 +94,10 @@ public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatBinaryM result.Should().BeFalse(); } - [Fact] + [SkippableFact] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatDllMissing() { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); // Binary present, DLL missing var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( @@ -117,13 +107,10 @@ public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenCompatDllMiss result.Should().BeFalse(); } - [Fact] + [SkippableFact] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionIsNull() { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( fileExists: _ => true, @@ -132,16 +119,13 @@ public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionIsNull result.Should().BeFalse(); } - [Theory] + [SkippableTheory] [InlineData(1, 3, 0)] [InlineData(1, 0, 0)] [InlineData(0, 1, 0)] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionTooOld(int major, int minor, int build) { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( fileExists: _ => true, @@ -150,17 +134,14 @@ public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenVersionTooOld result.Should().BeFalse(); } - [Theory] + [SkippableTheory] [InlineData(0, 0, 0)] // dev build [InlineData(1, 4, 0)] // minimum supported [InlineData(1, 5, 0)] // above minimum [InlineData(2, 0, 0)] // major version bump public void IsCompatLayerAvailableWithPipeSupport_ReturnsTrue_WhenVersionSupported(int major, int minor, int build) { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( fileExists: _ => true, @@ -169,13 +150,10 @@ public void IsCompatLayerAvailableWithPipeSupport_ReturnsTrue_WhenVersionSupport result.Should().BeTrue(); } - [Fact] + [SkippableFact] public void IsCompatLayerAvailableWithPipeSupport_ReturnsFalse_WhenGetVersionThrows() { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } + SkipOn.AllExcept(SkipOn.PlatformValue.Windows); var result = ServerlessCompatPipeNameHelper.IsCompatLayerAvailableWithPipeSupport( fileExists: _ => true, From 648374772d9c74e53a9aeeca483a37caf72ded04 Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 25 Mar 2026 17:03:37 -0400 Subject: [PATCH 37/38] Revert Datadog.Serverless.Compat dependency to 1.2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compat 1.4.0 isn't published yet and has a dependency on these tracer changes. Keep the 1.2.0 dependency — the instrumentation silently skips when the target methods don't exist, and IsCompatLayerAvailableWithPipeSupport gates on >= 1.4.0 at runtime. The dependency will be bumped when compat 1.4.0 is published. Co-Authored-By: Claude Opus 4.6 (1M context) --- tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj b/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj index 0192bdc5d1b7..eaba4935aed2 100644 --- a/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj +++ b/tracer/src/Datadog.AzureFunctions/Datadog.AzureFunctions.csproj @@ -30,7 +30,7 @@ - + From 791e2e7f0aa40350327b3712830cf1fa3e9d88b1 Mon Sep 17 00:00:00 2001 From: Lewis Date: Thu, 26 Mar 2026 10:08:21 -0400 Subject: [PATCH 38/38] Fix generated_calltargets.g.cpp sig index (sig168 -> sig173) The sig index shifted due to new signatures added in master. Use the correct sig173 as determined by CI's Nuke build. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Generated/generated_calltargets.g.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp index 6bb732cf32cc..d94a643b4435 100644 --- a/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp +++ b/tracer/src/Datadog.Tracer.Native/Generated/generated_calltargets.g.cpp @@ -1100,8 +1100,8 @@ std::vector callTargets = {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,2,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.Core.Pipeline.Logger"),(WCHAR*)WStr("Dispatch"),sig345,2,1,4,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.LogsInjection.LoggerDispatchInstrumentation"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Serilog"),(WCHAR*)WStr("Serilog.LoggerConfiguration"),(WCHAR*)WStr("CreateLogger"),sig124,1,1,0,0,4,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Logging.Serilog.DirectSubmission.LoggerConfigurationInstrumentation"),CallTargetKind::Default,1,15}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig168,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, -{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig168,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateDogStatsDPipeName"),sig173,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateDogStatsDPipeName_Integration"),CallTargetKind::Default,1,14}, +{(WCHAR*)WStr("Datadog.Serverless.Compat"),(WCHAR*)WStr("Datadog.Serverless.CompatibilityLayer"),(WCHAR*)WStr("CalculateTracePipeName"),sig173,1,0,0,0,1,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Serverless.CompatibilityLayer_CalculateTracePipeName_Integration"),CallTargetKind::Default,1,14}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig002,5,4,0,0,6,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("ServiceStack.Redis"),(WCHAR*)WStr("ServiceStack.Redis.RedisNativeClient"),(WCHAR*)WStr("SendReceive"),sig003,6,6,0,0,10,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.Redis.ServiceStack.RedisNativeClientSendReceiveIntegration_6_2_0"),CallTargetKind::Default,1,15}, {(WCHAR*)WStr("Microsoft.Data.SqlClient"),(WCHAR*)WStr("Microsoft.Data.SqlClient.SqlCommand"),(WCHAR*)WStr("ExecuteDbDataReader"),sig140,2,1,0,0,7,65535,65535,assemblyName,(WCHAR*)WStr("Datadog.Trace.ClrProfiler.AutoInstrumentation.AdoNet.CommandExecuteReaderWithBehaviorIntegration"),CallTargetKind::Default,1,15},