diff --git a/tracer/build/_build/SmokeTests/SmokeTestScenario.cs b/tracer/build/_build/SmokeTests/SmokeTestScenario.cs index bc6c6a6863f5..f53f4fdd2d63 100644 --- a/tracer/build/_build/SmokeTests/SmokeTestScenario.cs +++ b/tracer/build/_build/SmokeTests/SmokeTestScenario.cs @@ -10,7 +10,7 @@ public abstract record SmokeTestScenario protected const string DefaultSnapshotIgnoredAttrs = "span_id" + ",trace_id" + ",parent_id" + ",duration" + ",start" + ",metrics.system.pid" + ",meta.runtime-id" + "," + "meta.network.client.ip" + ",meta.http.client_ip" + ",metrics.process_id" + ",meta._dd.p.dm" + "," - + "meta._dd.p.tid" + ",meta._dd.parent_id" + ",meta._dd.appsec.s.req.params" + "," + + "meta._dd.p.tid" + ",meta._dd.parent_id" + ",meta._dd.tags.process" + ",meta._dd.appsec.s.req.params" + "," + "meta._dd.appsec.s.res.body" + ",meta._dd.appsec.s.req.headers" + "," + "meta._dd.appsec.s.res.headers" + ",meta._dd.appsec.fp.http.endpoint" + "," + "meta._dd.appsec.fp.http.header" + ",meta._dd.appsec.fp.http.network"; diff --git a/tracer/build/smoke_test_snapshots/smoke_test_iis_snapshots.json b/tracer/build/smoke_test_snapshots/smoke_test_iis_snapshots.json index f148d7f90768..77ced1c50273 100644 --- a/tracer/build/smoke_test_snapshots/smoke_test_iis_snapshots.json +++ b/tracer/build/smoke_test_snapshots/smoke_test_iis_snapshots.json @@ -24,6 +24,7 @@ "runtime-id": "05dff020-c9cc-4b50-9395-e1fe88603312", "language": "dotnet", "_dd.runtime_family": "dotnet", + "_dd.tags.process": "entrypoint.basedir:VALUE,entrypoint.name:VALUE,entrypoint.workdir:VALUE,svc.auto:VALUE", "_dd.appsec.event_rules.version": "1.15.0", "_dd.appsec.fp.http.endpoint": "http-get-7460da9d--", "_dd.appsec.fp.http.header": "hdr-0000000000--3-98425651", @@ -62,6 +63,7 @@ "_dd.p.tid": "67a4e73b00000000", "runtime-id": "05dff020-c9cc-4b50-9395-e1fe88603312", "language": "dotnet", + "_dd.tags.process": "entrypoint.basedir:VALUE,entrypoint.name:VALUE,entrypoint.workdir:VALUE,svc.auto:VALUE", "_dd.base_service": "AspNetCoreSmokeTest", "_dd.svc_src": "http-client" }, diff --git a/tracer/build/smoke_test_snapshots/smoke_test_snapshots.json b/tracer/build/smoke_test_snapshots/smoke_test_snapshots.json index 31ac2d77f7cc..e774a232cd8b 100644 --- a/tracer/build/smoke_test_snapshots/smoke_test_snapshots.json +++ b/tracer/build/smoke_test_snapshots/smoke_test_snapshots.json @@ -18,6 +18,7 @@ "out.host": "localhost", "runtime-id": "11c61d09-16bb-477f-87ab-4f81d656c5ca", "span.kind": "client", + "_dd.tags.process": "entrypoint.basedir:VALUE,entrypoint.name:VALUE,entrypoint.workdir:VALUE,svc.auto:VALUE", "_dd.base_service": "AspNetCoreSmokeTest", "_dd.svc_src": "http-client" }, diff --git a/tracer/build/smoke_test_snapshots/smoke_test_snapshots_2_1.json b/tracer/build/smoke_test_snapshots/smoke_test_snapshots_2_1.json index 634eca483020..82d61311c8b6 100644 --- a/tracer/build/smoke_test_snapshots/smoke_test_snapshots_2_1.json +++ b/tracer/build/smoke_test_snapshots/smoke_test_snapshots_2_1.json @@ -18,6 +18,7 @@ "out.host": "localhost", "runtime-id": "b34b2bed-9444-4597-87f6-b8202b03b1b8", "span.kind": "client", + "_dd.tags.process": "entrypoint.basedir:VALUE,entrypoint.name:VALUE,entrypoint.workdir:VALUE,svc.auto:VALUE", "_dd.base_service": "AspNetCoreSmokeTest", "_dd.svc_src": "http-client" }, diff --git a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs index cb03b502c47f..83bc1645edf5 100644 --- a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs @@ -33,7 +33,7 @@ namespace Datadog.Trace.Configuration public partial record TracerSettings { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(); - private static readonly HashSet DefaultExperimentalFeatures = ["DD_TAGS", ConfigurationKeys.PropagateProcessTags]; + private static readonly HashSet DefaultExperimentalFeatures = ["DD_TAGS"]; private readonly Lazy _fallbackApplicationName; @@ -87,7 +87,7 @@ internal TracerSettings(IConfigurationSource? source, IConfigurationTelemetry te PropagateProcessTags = config .WithKeys(ConfigurationKeys.PropagateProcessTags) - .AsBool(ExperimentalFeaturesEnabled.Contains(ConfigurationKeys.PropagateProcessTags)); // read it as "defaults to false" + .AsBool(true); GCPFunctionSettings = new ImmutableGCPFunctionSettings(source, telemetry); IsRunningInGCPFunctions = GCPFunctionSettings.IsGCPFunction; diff --git a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml index aa637d4bacd7..ad4fc1270c09 100644 --- a/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml +++ b/tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml @@ -775,12 +775,12 @@ supportedConfigurations: const_name: UseUnsafeEncoder documentation: Use new unsafe encoder for the waf DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED: - - implementation: A + - implementation: B type: boolean - default: 'false' + default: 'true' const_name: PropagateProcessTags documentation: |- - Enables propagation of process-level tags across traces. Type: `boolean`. Default: `false` + Enables propagation of process-level tags across traces. Type: `boolean`. Default: `true` DD_GIT_BRANCH: - implementation: A type: string 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 5ac4ed1e7782..30b26bdcf2d9 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 @@ -151,7 +151,7 @@ internal static partial class ConfigurationKeys public const string Environment = "DD_ENV"; /// - /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `false` + /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `true` /// public const string PropagateProcessTags = "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"; 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 5ac4ed1e7782..30b26bdcf2d9 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 @@ -151,7 +151,7 @@ internal static partial class ConfigurationKeys public const string Environment = "DD_ENV"; /// - /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `false` + /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `true` /// public const string PropagateProcessTags = "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"; 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 5ac4ed1e7782..30b26bdcf2d9 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 @@ -151,7 +151,7 @@ internal static partial class ConfigurationKeys public const string Environment = "DD_ENV"; /// - /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `false` + /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `true` /// public const string PropagateProcessTags = "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"; 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 5ac4ed1e7782..30b26bdcf2d9 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 @@ -151,7 +151,7 @@ internal static partial class ConfigurationKeys public const string Environment = "DD_ENV"; /// - /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `false` + /// Enables propagation of process-level tags across traces. Type: `boolean`. Default: `true` /// public const string PropagateProcessTags = "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsKinesisTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsKinesisTests.cs index 804f450450ea..031f63733023 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsKinesisTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsKinesisTests.cs @@ -44,6 +44,7 @@ public static IEnumerable GetEnabledConfig() public async Task SubmitsDsmMetrics(string packageVersion, string metadataSchemaVersion) { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); SetEnvironmentVariable("DD_TRACE_SPAN_ATTRIBUTE_SCHEMA", metadataSchemaVersion); var isExternalSpan = metadataSchemaVersion == "v0"; var clientSpanServiceName = isExternalSpan ? $"{EnvironmentHelper.FullSampleName}-aws-kinesis" : EnvironmentHelper.FullSampleName; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSnsTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSnsTests.cs index 9ec1667d3a7d..30ad16682788 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSnsTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSnsTests.cs @@ -39,6 +39,7 @@ public static IEnumerable GetEnabledConfig() public async Task SubmitsDsmMetrics(string packageVersion) { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); using var telemetry = this.ConfigureTelemetry(); using var agent = EnvironmentHelper.GetMockAgent(); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSqsTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSqsTests.cs index ab074f8717d2..7f80ffb4daa8 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSqsTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/DataStreamsMonitoringAwsSqsTests.cs @@ -51,6 +51,7 @@ public static IEnumerable GetEnabledConfig() public async Task SubmitsDsmMetrics(string packageVersion, int batch, int sameThread, int inject) { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); // set scenario to run SetEnvironmentVariable("TEST_BATCH", batch.ToString()); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/MsTestV2Tests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/MsTestV2Tests.cs index 2a73d67eb252..6d17e019108f 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/MsTestV2Tests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/MsTestV2Tests.cs @@ -100,6 +100,9 @@ public async Task SubmitTraces(string packageVersion) targetSpan.Tags.Remove(Tags.GitCommitSha); targetSpan.Tags.Remove(Tags.GitRepositoryUrl); + // Remove process tags that get added to the first span of a payload + targetSpan.Tags.Remove(Tags.ProcessTags); + // Remove EFD tags targetSpan.Tags.Remove(TestTags.TestIsNew); targetSpan.Tags.Remove(TestTags.TestIsRetry); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/NUnitTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/NUnitTests.cs index c495d702a6c4..0b20005cd99c 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/NUnitTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/NUnitTests.cs @@ -94,6 +94,9 @@ public async Task SubmitTraces(string packageVersion) targetSpan.Tags.Remove(Tags.GitCommitSha); targetSpan.Tags.Remove(Tags.GitRepositoryUrl); + // Remove process tags that get added to the first span of a payload + targetSpan.Tags.Remove(Tags.ProcessTags); + // Remove EFD tags targetSpan.Tags.Remove(TestTags.TestIsNew); targetSpan.Tags.Remove(TestTags.TestIsRetry); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/XUnitTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/XUnitTests.cs index b132000c0800..39fdc470ec9d 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/XUnitTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/CI/XUnitTests.cs @@ -68,6 +68,9 @@ public virtual async Task SubmitTraces(string packageVersion) targetSpan.Tags.Remove(Tags.GitCommitSha); targetSpan.Tags.Remove(Tags.GitRepositoryUrl); + // Remove process tags that get added to the first span of a payload + targetSpan.Tags.Remove(Tags.ProcessTags); + // Remove EFD tags targetSpan.Tags.Remove(TestTags.TestIsNew); targetSpan.Tags.Remove(TestTags.TestIsRetry); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringKafkaTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringKafkaTests.cs index ba549d59cc53..ff26acd73d5d 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringKafkaTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringKafkaTests.cs @@ -78,6 +78,7 @@ public async Task SubmitsDataStreams(bool enableConsumerScopeCreation, bool enab var topicSuffix = $"{nameof(SubmitsDataStreams)}-{(enableConsumerScopeCreation ? "1" : "0")}-{(enableLegacyHeaders ? "1" : "0")}"; SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); SetEnvironmentVariable(ConfigurationKeys.KafkaCreateConsumerScopeEnabled, enableConsumerScopeCreation ? "1" : "0"); SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.LegacyHeadersEnabled, enableLegacyHeaders ? "1" : "0"); @@ -114,6 +115,7 @@ public async Task HandlesBatchProcessing() var topicSuffix = $"{nameof(HandlesBatchProcessing)}"; SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); // set variable to create short spans on receive instead of spans that last until the next consume SetEnvironmentVariable(ConfigurationKeys.KafkaCreateConsumerScopeEnabled, "0"); SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.LegacyHeadersEnabled, "1"); @@ -161,6 +163,7 @@ public async Task WhenNotSupported_DoesNotSubmitDataStreams() var topicSuffix = "WhenNotSupported"; SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); using var agent = EnvironmentHelper.GetMockAgent(); agent.Configuration = new MockTracerAgent.AgentConfiguration { Endpoints = Array.Empty() }; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringManualApiTest.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringManualApiTest.cs index 305228330a8c..7cd5565f8c70 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringManualApiTest.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringManualApiTest.cs @@ -28,6 +28,7 @@ public DataStreamsMonitoringManualApiTest(ITestOutputHelper output) public async Task ContextPropagation() { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); using var agent = EnvironmentHelper.GetMockAgent(); using var processResult = await RunSampleAndWaitForExit(agent); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringRabbitMQTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringRabbitMQTests.cs index d179e56b1549..c30d7d85c92e 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringRabbitMQTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/DataStreamsMonitoringRabbitMQTests.cs @@ -36,6 +36,7 @@ public DataStreamsMonitoringRabbitMQTests(ITestOutputHelper output) public async Task HandleProduceAndConsume(string packageVersion) { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.LegacyHeadersEnabled, "1"); using var assertionScope = new AssertionScope(); @@ -60,6 +61,7 @@ await Verifier.Verify(PayloadsToPoints(agent.DataStreams), settings) public async Task ValidateSpanTags(string packageVersion) { SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.Enabled, "1"); + SetEnvironmentVariable(ConfigurationKeys.PropagateProcessTags, "0"); SetEnvironmentVariable(ConfigurationKeys.DataStreamsMonitoring.LegacyHeadersEnabled, "1"); using var assertionScope = new AssertionScope(); diff --git a/tracer/test/Datadog.Trace.TestHelpers.SharedSource/VerifyHelper.cs b/tracer/test/Datadog.Trace.TestHelpers.SharedSource/VerifyHelper.cs index 081a7bded93e..4f77cf223343 100644 --- a/tracer/test/Datadog.Trace.TestHelpers.SharedSource/VerifyHelper.cs +++ b/tracer/test/Datadog.Trace.TestHelpers.SharedSource/VerifyHelper.cs @@ -206,10 +206,15 @@ public static VerifySettings AddSimpleScrubber(this VerifySettings settings, str // remove propagated tags because their positions in the snapshots are not stable // with our span ordering. correct position (first span in every trace chunk) is covered by other tests. ?.Where(kvp => !kvp.Key.StartsWith(TagPropagation.PropagatedTagPrefix, StringComparison.Ordinal)) - // We must ignore both `_dd.git.repository_url` and `_dd.git.commit.sha` because we are only setting it on the first span of a trace - // no matter what. That means we have unstable snapshot results. - // Also ignoring `_dd.parent_id` since we test specific headers combinations which check for the value, hence why not adding it to the snapshots - .Where(kvp => kvp.Key != Tags.GitRepositoryUrl && kvp.Key != Tags.GitCommitSha && kvp.Key != Tags.LastParentId) + .Where(kvp => + // We must ignore both `_dd.git.repository_url` and `_dd.git.commit.sha` because we are only setting it on the first span of a trace + // no matter what. That means we have unstable snapshot results. + kvp.Key != Tags.GitRepositoryUrl + && kvp.Key != Tags.GitCommitSha + // Also ignoring `_dd.parent_id` since we test specific headers combinations which check for the value, hence why not adding it to the snapshots + && kvp.Key != Tags.LastParentId + // same as git related tags above, process tags are only added to the first span of each payload, which makes snapshots unstable. + && kvp.Key != Tags.ProcessTags) .Select( kvp => kvp.Key switch { @@ -238,10 +243,15 @@ public static VerifySettings AddSimpleScrubber(this VerifySettings settings, str // remove propagated tags because their positions in the snapshots are not stable // with our span ordering. correct position (first span in every trace chunk) is covered by other tests. ?.Where(kvp => !kvp.Key.StartsWith(TagPropagation.PropagatedTagPrefix, StringComparison.Ordinal)) - // We must ignore both `_dd.git.repository_url` and `_dd.git.commit.sha` because we are only setting it on the first span of a trace - // no matter what. That means we have unstable snapshot results. - // Also ignoring `_dd.parent_id` since we test specific headers combinations which check for the value, hence why not adding it to the snapshots - .Where(kvp => kvp.Key != Tags.GitRepositoryUrl && kvp.Key != Tags.GitCommitSha && kvp.Key != Tags.LastParentId) + .Where(kvp => + // We must ignore both `_dd.git.repository_url` and `_dd.git.commit.sha` because we are only setting it on the first span of a trace + // no matter what. That means we have unstable snapshot results. + kvp.Key != Tags.GitRepositoryUrl + && kvp.Key != Tags.GitCommitSha + // Also ignoring `_dd.parent_id` since we test specific headers combinations which check for the value, hence why not adding it to the snapshots + && kvp.Key != Tags.LastParentId + // same as git related tags above, process tags are only added to the first span of each payload, which makes snapshots unstable. + && kvp.Key != Tags.ProcessTags) .Select( kvp => kvp.Key switch { diff --git a/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV0Rules.cs b/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV0Rules.cs index 60fdde916206..1d22e6acda54 100644 --- a/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV0Rules.cs +++ b/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV0Rules.cs @@ -18,6 +18,7 @@ public static Result IsAdoNetV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("db.name") .IsPresent("db.type") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "AdoNet") .Matches("span.kind", "client")); @@ -32,6 +33,7 @@ public static Result IsAerospikeV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("aerospike.setname") .IsOptional("aerospike.userkey") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aerospike") .Matches("span.kind", "client")); @@ -50,6 +52,7 @@ public static Result IsAspNetV0(this MockSpan span, ISet excludeTags = n .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -68,6 +71,7 @@ public static Result IsAspNetMvcV0(this MockSpan span, ISet excludeTags .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -95,6 +99,7 @@ public static Result IsAspNetWebApi2V0(this MockSpan span, ISet excludeT .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -114,6 +119,7 @@ public static Result IsAspNetCoreV0(this MockSpan span, ISet excludeTags .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "aspnet_core") .Matches("span.kind", "server")); @@ -129,6 +135,7 @@ public static Result IsAspNetCoreMvcV0(this MockSpan span) => Result.FromSpan(sp .IsOptional("aspnet_core.page") .IsPresent("aspnet_core.route") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "aspnet_core") .Matches("span.kind", "server")); @@ -152,6 +159,7 @@ public static Result IsAwsDynamoDbV0(this MockSpan span) => Result.FromSpan(span .IsPresent("_dd.peer.service.source") .Matches("component", "aws-sdk") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -176,6 +184,7 @@ public static Result IsAwsKinesisOutboundV0(this MockSpan span) => Result.FromSp .IsPresent("_dd.peer.service.source") .Matches("component", "aws-sdk") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -199,6 +208,7 @@ public static Result IsAwsS3RequestV0(this MockSpan span) => Result.FromSpan(spa .IsOptional("peer.service") .IsOptional("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .Matches("span.kind", "client")); @@ -222,6 +232,7 @@ public static Result IsAwsSqsInboundV0(this MockSpan span) => Result.FromSpan(sp .IsPresent("http.status_code") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .Matches("span.kind", "consumer")); @@ -247,6 +258,7 @@ public static Result IsAwsSqsOutboundV0(this MockSpan span) => Result.FromSpan(s .IsPresent("peer.service") .IsPresent("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .MatchesOneOf("span.kind", "producer", "client")); @@ -270,6 +282,7 @@ public static Result IsAwsSnsInboundV0(this MockSpan span) => Result.FromSpan(sp .IsPresent("http.status_code") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .Matches("span.kind", "consumer")); @@ -295,6 +308,7 @@ public static Result IsAwsSnsOutboundV0(this MockSpan span) => Result.FromSpan(s .IsPresent("peer.service") .IsPresent("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .MatchesOneOf("span.kind", "producer", "client")); @@ -316,6 +330,7 @@ public static Result IsAwsEventBridgeInboundV0(this MockSpan span) => Result.Fro .IsPresent("http.status_code") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .Matches("span.kind", "consumer")); @@ -339,6 +354,7 @@ public static Result IsAwsEventBridgeOutboundV0(this MockSpan span) => Result.Fr .IsPresent("peer.service") .IsPresent("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .MatchesOneOf("span.kind", "producer", "client")); @@ -362,6 +378,7 @@ public static Result IsAwsStepFunctionsRequestV0(this MockSpan span) => Result.F .IsOptional("peer.service") .IsOptional("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aws-sdk") .Matches("span.kind", "producer")); @@ -388,6 +405,7 @@ public static Result IsAzureServiceBusInboundV0(this MockSpan span, ISet .IfPresentMatches("component", "servicebus") .IfPresentMatches("kind", "consumer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "consumer")); @@ -408,6 +426,7 @@ public static Result IsAzureServiceBusInboundAPMV0(this MockSpan span, ISet .Matches("component", "AzureServiceBus") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -497,6 +519,7 @@ public static Result IsAzureServiceBusRequestV0(this MockSpan span, ISet .IfPresentMatches("component", "servicebus") .IfPresentMatches("kind", "client") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -518,6 +541,7 @@ public static Result IsAzureEventHubsOutboundV0(this MockSpan span, ISet .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -537,6 +561,7 @@ public static Result IsAzureEventHubsCreateV0(this MockSpan span, ISet e .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -557,6 +582,7 @@ public static Result IsAzureEventHubsInboundV0(this MockSpan span, ISet .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "consumer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "consumer")); @@ -574,6 +600,7 @@ public static Result IsCosmosDbV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("cosmosdb.connection.mode") .IsOptional("http.useragent") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "CosmosDb") .Matches("span.kind", "client")); @@ -590,6 +617,7 @@ public static Result IsCouchbaseV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("out.port") .IsOptional("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "Couchbase") .Matches("span.kind", "client")); @@ -604,6 +632,7 @@ public static Result IsElasticsearchNetV0(this MockSpan span) => Result.FromSpan .IsPresent("elasticsearch.url") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "elasticsearch-net") .Matches("span.kind", "client")); @@ -617,6 +646,7 @@ public static Result IsGraphQLV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("graphql.operation.type") .IsPresent("graphql.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "GraphQL") .Matches("span.kind", "server") @@ -637,6 +667,7 @@ public static Result IsGrpcClientV0(this MockSpan span, ISet excludeTags .IsPresent("out.host") .IsPresent("peer.hostname") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "Grpc") .Matches("span.kind", "client")); @@ -654,6 +685,7 @@ public static Result IsGrpcServerV0(this MockSpan span, ISet excludeTags .IsPresent("grpc.method.service") .IsPresent("grpc.status.code") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "Grpc") .Matches("span.kind", "server")); @@ -663,6 +695,7 @@ public static Result IsHangfireV0(this MockSpan span) => Result.FromSpan(span) .Matches(Type, "hangfire")) .Tags(s => s .Matches("_dd.base_service", "Samples.Hangfire") + .IsOptional("_dd.tags.process") .Matches("component", "hangfire") .Matches("span.kind", "internal") .IsPresent("job.createdat") @@ -678,6 +711,7 @@ public static Result IsHotChocolateV0(this MockSpan span) => Result.FromSpan(spa .IsPresent("graphql.source") .Matches("component", "HotChocolate") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "server") .IsOptional("events")); @@ -694,6 +728,7 @@ public static Result IsHttpMessageHandlerV0(this MockSpan span) => Result.FromSp .IsPresent("out.host") .IsPresent("component") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -714,6 +749,7 @@ public static Result IsKafkaInboundV0(this MockSpan span) => Result.FromSpan(spa .IsOptional("messaging.kafka.cluster_id") .IsPresent("messaging.destination.name") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "kafka") .Matches("span.kind", "consumer")); @@ -735,6 +771,7 @@ public static Result IsKafkaOutboundV0(this MockSpan span) => Result.FromSpan(sp .IsOptional("messaging.kafka.cluster_id") .IsPresent("messaging.destination.name") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "kafka") .Matches("span.kind", "producer")); @@ -750,6 +787,7 @@ public static Result IsMongoDbV0(this MockSpan span) => Result.FromSpan(span) .IsPresent("out.host") .IsPresent("out.port") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "MongoDb") .Matches("span.kind", "client")); @@ -765,6 +803,7 @@ public static Result IsMsmqV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("msmq.queue.transactional") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "msmq") .MatchesOneOf("span.kind", "client", "producer", "consumer")); @@ -781,6 +820,7 @@ public static Result IsMySqlV0(this MockSpan span) => Result.FromSpan(span) .Matches("component", "MySql") .Matches("span.kind", "client") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .IsOptional("_dd.dbm_trace_injected")); @@ -792,6 +832,7 @@ public static Result IsNpgsqlV0(this MockSpan span) => Result.FromSpan(span) .IsPresent("db.name") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("db.type", "postgres") .Matches("component", "Npgsql") @@ -808,6 +849,7 @@ public static Result IsOpenTelemetryV0(this MockSpan span, ISet resource .IsOptional("otel.library.version") .IsPresent("otel.trace_id") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("otel.status_code", "STATUS_CODE_UNSET", "STATUS_CODE_OK", "STATUS_CODE_ERROR") .IsOptional("otel.status_description") @@ -821,6 +863,7 @@ public static Result IsOracleV0(this MockSpan span) => Result.FromSpan(span) .IsPresent("db.name") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("db.type", "oracle") .Matches("component", "Oracle") @@ -836,6 +879,7 @@ public static Result IsProcessV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("cmd.shell") .IsOptional("cmd.truncated") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "process") .Matches("span.kind", "internal")); @@ -847,7 +891,8 @@ public static Result IsProtobufV0(this MockSpan span) => Result.FromSpan(span) .IsPresent(Tags.SchemaOperation) .IsPresent(Tags.SchemaId) .IsPresent(Tags.SchemaDefinition) - .IsPresent(Tags.SchemaWeight)); + .IsPresent(Tags.SchemaWeight) + .IsOptional("_dd.tags.process")); public static Result IsRabbitMQV0(this MockSpan span) => Result.FromSpan(span) .Properties(s => s @@ -862,6 +907,7 @@ public static Result IsRabbitMQV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("amqp.queue") .IsOptional("message.size") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "RabbitMQ") .IsPresent("span.kind")); @@ -874,6 +920,7 @@ public static Result IsRemotingClientV0(this MockSpan span) => Result.FromSpan(s .Matches("rpc.system", "dotnet_remoting") .Matches("component", "Remoting") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -885,6 +932,7 @@ public static Result IsRemotingServerV0(this MockSpan span) => Result.FromSpan(s .Matches("rpc.system", "dotnet_remoting") .Matches("component", "Remoting") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("span.kind", "server")); public static Result IsServiceRemotingClientV0(this MockSpan span) => Result.FromSpan(span) @@ -905,6 +953,7 @@ public static Result IsServiceRemotingClientV0(this MockSpan span) => Result.Fro .IsOptional("service-fabric.service-remoting.interface-id") .IsOptional("service-fabric.service-remoting.invocation-id") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -926,6 +975,7 @@ public static Result IsServiceRemotingServerV0(this MockSpan span) => Result.Fro .IsOptional("service-fabric.service-remoting.interface-id") .IsOptional("service-fabric.service-remoting.invocation-id") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("span.kind", "server")); public static Result IsServiceStackRedisV0(this MockSpan span) => Result.FromSpan(span) @@ -939,6 +989,7 @@ public static Result IsServiceStackRedisV0(this MockSpan span) => Result.FromSpa .IsPresent("out.host") .IsPresent("out.port") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "ServiceStackRedis") .Matches("span.kind", "client")); @@ -954,6 +1005,7 @@ public static Result IsStackExchangeRedisV0(this MockSpan span) => Result.FromSp .IsPresent("out.host") .IsPresent("out.port") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "StackExchangeRedis") .Matches("span.kind", "client")); @@ -966,6 +1018,7 @@ public static Result IsSqliteV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("db.name") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("db.type", "sqlite") .Matches("component", "Sqlite") @@ -979,6 +1032,7 @@ public static Result IsSqlClientV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("db.name") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .IsOptional("_dd.dbm_trace_injected") .IsOptional("dd.instrumentation.time_ms") @@ -995,6 +1049,7 @@ public static Result IsWcfV0(this MockSpan span, ISet excludeTags = null .IsOptional("http.request.headers.host") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .Matches("component", "Wcf") .Matches("span.kind", "server")); @@ -1009,6 +1064,7 @@ public static Result IsWebRequestV0(this MockSpan span) => Result.FromSpan(span) .IsPresent("http.url") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("component", "HttpMessageHandler", "WebRequest") .Matches("span.kind", "client")); @@ -1029,6 +1085,7 @@ public static Result IsQuartzV0(this MockSpan span) => Result.FromSpan(span) .IsOptional("scheduler.name") .IsOptional("span.kind") .IsPresent("trigger.group") - .IsPresent("trigger.name")); + .IsPresent("trigger.name") + .IsOptional("_dd.tags.process")); } } diff --git a/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV1Rules.cs b/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV1Rules.cs index b8733f068193..bbd118ae17fd 100644 --- a/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV1Rules.cs +++ b/tracer/test/Datadog.Trace.TestHelpers/SpanMetadataV1Rules.cs @@ -20,6 +20,7 @@ public static Result IsAdoNetV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "AdoNet") @@ -37,6 +38,7 @@ public static Result IsAerospikeV1(this MockSpan span) => Result.FromSpan(span) .IsOptional("peer.service") .IsOptional("_dd.peer.service.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aerospike") .Matches("span.kind", "client")); @@ -55,6 +57,7 @@ public static Result IsAspNetV1(this MockSpan span, ISet excludeTags = n .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -74,6 +77,7 @@ public static Result IsAspNetMvcV1(this MockSpan span, ISet excludeTags .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -102,6 +106,7 @@ public static Result IsAspNetWebApi2V1(this MockSpan span, ISet excludeT .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aspnet") .Matches("span.kind", "server")); @@ -122,6 +127,7 @@ public static Result IsAspNetCoreV1(this MockSpan span, ISet excludeTags .IsPresent("http.useragent") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aspnet_core") .Matches("span.kind", "server")); @@ -138,6 +144,7 @@ public static Result IsAspNetCoreMvcV1(this MockSpan span) => Result.FromSpan(sp .IsOptional("aspnet_core.page") .IsPresent("aspnet_core.route") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "aspnet_core") .Matches("span.kind", "server")); @@ -164,6 +171,7 @@ public static Result IsAzureServiceBusInboundV1(this MockSpan span, ISet .IfPresentMatches("component", "servicebus") .IfPresentMatches("kind", "consumer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "consumer")); @@ -184,6 +192,7 @@ public static Result IsAzureServiceBusInboundAPMV1(this MockSpan span, ISet .Matches("component", "AzureServiceBus") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -285,6 +297,7 @@ public static Result IsAzureServiceBusRequestV1(this MockSpan span, ISet .IfPresentMatches("component", "servicebus") .IfPresentMatches("kind", "client") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "client")); @@ -309,6 +322,7 @@ public static Result IsAzureEventHubsOutboundV1(this MockSpan span, ISet .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -331,6 +345,7 @@ public static Result IsAzureEventHubsCreateV1(this MockSpan span, ISet e .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "producer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -351,6 +366,7 @@ public static Result IsAzureEventHubsInboundV1(this MockSpan span, ISet .Matches("component", "AzureEventHubs") .IfPresentMatches("kind", "consumer") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "consumer")); @@ -371,6 +387,7 @@ public static Result IsCosmosDbV1(this MockSpan span) => Result.FromSpan(span) .IsOptional("cosmosdb.connection.mode") .IsOptional("http.useragent") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "CosmosDb") @@ -390,6 +407,7 @@ public static Result IsCouchbaseV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.couchbase.seed.nodes", "out.host", "peer.service") .Matches("component", "Couchbase") @@ -407,6 +425,7 @@ public static Result IsElasticsearchNetV1(this MockSpan span) => Result.FromSpan .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "elasticsearch-net") @@ -421,6 +440,7 @@ public static Result IsGraphQLV1(this MockSpan span) => Result.FromSpan(span) .IsOptional("graphql.operation.type") .IsPresent("graphql.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "GraphQL") .Matches("span.kind", "server") @@ -443,6 +463,7 @@ public static Result IsGrpcClientV1(this MockSpan span, ISet excludeTags .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "rpc.service", "out.host", "peer.service") .Matches("component", "Grpc") @@ -461,6 +482,7 @@ public static Result IsGrpcServerV1(this MockSpan span, ISet excludeTags .IsPresent("grpc.method.service") .IsPresent("grpc.status.code") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "Grpc") .Matches("span.kind", "server")); @@ -471,6 +493,7 @@ public static Result IsHangfireV1(this MockSpan span) => Result.FromSpan(span) .Matches(Type, "hangfire")) .Tags(s => s .Matches("_dd.base_service", "Samples.Hangfire") + .IsOptional("_dd.tags.process") .Matches("component", "hangfire") .Matches("span.kind", "internal") .IsPresent("job.createdat") @@ -485,6 +508,7 @@ public static Result IsHotChocolateV1(this MockSpan span) => Result.FromSpan(spa .IsOptional("graphql.operation.type") .IsPresent("graphql.source") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "HotChocolate") .Matches("span.kind", "server")); @@ -502,6 +526,7 @@ public static Result IsHttpMessageHandlerV1(this MockSpan span) => Result.FromSp .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .IsPresent("component") @@ -524,6 +549,7 @@ public static Result IsKafkaInboundV1(this MockSpan span) => Result.FromSpan(spa .IsOptional("messaging.kafka.cluster_id") .IsPresent("messaging.destination.name") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "kafka") .Matches("span.kind", "consumer")); @@ -547,6 +573,7 @@ public static Result IsKafkaOutboundV1(this MockSpan span) => Result.FromSpan(sp .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "messaging.kafka.bootstrap.servers", "peer.service") .Matches("component", "kafka") @@ -565,6 +592,7 @@ public static Result IsMongoDbV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "MongoDb") @@ -582,6 +610,7 @@ public static Result IsMsmqInboundV1(this MockSpan span) => Result.FromSpan(span .IsOptional("msmq.queue.transactional") .IsPresent("out.host") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "msmq") .Matches("span.kind", "consumer")); @@ -602,6 +631,7 @@ public static Result IsMsmqOutboundV1(this MockSpan span) => Result.FromSpan(spa .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "msmq") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "producer")); @@ -619,6 +649,7 @@ public static Result IsMsmqClientV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "msmq") @@ -636,6 +667,7 @@ public static Result IsMySqlV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "MySql") @@ -653,6 +685,7 @@ public static Result IsNpgsqlV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "Npgsql") @@ -669,6 +702,7 @@ public static Result IsOpenTelemetryV1(this MockSpan span, ISet resource .IsOptional("otel.library.version") .IsPresent("otel.trace_id") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("otel.status_code", "STATUS_CODE_UNSET", "STATUS_CODE_OK", "STATUS_CODE_ERROR") .IsOptional("otel.status_description") @@ -685,6 +719,7 @@ public static Result IsOracleV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "Oracle") @@ -700,6 +735,7 @@ public static Result IsProcessV1(this MockSpan span) => Result.FromSpan(span) .IsOptional("cmd.shell") .IsOptional("cmd.truncated") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "process") .Matches("span.kind", "internal")); @@ -711,7 +747,8 @@ public static Result IsProtobufV1(this MockSpan span) => Result.FromSpan(span) .IsPresent(Tags.SchemaOperation) .IsPresent(Tags.SchemaId) .IsPresent(Tags.SchemaDefinition) - .IsPresent(Tags.SchemaWeight)); + .IsPresent(Tags.SchemaWeight) + .IsOptional("_dd.tags.process")); public static Result IsRabbitMQAdminV1(this MockSpan span) => Result.FromSpan(span) .WithMarkdownSection("Rabbit - Admin") @@ -729,6 +766,7 @@ public static Result IsRabbitMQAdminV1(this MockSpan span) => Result.FromSpan(sp .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "RabbitMQ") @@ -747,6 +785,7 @@ public static Result IsRabbitMQInboundV1(this MockSpan span) => Result.FromSpan( .IsOptional("amqp.queue") .IsOptional("message.size") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "RabbitMQ") .Matches("span.kind", "consumer")); @@ -767,6 +806,7 @@ public static Result IsRabbitMQOutboundV1(this MockSpan span) => Result.FromSpan .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "RabbitMQ") @@ -783,6 +823,7 @@ public static Result IsRemotingClientV1(this MockSpan span) => Result.FromSpan(s .Matches("component", "Remoting") .IfPresentMatchesOneOf("_dd.peer.service.source", "peer.service", "rpc.service") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("span.kind", "client", "server")); @@ -794,6 +835,7 @@ public static Result IsRemotingServerV1(this MockSpan span) => Result.FromSpan(s .Matches("rpc.system", "dotnet_remoting") .Matches("component", "Remoting") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("span.kind", "client", "server")); @@ -817,6 +859,7 @@ public static Result IsServiceRemotingClientV1(this MockSpan span) => Result.Fro .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "service-fabric.service-remoting.service", "service-fabric.service-remoting.uri", "peer.service") .Matches("span.kind", "client")); @@ -839,6 +882,7 @@ public static Result IsServiceRemotingServerV1(this MockSpan span) => Result.Fro .IsOptional("service-fabric.service-remoting.interface-id") .IsOptional("service-fabric.service-remoting.invocation-id") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("span.kind", "server")); @@ -855,6 +899,7 @@ public static Result IsServiceStackRedisV1(this MockSpan span) => Result.FromSpa .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "ServiceStackRedis") @@ -873,6 +918,7 @@ public static Result IsStackExchangeRedisV1(this MockSpan span) => Result.FromSp .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .Matches("component", "StackExchangeRedis") @@ -889,6 +935,7 @@ public static Result IsSqliteV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .Matches("component", "Sqlite") @@ -905,6 +952,7 @@ public static Result IsSqlClientV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "db.name", "out.host", "peer.service") .IsOptional("_dd.dbm_trace_injected") @@ -921,6 +969,7 @@ public static Result IsWcfV1(this MockSpan span, ISet excludeTags = null .IsOptional("http.request.headers.host") .IsPresent("http.url") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .Matches("component", "Wcf") .Matches("span.kind", "server")); @@ -938,6 +987,7 @@ public static Result IsWebRequestV1(this MockSpan span) => Result.FromSpan(span) .IsPresent("peer.service") .IsOptional("peer.service.remapped_from") .IsOptional("_dd.base_service") + .IsOptional("_dd.tags.process") .IsOptional("_dd.svc_src") .MatchesOneOf("_dd.peer.service.source", "out.host", "peer.service") .MatchesOneOf("component", "HttpMessageHandler", "WebRequest") @@ -959,6 +1009,7 @@ public static Result IsQuartzV1(this MockSpan span) => Result.FromSpan(span) .IsOptional("scheduler.name") .IsOptional("span.kind") .IsPresent("trigger.group") - .IsPresent("trigger.name")); + .IsPresent("trigger.name") + .IsOptional("_dd.tags.process")); } } diff --git a/tracer/test/Datadog.Trace.Tests/Agent/AgentWriterTests.cs b/tracer/test/Datadog.Trace.Tests/Agent/AgentWriterTests.cs index 82f5a183945d..b8a388db6db9 100644 --- a/tracer/test/Datadog.Trace.Tests/Agent/AgentWriterTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Agent/AgentWriterTests.cs @@ -69,6 +69,18 @@ public async Task SpanSampling_CanComputeStats_ShouldNotSend_WhenSpanSamplingDoe public async Task SpanSampling_ShouldSend_SingleMatchedSpan_WhenStatsDrops() { var api = new Mock(); + ArraySegment actualData = default; + var actualDroppedP0Traces = 0L; + var actualDroppedP0Spans = 0L; + api.Setup(x => x.SendTracesAsync(It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((ArraySegment traces, int _, bool _, long numberOfDroppedP0Traces, long numberOfDroppedP0Spans, bool _) => + { + actualData = traces; + actualDroppedP0Traces = numberOfDroppedP0Traces; + actualDroppedP0Spans = numberOfDroppedP0Spans; + }) + .ReturnsAsync(true); + var statsAggregator = new StubStatsAggregator(shouldKeepTrace: false, x => x); var settings = SpanSamplingRule("*", "*"); var agent = new AgentWriter(api.Object, statsAggregator, statsd: TestStatsdManager.NoOp, automaticFlush: false); @@ -81,14 +93,16 @@ public async Task SpanSampling_ShouldSend_SingleMatchedSpan_WhenStatsDrops() traceContext.SetSamplingPriority(priority: SamplingPriorityValues.UserReject, mechanism: SamplingMechanism.Manual, rate: null, limiterRate: null); span.Finish(); var traceChunk = new SpanCollection([span]); - var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(new TraceChunkModel(traceChunk, SamplingPriorityValues.UserKeep), SpanFormatterResolver.Instance); + var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(new TraceChunkModel(traceChunk, SamplingPriorityValues.UserKeep, isFirstChunkInPayload: true), SpanFormatterResolver.Instance); await agent.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API var expectedDroppedP0Traces = 1; var expectedDroppedP0Spans = 0; - - api.Verify(x => x.SendTracesAsync(It.Is>(y => Equals(y, expectedData1)), It.Is(i => i == 1), It.IsAny(), It.Is(i => i == expectedDroppedP0Traces), It.Is(i => i == expectedDroppedP0Spans), It.IsAny()), Times.Once); + api.Verify(x => x.SendTracesAsync(It.IsAny>(), 1, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + AssertPayloadEqual(actualData, expectedData1); + actualDroppedP0Traces.Should().Be(expectedDroppedP0Traces); + actualDroppedP0Spans.Should().Be(expectedDroppedP0Spans); await _agentWriter.FlushAndCloseAsync(); } @@ -97,6 +111,18 @@ public async Task SpanSampling_ShouldSend_SingleMatchedSpan_WhenStatsDrops() public async Task SpanSampling_ShouldSend_MultipleMatchedSpans_WhenStatsDrops() { var api = new Mock(); + ArraySegment actualData = default; + var actualDroppedP0Traces = 0L; + var actualDroppedP0Spans = 0L; + api.Setup(x => x.SendTracesAsync(It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((ArraySegment traces, int _, bool _, long numberOfDroppedP0Traces, long numberOfDroppedP0Spans, bool _) => + { + actualData = traces; + actualDroppedP0Traces = numberOfDroppedP0Traces; + actualDroppedP0Spans = numberOfDroppedP0Spans; + }) + .ReturnsAsync(true); + var statsAggregator = new StubStatsAggregator(shouldKeepTrace: false, x => x); var settings = SpanSamplingRule("*", "*"); var agent = new AgentWriter(api.Object, statsAggregator, statsd: TestStatsdManager.NoOp, automaticFlush: false); @@ -115,13 +141,16 @@ public async Task SpanSampling_ShouldSend_MultipleMatchedSpans_WhenStatsDrops() var expectedChunk = new SpanCollection([rootSpan, keptChildSpan]); // var size = ComputeSize(expectedChunk); - var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(new TraceChunkModel(expectedChunk, SamplingPriorityValues.UserKeep), SpanFormatterResolver.Instance); + var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(new TraceChunkModel(expectedChunk, SamplingPriorityValues.UserKeep, isFirstChunkInPayload: true), SpanFormatterResolver.Instance); await agent.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API var expectedDroppedP0Traces = 1; var expectedDroppedP0Spans = 0; - api.Verify(x => x.SendTracesAsync(It.Is>(y => Equals(y, expectedData1)), It.Is(i => i == 1), It.IsAny(), It.Is(i => i == expectedDroppedP0Traces), It.Is(i => i == expectedDroppedP0Spans), It.IsAny()), Times.Once); + api.Verify(x => x.SendTracesAsync(It.IsAny>(), 1, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + AssertPayloadEqual(actualData, expectedData1); + actualDroppedP0Traces.Should().Be(expectedDroppedP0Traces); + actualDroppedP0Spans.Should().Be(expectedDroppedP0Spans); await _agentWriter.FlushAndCloseAsync(); } @@ -182,6 +211,14 @@ public void PushStats() [Fact] public async Task WriteTrace_2Traces_SendToApi() { + ArraySegment actualPayload = default; + _api.Setup(x => x.SendTracesAsync(It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((ArraySegment traces, int _, bool _, long _, long _, bool _) => + { + actualPayload = traces; + }) + .ReturnsAsync(true); + var spans = CreateTraceChunk(1); var traceChunk = new TraceChunkModel(spans); var expectedData1 = Vendors.MessagePack.MessagePackSerializer.Serialize(traceChunk, SpanFormatterResolver.Instance); @@ -189,9 +226,11 @@ public async Task WriteTrace_2Traces_SendToApi() _agentWriter.WriteTrace(spans); await _agentWriter.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API - _api.Verify(x => x.SendTracesAsync(It.Is>(y => Equals(y, expectedData1)), It.Is(i => i == 1), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _api.Verify(x => x.SendTracesAsync(It.IsAny>(), 1, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + AssertPayloadEqual(actualPayload, expectedData1); _api.Invocations.Clear(); + actualPayload = default; spans = CreateTraceChunk(1, 2); traceChunk = new TraceChunkModel(spans); @@ -200,7 +239,8 @@ public async Task WriteTrace_2Traces_SendToApi() _agentWriter.WriteTrace(spans); await _agentWriter.FlushTracesAsync(); // Force a flush to make sure the trace is written to the API - _api.Verify(x => x.SendTracesAsync(It.Is>(y => Equals(y, expectedData2)), It.Is(i => i == 1), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _api.Verify(x => x.SendTracesAsync(It.IsAny>(), 1, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + AssertPayloadEqual(actualPayload, expectedData2); await _agentWriter.FlushAndCloseAsync(); } @@ -500,10 +540,18 @@ private static bool WaitForDequeue(AgentWriter agent, bool wakeUpThread = true, return mutex.Wait(delay); } - private static bool Equals(ArraySegment data, byte[] expectedData) + private static void AssertPayloadEqual(ArraySegment data, byte[] expectedData) { - var equals = data.Array!.Skip(data.Offset).Take(data.Count).Skip(SpanBufferMessagePackSerializer.HeaderSizeConst).SequenceEqual(expectedData); - return equals; + data.Array.Should().NotBeNull(); + data.Count.Should().BeGreaterOrEqualTo(SpanBufferMessagePackSerializer.HeaderSizeConst); + + var actualPayload = data.Array! + .Skip(data.Offset) + .Take(data.Count) + .Skip(SpanBufferMessagePackSerializer.HeaderSizeConst) + .ToArray(); + + actualPayload.Should().Equal(expectedData); } private static int ComputeSize(SpanCollection spans) diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/MutableSettingsTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/MutableSettingsTests.cs index 381328c102a0..c312b8652d37 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/MutableSettingsTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/MutableSettingsTests.cs @@ -703,7 +703,7 @@ public void LogsInjectionEnabled(string value, bool expected) [InlineData(false)] public void ProcessTagsEnabledIfPropagationEnabled(bool propagateTags) { - var source = propagateTags ? CreateConfigurationSource((ConfigurationKeys.PropagateProcessTags, "true")) : CreateConfigurationSource(); + var source = CreateConfigurationSource((ConfigurationKeys.PropagateProcessTags, propagateTags.ToString())); var settings = new TracerSettings(source); var mutable = GetMutableSettings(source, settings); diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs index 698971005190..e6f998c6f77b 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/TracerSettingsTests.cs @@ -1154,7 +1154,7 @@ public void OtlpLogsTimeoutMsFallback(string logsTimeout, string generalTimeout, } [Theory] - [MemberData(nameof(BooleanTestCases), false)] + [MemberData(nameof(BooleanTestCases), true)] public void ProcessTagsEnabled(string value, bool expected) { var source = CreateConfigurationSource((ConfigurationKeys.PropagateProcessTags, value)); @@ -1162,19 +1162,5 @@ public void ProcessTagsEnabled(string value, bool expected) settings.PropagateProcessTags.Should().Be(expected); } - - [Theory] - [InlineData(null, false)] - [InlineData("", false)] - [InlineData("none", false)] - [InlineData("all", true)] - [InlineData(ConfigurationKeys.PropagateProcessTags, true)] - public void ProcessTagsEnabledIfExperimentalEnabled(string value, bool expected) - { - var source = CreateConfigurationSource((ConfigurationKeys.ExperimentalFeaturesEnabled, value)); - var settings = new TracerSettings(source); - - settings.PropagateProcessTags.Should().Be(expected); - } } } diff --git a/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsManagerTests.cs b/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsManagerTests.cs index d7e58b90d9bb..1ccdbfc06b06 100644 --- a/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsManagerTests.cs +++ b/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsManagerTests.cs @@ -346,6 +346,10 @@ private static DataStreamsManager GetDataStreamManager(bool enabled, out DataStr { ConfigurationKeys.Environment, "foo" }, { ConfigurationKeys.ServiceName, "bar" }, { ConfigurationKeys.DataStreamsMonitoring.Enabled, enabled.ToString() }, + // TODO: inject a deterministic value for process tags instead, to make test closer to reality + // there are already tests about process tags, so this one is not required to "prove" it works + // but it'd be cleaner not to have exclusions like this + { ConfigurationKeys.PropagateProcessTags, "false" } }); return new DataStreamsManager(settings, writer, Mock.Of()); } diff --git a/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsMessagePackFormatterTests.cs b/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsMessagePackFormatterTests.cs index 242d91ee6e1e..927e70779b60 100644 --- a/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsMessagePackFormatterTests.cs +++ b/tracer/test/Datadog.Trace.Tests/DataStreamsMonitoring/DataStreamsMessagePackFormatterTests.cs @@ -29,7 +29,15 @@ public void CanRoundTripMessagePackFormat() var service = "service=name"; var bucketDuration = 10_000_000_000; var edgeTags = new[] { "edge-1" }; - var settings = TracerSettings.Create(new() { { ConfigurationKeys.Environment, "my-env" }, { ConfigurationKeys.ServiceName, service } }); + var settings = TracerSettings.Create(new Dictionary + { + { ConfigurationKeys.Environment, "my-env" }, + { ConfigurationKeys.ServiceName, service }, + // TODO: inject a deterministic value for process tags instead, to make test closer to reality + // there are already tests about process tags, so this one is not required to "prove" it works + // but it'd be cleaner not to have exclusions like this + { ConfigurationKeys.PropagateProcessTags, "false" } + }); var formatter = new DataStreamsMessagePackFormatter(settings, new ProfilerSettings(ProfilerState.Disabled)); var timeNs = DateTimeOffset.UtcNow.ToUnixTimeNanoseconds(); diff --git a/tracer/test/Datadog.Trace.Tests/Tagging/TagsListTests.cs b/tracer/test/Datadog.Trace.Tests/Tagging/TagsListTests.cs index 9bae953ec6d0..614693ddcd6f 100644 --- a/tracer/test/Datadog.Trace.Tests/Tagging/TagsListTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Tagging/TagsListTests.cs @@ -173,7 +173,8 @@ public async Task Serialization_RootSpan() deserializedSpan.Tags.Should().Contain(Tags.RuntimeId, Tracer.RuntimeId); deserializedSpan.Tags.Should().Contain(Tags.Propagated.DecisionMaker, SamplingMechanism.Default); deserializedSpan.Tags.Should().Contain(Tags.Propagated.TraceIdUpper, hexStringTraceId); - deserializedSpan.Tags.Should().HaveCount(customTagCount + 5); + deserializedSpan.Tags.Should().ContainKey(Tags.ProcessTags); + deserializedSpan.Tags.Should().HaveCount(customTagCount + 6); deserializedSpan.Metrics.Should().Contain(Metrics.SamplingPriority, 1); deserializedSpan.Metrics.Should().Contain(Metrics.SamplingLimitDecision, 0.75); @@ -217,7 +218,8 @@ public async Task Serialization_ServiceEntrySpan() deserializedSpan.Tags.Should().Contain(Tags.Propagated.TraceIdUpper, hexStringTraceId); deserializedSpan.Tags.Should().ContainKey(Tags.BaseService); deserializedSpan.Tags[Tags.BaseService].Should().Be(_tracer.DefaultServiceName); - deserializedSpan.Tags.Should().HaveCount(customTagCount + 6); + deserializedSpan.Tags.Should().ContainKey(Tags.ProcessTags); + deserializedSpan.Tags.Should().HaveCount(customTagCount + 7); deserializedSpan.Metrics.Should().Contain(Metrics.SamplingLimitDecision, 0.75); deserializedSpan.Metrics.Should().Contain(Metrics.TopLevelSpan, 1); @@ -257,7 +259,8 @@ public async Task Serialization_ChildSpan() deserializedSpan.Tags.Should().Contain(Tags.Propagated.TraceIdUpper, hexStringTraceId); deserializedSpan.Tags.Should().ContainKey(Tags.BaseService); deserializedSpan.Tags[Tags.BaseService].Should().Be(_tracer.DefaultServiceName); - deserializedSpan.Tags.Should().HaveCount(customTagCount + 5); + deserializedSpan.Tags.Should().ContainKey(Tags.ProcessTags); + deserializedSpan.Tags.Should().HaveCount(customTagCount + 6); deserializedSpan.Metrics.Should().Contain(Metrics.SamplingLimitDecision, 0.75); deserializedSpan.Metrics.Should().HaveCount(customTagCount + 1);