diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/AllocationsProvider.cpp b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/AllocationsProvider.cpp index 312143739832..93b0f4dc498b 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/AllocationsProvider.cpp +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/AllocationsProvider.cpp @@ -232,7 +232,7 @@ void AllocationsProvider::OnAllocation(std::chrono::nanoseconds timestamp, // TODO: we need to check that threads are not jumping from one AppDomain to the other too frequently // because we might be receiving this event 1 second after it has been emitted - // It this is the case, we should simply set the AppDomainId to -1 all the time. + // It this is the case, we should simply set the AppDomainId to 0 all the time. AppDomainID appDomainId; if (SUCCEEDED(_pCorProfilerInfo->GetThreadAppDomain(threadInfo->GetClrThreadId(), &appDomainId))) { @@ -240,15 +240,13 @@ void AllocationsProvider::OnAllocation(std::chrono::nanoseconds timestamp, } else { - rawSample.AppDomainId = -1; + rawSample.AppDomainId = 0; } } else // create a fake IThreadInfo that wraps the OS thread id (no name, no profiler thread id) { rawSample.ThreadInfo = std::make_shared(threadId); - - // TODO: do we need to set to -1? - // rawSample.AppDomainId = -1; + rawSample.AppDomainId = 0; } // rawSample.AllocationSize = objectSize; diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.cpp b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.cpp index 927c6bc60b08..129928633434 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.cpp +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.cpp @@ -8,6 +8,7 @@ #include #include "EnvironmentVariables.h" +#include "Log.h" #include "OpSysTools.h" #include "shared/src/native-src/dd_filesystem.hpp" @@ -33,13 +34,13 @@ Configuration::Configuration() _pprofDirectory = ExtractPprofDirectory(); _isOperationalMetricsEnabled = GetEnvironmentValue(EnvironmentVariables::OperationalMetricsEnabled, false); _isNativeFrameEnabled = GetEnvironmentValue(EnvironmentVariables::NativeFramesEnabled, false); - _isCpuProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::CpuProfilingEnabled, true); - _isWallTimeProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::WallTimeProfilingEnabled, true); - _isExceptionProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::ExceptionProfilingEnabled, true); - _isAllocationProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::AllocationProfilingEnabled, false); + _isCpuProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::CpuProfilingEnabled, true, true); + _isWallTimeProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::WallTimeProfilingEnabled, true, true); + _isExceptionProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::ExceptionProfilingEnabled, true, true); + _isAllocationProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::AllocationProfilingEnabled, false, true); _isContentionProfilingEnabled = GetContention(); - _isGarbageCollectionProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::GCProfilingEnabled, true); - _isHeapProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::HeapProfilingEnabled, false); + _isGarbageCollectionProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::GCProfilingEnabled, true, true); + _isHeapProfilingEnabled = GetEnvironmentValue(EnvironmentVariables::HeapProfilingEnabled, false, true); _uploadPeriod = ExtractUploadInterval(); _userTags = ExtractUserTags(); _version = GetEnvironmentValue(EnvironmentVariables::Version, DefaultVersion); @@ -50,7 +51,7 @@ Configuration::Configuration() _agentPort = GetEnvironmentValue(EnvironmentVariables::AgentPort, DefaultAgentPort); _site = ExtractSite(); _apiKey = GetEnvironmentValue(EnvironmentVariables::ApiKey, DefaultEmptyString); - _serviceName = GetEnvironmentValue(EnvironmentVariables::ServiceName, OpSysTools::GetProcessName()); + _serviceName = GetEnvironmentValue(EnvironmentVariables::ServiceName, OpSysTools::GetProcessName(), true); _isAgentLess = GetEnvironmentValue(EnvironmentVariables::Agentless, false); _exceptionSampleLimit = GetEnvironmentValue(EnvironmentVariables::ExceptionSampleLimit, 500); _allocationSampleLimit = GetEnvironmentValue(EnvironmentVariables::AllocationSampleLimit, 2000); @@ -90,7 +91,7 @@ Configuration::Configuration() _cpuProfilingInterval = ExtractCpuProfilingInterval(1ms); } - _isEtwEnabled = GetEnvironmentValue(EnvironmentVariables::EtwEnabled, true); + _isEtwEnabled = GetEnvironmentValue(EnvironmentVariables::EtwEnabled, true, true); _deploymentMode = GetEnvironmentValue(EnvironmentVariables::SsiDeployed, DeploymentMode::Manual); _isEtwLoggingEnabled = GetEnvironmentValue(EnvironmentVariables::EtwLoggingEnabled, false); _etwReplayEndpoint = GetEnvironmentValue(EnvironmentVariables::EtwReplayEndpoint, DefaultEmptyString); @@ -518,11 +519,12 @@ bool Configuration::GetContention() // first look at the supported env var if (IsEnvironmentValueSet(EnvironmentVariables::LockContentionProfilingEnabled, lockContentionEnabled)) { + Log::Info("Configuration: ", EnvironmentVariables::LockContentionProfilingEnabled, " env var is set - lock contention is enabled"); return lockContentionEnabled; } // if not there, look at the deprecated one - return GetEnvironmentValue(EnvironmentVariables::DeprecatedContentionProfilingEnabled, lockContentionEnabled); + return GetEnvironmentValue(EnvironmentVariables::DeprecatedContentionProfilingEnabled, lockContentionEnabled, true); } bool Configuration::GetDefaultDebugLogEnabled() @@ -669,13 +671,32 @@ static bool convert_to(shared::WSTRING const& s, DeploymentMode& result) template -T Configuration::GetEnvironmentValue(shared::WSTRING const& name, T const& defaultValue) +T Configuration::GetEnvironmentValue(shared::WSTRING const& name, T const& defaultValue, bool shouldLog) { - if (!shared::EnvironmentExist(name)) return defaultValue; + if (!shared::EnvironmentExist(name)) + { + if (shouldLog) + { + Log::Info("Configuration: ", name, " env var is not set - '", defaultValue, "' is used as default value"); + } + return defaultValue; + } T result{}; auto r = shared::GetEnvironmentValue(name); - if (!convert_to(r, result)) return defaultValue; + if (!convert_to(r, result)) + { + if (shouldLog) + { + Log::Info("Configuration: ", name, " env var is set to '", r,"' that cannot be converted - '", defaultValue, "' is used as default value"); + } + return defaultValue; + } + + if (shouldLog) + { + Log::Info("Configuration: ", name, " env var is set to '", r, "'"); + } return result; } diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.h b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.h index d906277227df..0684502f1a28 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.h +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/Configuration.h @@ -99,7 +99,7 @@ class Configuration final : public IConfiguration static std::chrono::seconds GetDefaultUploadInterval(); static bool GetDefaultDebugLogEnabled(); template - static T GetEnvironmentValue(shared::WSTRING const& name, T const& defaultValue); + static T GetEnvironmentValue(shared::WSTRING const& name, T const& defaultValue, bool shouldLog = false); template static bool IsEnvironmentValueSet(shared::WSTRING const& name, T& value); static std::chrono::nanoseconds ExtractCpuWallTimeSamplingRate(int minimum = 5); diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ContentionProvider.cpp b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ContentionProvider.cpp index c7ed1b2e7473..7fecefe24615 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ContentionProvider.cpp +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ContentionProvider.cpp @@ -278,15 +278,13 @@ void ContentionProvider::AddContentionSample( } else { - rawSample.AppDomainId = -1; + rawSample.AppDomainId = 0; } } else // create a fake IThreadInfo that wraps the OS thread id (no name, no profiler thread id) { rawSample.ThreadInfo = std::make_shared(threadId); - - // TODO: do we need to set to -1? - //rawSample.AppDomainId = -1; + rawSample.AppDomainId = 0; } } diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/CpuProfilerType.h b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/CpuProfilerType.h index 401024bd0207..d5a13cfdf5a7 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/CpuProfilerType.h +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/CpuProfilerType.h @@ -5,7 +5,7 @@ #include "shared/src/native-src/string.h" -enum class CpuProfilerType +enum CpuProfilerType : int { ManualCpuTime, #ifdef LINUX diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/DeploymentMode.h b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/DeploymentMode.h index 9f714d2d0958..8c6639be2e65 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/DeploymentMode.h +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/DeploymentMode.h @@ -5,7 +5,7 @@ #include -enum class DeploymentMode +enum DeploymentMode : int { Manual, SingleStepInstrumentation diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Configuration/ConfigurationTest.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Configuration/ConfigurationTest.cs new file mode 100644 index 000000000000..60201daf34c1 --- /dev/null +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Configuration/ConfigurationTest.cs @@ -0,0 +1,205 @@ +// +// 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 2022 Datadog, Inc. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using Datadog.Profiler.IntegrationTests.Helpers; +using FluentAssertions; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Profiler.IntegrationTests.Exceptions +{ + public class ConfigurationTest + { + private const string Scenario1 = "--scenario 18"; + + private readonly ITestOutputHelper _output; + + public ConfigurationTest(ITestOutputHelper output) + { + _output = output; + } + + // NOTE: we don't need to validate ALL runtimes but just one + // + + [TestAppFact("Samples.Computer01", new[] { "net9.0" })] + public void CheckEnvVarsInLogWithDefaultProfilers(string appName, string framework, string appAssembly) + { + var runner = new TestApplicationRunner(appName, framework, appAssembly, _output, commandLine: Scenario1); + // EnvironmentHelper.DisableDefaultProfilers(runner); + + using var agent = MockDatadogAgent.CreateHttpAgent(runner.XUnitLogger); + runner.Run(agent); + + bool cpuIsLogged = false; + bool walltimeIsLogged = false; + bool exceptionIsLogged = false; + bool allocationIsLogged = false; + bool lockIsLogged = false; + bool gcIsLogged = false; + bool heapIsLogged = false; + bool serviceIsLogged = false; + bool etwIsLogged = false; + + var logFile = Directory.GetFiles(runner.Environment.LogDir) + .Single(f => Path.GetFileName(f).StartsWith("DD-DotNet-Profiler-Native-")); + + foreach (var line in File.ReadLines(logFile)) + { + if (line.Contains("DD_PROFILING_CPU_ENABLED")) + { + cpuIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_WALLTIME_ENABLED")) + { + walltimeIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_EXCEPTION_ENABLED")) + { + exceptionIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_ALLOCATION_ENABLED")) + { + allocationIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_CONTENTION_ENABLED")) + { + lockIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_GC_ENABLED")) + { + gcIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_HEAP_ENABLED")) + { + heapIsLogged = true; + } + else + if (line.Contains("DD_SERVICE")) + { + serviceIsLogged = true; + } + else + if (line.Contains("DD_INTERNAL_PROFILING_ETW_ENABLED")) + { + etwIsLogged = true; + } + else if (line.Contains("] Configuration: DD_")) + { + // This is the default value + Assert.Fail($"unexpected configuration log - {line}"); + } + } + + cpuIsLogged.Should().BeTrue(); + walltimeIsLogged.Should().BeTrue(); + exceptionIsLogged.Should().BeTrue(); + allocationIsLogged.Should().BeTrue(); + lockIsLogged.Should().BeTrue(); + gcIsLogged.Should().BeTrue(); + heapIsLogged.Should().BeTrue(); + serviceIsLogged.Should().BeTrue(); + etwIsLogged.Should().BeTrue(); + } + + [TestAppFact("Samples.Computer01", new[] { "net9.0" })] + public void CheckEnvVarsInLogWithDisabledProfilers(string appName, string framework, string appAssembly) + { + var runner = new TestApplicationRunner(appName, framework, appAssembly, _output, commandLine: Scenario1); + EnvironmentHelper.DisableDefaultProfilers(runner); + + using var agent = MockDatadogAgent.CreateHttpAgent(runner.XUnitLogger); + runner.Run(agent); + + bool cpuIsLogged = false; + bool walltimeIsLogged = false; + bool exceptionIsLogged = false; + bool allocationIsLogged = false; + bool lockIsLogged = false; + bool gcIsLogged = false; + bool heapIsLogged = false; + bool serviceIsLogged = false; + bool etwIsLogged = false; + + var logFile = Directory.GetFiles(runner.Environment.LogDir) + .Single(f => Path.GetFileName(f).StartsWith("DD-DotNet-Profiler-Native-")); + + foreach (var line in File.ReadLines(logFile)) + { + if (line.Contains("DD_PROFILING_CPU_ENABLED")) + { + cpuIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_WALLTIME_ENABLED")) + { + walltimeIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_EXCEPTION_ENABLED")) + { + exceptionIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_ALLOCATION_ENABLED")) + { + allocationIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_LOCK_ENABLED")) + { + lockIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_GC_ENABLED")) + { + gcIsLogged = true; + } + else + if (line.Contains("DD_PROFILING_HEAP_ENABLED")) + { + heapIsLogged = true; + } + else + if (line.Contains("DD_SERVICE")) + { + serviceIsLogged = true; + } + else + if (line.Contains("DD_INTERNAL_PROFILING_ETW_ENABLED")) + { + etwIsLogged = true; + } + else if (line.Contains("] Configuration: DD_")) + { + // This is the default value + Assert.Fail($"unexpected configuration log - {line}"); + } + } + + cpuIsLogged.Should().BeTrue(); + walltimeIsLogged.Should().BeTrue(); + exceptionIsLogged.Should().BeTrue(); + allocationIsLogged.Should().BeTrue(); + lockIsLogged.Should().BeTrue(); + gcIsLogged.Should().BeTrue(); + heapIsLogged.Should().BeTrue(); + serviceIsLogged.Should().BeTrue(); + etwIsLogged.Should().BeTrue(); + } + } +} 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 e3491cc9cace..1d16d3f9e304 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -131,6 +131,9 @@ + + + @@ -496,6 +499,7 @@ + diff --git a/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Core.cs b/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Core.cs index 8383184bfa0f..59d83a87b2dc 100644 --- a/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Core.cs +++ b/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Core.cs @@ -97,12 +97,13 @@ internal void BlockAndReport(IResult? result) } } - internal void ReportAndBlock(IResult? result) + internal void ReportAndBlock(IResult? result, Action telemetrySucessReport) { if (result is not null) { Reporter.TryReport(result, result.ShouldBlock); + telemetrySucessReport.Invoke(); if (result.ShouldBlock) { throw new BlockException(result, result.RedirectInfo ?? result.BlockInfo!, true); diff --git a/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Framework.cs b/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Framework.cs index 89b1b20d681d..b47d5f21d99d 100644 --- a/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Framework.cs +++ b/tracer/src/Datadog.Trace/AppSec/Coordinator/SecurityCoordinator.Framework.cs @@ -313,12 +313,13 @@ internal void BlockAndReport(IResult? result) reporting(null, result.ShouldBlock); } - internal void ReportAndBlock(IResult? result) + internal void ReportAndBlock(IResult? result, Action telemetrySucessReport) { if (result is not null) { var reporting = Reporter.MakeReportingFunction(result); reporting(null, result.ShouldBlock); + telemetrySucessReport.Invoke(); if (result.ShouldBlock) { diff --git a/tracer/src/Datadog.Trace/AppSec/Rasp/RaspModule.cs b/tracer/src/Datadog.Trace/AppSec/Rasp/RaspModule.cs index 3055687c4688..8d7ef08e19e0 100644 --- a/tracer/src/Datadog.Trace/AppSec/Rasp/RaspModule.cs +++ b/tracer/src/Datadog.Trace/AppSec/Rasp/RaspModule.cs @@ -23,6 +23,13 @@ internal static class RaspModule private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(RaspModule)); private static bool _nullContextReported = false; + internal enum BlockType + { + Irrelevant = 0, + Success = 1, + Failure = 2 + } + private static RaspRuleType? TryGetAddressRuleType(string address) => address switch { @@ -34,6 +41,47 @@ internal static class RaspModule _ => null, }; + private static RaspRuleTypeMatch? TryGetAddressRuleTypeMatch(string address, BlockType blockType) + => address switch + { + AddressesConstants.FileAccess => blockType switch + { + BlockType.Success => RaspRuleTypeMatch.LfiSuccess, + BlockType.Failure => RaspRuleTypeMatch.LfiFailure, + BlockType.Irrelevant => RaspRuleTypeMatch.LfiIrrelevant, + _ => null, + }, + AddressesConstants.UrlAccess => blockType switch + { + BlockType.Success => RaspRuleTypeMatch.SsrfSuccess, + BlockType.Failure => RaspRuleTypeMatch.SsrfFailure, + BlockType.Irrelevant => RaspRuleTypeMatch.SsrfIrrelevant, + _ => null, + }, + AddressesConstants.DBStatement => blockType switch + { + BlockType.Success => RaspRuleTypeMatch.SQlISuccess, + BlockType.Failure => RaspRuleTypeMatch.SQlIFailure, + BlockType.Irrelevant => RaspRuleTypeMatch.SQlIIrrelevant, + _ => null, + }, + AddressesConstants.ShellInjection => blockType switch + { + BlockType.Success => RaspRuleTypeMatch.CommandInjectionShellSuccess, + BlockType.Failure => RaspRuleTypeMatch.CommandInjectionShellFailure, + BlockType.Irrelevant => RaspRuleTypeMatch.CommandInjectionShellIrrelevant, + _ => null, + }, + AddressesConstants.CommandInjection => blockType switch + { + BlockType.Success => RaspRuleTypeMatch.CommandInjectionExecSuccess, + BlockType.Failure => RaspRuleTypeMatch.CommandInjectionExecFailure, + BlockType.Irrelevant => RaspRuleTypeMatch.CommandInjectionExecIrrelevant, + _ => null, + }, + _ => null, + }; + internal static void OnLfi(string file) { CheckVulnerability(new Dictionary { [AddressesConstants.FileAccess] = file }, AddressesConstants.FileAccess); @@ -84,7 +132,7 @@ private static void CheckVulnerability(Dictionary arguments, str RunWafRasp(arguments, rootSpan, address); } - private static void RecordRaspTelemetry(string address, bool isMatch, bool timeOut) + private static void RecordRaspTelemetry(string address, bool isMatch, bool timeOut, BlockType matchType) { var ruleType = TryGetAddressRuleType(address); @@ -98,7 +146,15 @@ private static void RecordRaspTelemetry(string address, bool isMatch, bool timeO if (isMatch) { - TelemetryFactory.Metrics.RecordCountRaspRuleMatch(ruleType.Value); + var ruleTypeMatch = TryGetAddressRuleTypeMatch(address, matchType); + + if (ruleTypeMatch is null) + { + Log.Warning("RASP: Rule match type not found for address {Address} {MatchType}", address, matchType); + return; + } + + TelemetryFactory.Metrics.RecordCountRaspRuleMatch(ruleTypeMatch.Value); } if (timeOut) @@ -129,11 +185,6 @@ private static void RunWafRasp(Dictionary arguments, Span rootSp var result = securityCoordinator.Value.RunWaf(arguments, runWithEphemeral: true, isRasp: true); - if (result is not null) - { - RecordRaspTelemetry(address, result.ReturnCode == Waf.WafReturnCode.Match, result.Timeout); - } - try { if (result?.SendStackInfo is not null && Security.Instance.Settings.StackTraceEnabled) @@ -158,9 +209,26 @@ private static void RunWafRasp(Dictionary arguments, Span rootSp AddSpanId(result); - // we want to report first because if we are inside a try{} catch(Exception ex){} block, we will not report - // the blockings, so we report first and then block - securityCoordinator.Value.ReportAndBlock(result); + if (result is not null) + { + // we want to report first because if we are inside a try{} catch(Exception ex){} block, we will not report + // the blockings, so we report first and then block + try + { + var matchSuccesCode = result.ReturnCode == WafReturnCode.Match && result.ShouldBlock ? + BlockType.Success : BlockType.Irrelevant; + + securityCoordinator.Value.ReportAndBlock(result, () => RecordRaspTelemetry(address, result.ReturnCode == Waf.WafReturnCode.Match, result.Timeout, matchSuccesCode)); + } + catch (Exception ex) when (ex is not BlockException) + { + var matchFailureCode = result.ReturnCode == WafReturnCode.Match && result.ShouldBlock ? + BlockType.Failure : BlockType.Irrelevant; + + RecordRaspTelemetry(address, result.ReturnCode == Waf.WafReturnCode.Match, result.Timeout, matchFailureCode); + Log.Error(ex, "RASP: Error while reporting and blocking."); + } + } } private static void AddSpanId(IResult? result) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/IS3EtagResponse.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/IS3EtagResponse.cs new file mode 100644 index 000000000000..7a49841306a3 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/IS3EtagResponse.cs @@ -0,0 +1,22 @@ +// +// 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 Datadog.Trace.DuckTyping; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3; + +/// +/// Shared interface for ducktyping for PutObjectResponse, CopyObjectResponse, and +/// CompleteMultipartUploadResponse. +/// +internal interface IS3EtagResponse : IDuckType +{ + /// + /// Gets the S3 response eTag, which is usually wrapped in quotes. + /// + [DuckField(Name = "eTag")] + string ETag { get; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadAsyncIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadAsyncIntegration.cs index 6359bb1965af..80791333cee4 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadAsyncIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadAsyncIntegration.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel; using System.Threading; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.MultipartUploadManagement; @@ -40,11 +41,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.BucketName, request.ObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static TReturn? OnAsyncMethodEnd(TTarget instance, TReturn? returnValue, Exception exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is ICompleteMultipartUploadRequest request && returnValue is not null) + { + var bucketName = request.BucketName; + var key = request.ObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return returnValue; } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadIntegration.cs index 6a92b12b2bc2..551fe8077dc9 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/MultipartUploadManagement/CompleteMultipartUploadIntegration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.MultipartUploadManagement; @@ -39,11 +40,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.BucketName, request.ObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn? returnValue, Exception? exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is ICompleteMultipartUploadRequest request && returnValue is not null) + { + var bucketName = request.BucketName; + var key = request.ObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return new CallTargetReturn(returnValue); } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectAsyncIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectAsyncIntegration.cs index bc7f03f059eb..f7e16f414ecf 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectAsyncIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectAsyncIntegration.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel; using System.Threading; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.ObjectManagement; @@ -40,11 +41,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.DestinationBucketName, request.DestinationObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static TReturn? OnAsyncMethodEnd(TTarget instance, TReturn? returnValue, Exception exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is ICopyObjectRequest request && returnValue is not null) + { + var bucketName = request.DestinationBucketName; + var key = request.DestinationObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return returnValue; } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectIntegration.cs index f42fd1bc99b6..77a0873dea86 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/CopyObjectIntegration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.ObjectManagement; @@ -39,11 +40,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.DestinationBucketName, request.DestinationObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn? returnValue, Exception? exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is ICopyObjectRequest request && returnValue is not null) + { + var bucketName = request.DestinationBucketName; + var key = request.DestinationObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return new CallTargetReturn(returnValue); } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectAsyncIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectAsyncIntegration.cs index 4daf574eeebb..f90a5e51c11e 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectAsyncIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectAsyncIntegration.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel; using System.Threading; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.ObjectManagement; @@ -40,11 +41,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.BucketName, request.ObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static TReturn? OnAsyncMethodEnd(TTarget instance, TReturn? returnValue, Exception exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is IPutObjectRequest request && returnValue is not null) + { + var bucketName = request.BucketName; + var key = request.ObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return returnValue; } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectIntegration.cs index 917af91ac39f..cf07f1714970 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectIntegration.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/S3/ObjectManagement/PutObjectIntegration.cs @@ -6,6 +6,7 @@ using System; using System.ComponentModel; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; using Datadog.Trace.ClrProfiler.CallTarget; namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.S3.ObjectManagement; @@ -39,11 +40,20 @@ internal static CallTargetState OnMethodBegin(TTarget instanc var scope = AwsS3Common.CreateScope(Tracer.Instance, Operation, out var tags); AwsS3Common.SetTags(tags, request.BucketName, request.ObjectKey); - return new CallTargetState(scope); + return new CallTargetState(scope, request); } internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn? returnValue, Exception? exception, in CallTargetState state) + where TReturn : IS3EtagResponse { + if (Tracer.Instance.Settings.SpanPointersEnabled && state.Scope is not null && state.State is IPutObjectRequest request && returnValue is not null) + { + var bucketName = request.BucketName; + var key = request.ObjectKey; + var eTag = returnValue.ETag; + SpanPointers.AddS3SpanPointer(state.Scope.Span, bucketName, key, eTag); + } + state.Scope.DisposeWithException(exception); return new CallTargetReturn(returnValue); } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Shared/SpanPointers.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Shared/SpanPointers.cs new file mode 100644 index 000000000000..1b443569de05 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Shared/SpanPointers.cs @@ -0,0 +1,147 @@ +// +// 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.Generic; +using System.Security.Cryptography; +using System.Text; +using Datadog.Trace.Util; + +#if NETCOREAPP3_1_OR_GREATER +using System; +using System.Buffers; +#else +using Datadog.Trace.VendoredMicrosoftCode.System.Buffers; +#endif + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; + +/// +/// SpanPointer helper methods +/// +internal static class SpanPointers +{ + // The pointer direction will always be down. The serverless agent handles cases where the + // direction is up. + private const string DownDirection = "d"; + private const string LinkKind = "span-pointer"; + private const int SpanPointerHashSizeBytes = 16; + private const string S3PtrKind = "aws.s3.object"; + + // S3 hashing rules: https://github.com/DataDog/dd-span-pointer-rules/blob/main/AWS/S3/Object/README.md + public static void AddS3SpanPointer(Span span, string bucketName, string key, string? eTag) + { + if (eTag == null) + { + return; + } + + var components = ConcatenateComponents(bucketName, key, eTag); + var hash = GeneratePointerHash(components); + + var spanLinkAttributes = new List>(4) + { + new("ptr.kind", S3PtrKind), + new("ptr.dir", DownDirection), + new("ptr.hash", hash), + new("link.kind", LinkKind) + }; + + var spanLink = new SpanLink(SpanContext.Zero, spanLinkAttributes); + span.AddLink(spanLink); + } + + internal static string ConcatenateComponents(string bucketName, string key, string eTag) + { + var builder = StringBuilderCache.Acquire(); + builder.Append(bucketName); + builder.Append('|'); + builder.Append(key); + builder.Append('|'); + + // ReSharper disable once MergeIntoPattern + // ReSharper disable once UseIndexFromEndExpression + if (eTag.Length >= 2 && eTag[0] == '"' && eTag[eTag.Length - 1] == '"') + { + // trim double-quotes around eTag if both leading and trailing quotes are present + // and there is at least one more character between them + // (avoid allocating a new string with String.Substring()) + builder.Append(eTag, 1, eTag.Length - 2); + } + else + { + builder.Append(eTag); + } + + return StringBuilderCache.GetStringAndRelease(builder); + } + + // Hashing rules: https://github.com/DataDog/dd-span-pointer-rules/tree/main?tab=readme-ov-file#general-hashing-rules + internal static string GeneratePointerHash(string components) + { + // compute max buffer size for UTF-8 bytes + // (faster than computing the actual byte count and good enough for the buffer size) + var maxByteCount = Encoding.UTF8.GetMaxByteCount(components.Length); + +#if NETCOREAPP3_1_OR_GREATER + // in .NET Core 3.1 and above, we can allocate the buffer + // for the UTF-8 bytes on the stack if it's small enough + if (maxByteCount < 256) + { + Span stackBuffer = stackalloc byte[maxByteCount]; + return ComputeHash(components, stackBuffer); + } +#endif + // rent a buffer for the UTF-8 bytes + var buffer = ArrayPool.Shared.Rent(minimumLength: maxByteCount); + + try + { + return ComputeHash(components, buffer); + } + finally + { + ArrayPool.Shared.Return(buffer); + } + } + +#if NETCOREAPP3_1_OR_GREATER + // .NET Core 3.1 and above have Encoding.UTF8.GetBytes() overload that writes to a Span buffer + internal static string ComputeHash(string components, Span buffer) + { + var byteCount = Encoding.UTF8.GetBytes(components, buffer); + Span fullHash = stackalloc byte[32]; // SHA256 produces 32 bytes + +#if NET6_0_OR_GREATER + // .NET 6 has a static TryHashData() method that avoids the allocation of a SHA256 instance + SHA256.TryHashData(buffer[..byteCount], fullHash, out _); +#else + using var sha256 = SHA256.Create(); + sha256.TryComputeHash(buffer[..byteCount], fullHash, out _); +#endif + + var truncatedHash = fullHash[..SpanPointerHashSizeBytes]; + return HexString.ToHexString(truncatedHash); + } +#else + // .NET Framework and .NET Standard 2.0 do not have Encoding.UTF8.GetBytes() overload + // that writes to a Span, so we fall back to a rented byte[] + internal static string ComputeHash(string components, byte[] buffer) + { + var byteCount = Encoding.UTF8.GetBytes( + components, + charIndex: 0, + charCount: components.Length, + bytes: buffer, + byteIndex: 0); + + using var sha256 = SHA256.Create(); + var fullHash = sha256.ComputeHash(buffer, offset: 0, count: byteCount); + var truncatedHash = fullHash.AsSpan(0, SpanPointerHashSizeBytes); + return HexString.ToHexString(truncatedHash); + } +#endif +} diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs index 3c2a2dd008f9..54a7eb0890ab 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs @@ -539,6 +539,12 @@ internal static partial class ConfigurationKeys /// public const string DisabledAdoNetCommandTypes = "DD_TRACE_DISABLED_ADONET_COMMAND_TYPES"; + /// + /// Configuration key for toggling span pointers on AWS requests. + /// Default value is true + /// + public const string SpanPointersEnabled = "DD_TRACE_AWS_ADD_SPAN_POINTERS"; + /// /// String constants for CI Visibility configuration keys. /// diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs index 1df489f402f2..5da97e8c09f2 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs @@ -105,6 +105,12 @@ public ConfigurationResult> GetDictionary(string key .Select(source => source.GetDictionary(key, telemetry, validator, allowOptionalMappings, separator)) .FirstOrDefault(value => value.IsValid, ConfigurationResult>.NotFound()); + /// + public ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser) + => _sources + .Select(source => source.GetDictionary(key, telemetry, validator, parser)) + .FirstOrDefault(value => value.IsValid, ConfigurationResult>.NotFound()); + /// public ConfigurationResult GetAs(string key, IConfigurationTelemetry telemetry, Func> converter, Func? validator, bool recordValue) => _sources diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs index e25059a0abe5..a639b572df6f 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs @@ -1,4 +1,4 @@ -// +// // 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. // @@ -154,6 +154,9 @@ public ConfigurationResult> GetDictionary(string key return ConfigurationResult>.NotFound(); } + public ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser) + => GetDictionary(key, telemetry, validator, allowOptionalMappings: false, separator: ':'); + public ConfigurationResult GetAs(string key, IConfigurationTelemetry telemetry, Func> converter, Func? validator, bool recordValue) { if (TryGetValue(key, out var objValue) && objValue is not null) diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs index b7944b898a83..0e02827773da 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs @@ -1,4 +1,4 @@ -// +// // 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. // @@ -98,6 +98,18 @@ ConfigurationResult GetString( /// The value of the setting, or null if not found. ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, bool allowOptionalMappings, char separator); + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The context for recording telemetry. + /// An optional validation function that must be applied to + /// a successfully extracted value to determine if it should be accepted + /// A user-provided parser that converts the input string into a dictionary + /// The value of the setting, or null if not found. + ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser); + /// /// Gets the value of /// the setting with the specified key. diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs index ef1b4695c04b..9d50a36d016c 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs @@ -336,6 +336,68 @@ ConfigurationResult> Validate(IDictionary> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser) + { + var token = SelectToken(key); + if (token == null) + { + return ConfigurationResult>.NotFound(); + } + + if (!TreatNullDictionaryAsEmpty && !token.HasValues) + { + return ConfigurationResult>.NotFound(); + } + + var tokenAsString = token.ToString(); + + try + { + if (token.Type == JTokenType.Object || token.Type == JTokenType.Array) + { + try + { + var dictionary = ConvertToDictionary(key, token); + if (dictionary is null) + { + // AFAICT this should never return null in practice - we + // already checked the token is not null, and it will throw + // if parsing fails, so using parsing failure here for safety + return ConfigurationResult>.ParseFailure(); + } + + return Validate(dictionary); + } + catch (Exception e) + { + Log.Error(e, "Unable to parse configuration value for {ConfigurationKey} as key-value pairs of strings.", key); + telemetry.Record(key, tokenAsString, recordValue: true, _origin, TelemetryErrorCode.JsonStringError); + return ConfigurationResult>.ParseFailure(); + } + } + + var result = parser(tokenAsString); + return Validate(result); + } + catch (InvalidCastException) + { + telemetry.Record(key, tokenAsString, recordValue: true, _origin, TelemetryErrorCode.JsonStringError); + throw; // Exising behaviour + } + + ConfigurationResult> Validate(IDictionary dictionary) + { + if (validator is null || validator(dictionary)) + { + telemetry.Record(key, tokenAsString, recordValue: true, _origin); + return ConfigurationResult>.Valid(dictionary); + } + + telemetry.Record(key, tokenAsString, recordValue: true, _origin, TelemetryErrorCode.FailedValidation); + return ConfigurationResult>.Invalid(dictionary); + } + } + private protected virtual JToken? SelectToken(string key) => _configuration?.SelectToken(key, errorWhenNoMatch: false); private protected virtual IDictionary? ConvertToDictionary(string key, JToken token) diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs index 62a142611bcc..8ff1e644d1b3 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs @@ -36,6 +36,9 @@ public ConfigurationResult> GetDictionary(string key public ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, bool allowOptionalMappings, char separator) => ConfigurationResult>.NotFound(); + public ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser) + => ConfigurationResult>.NotFound(); + public ConfigurationResult GetAs(string key, IConfigurationTelemetry telemetry, Func> converter, Func? validator, bool recordValue) => ConfigurationResult.NotFound(); } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs index 848e87383fdc..b4b29ad83be4 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs @@ -276,5 +276,30 @@ public ConfigurationResult> GetDictionary(string key telemetry.Record(key, value, recordValue: true, Origin, TelemetryErrorCode.FailedValidation); return ConfigurationResult>.Invalid(result); } + + /// + public ConfigurationResult> GetDictionary(string key, IConfigurationTelemetry telemetry, Func, bool>? validator, Func> parser) + { + var value = GetString(key); + + if (value is null) + { + return ConfigurationResult>.NotFound(); + } + + // We record the original dictionary value here instead of serializing the _parsed_ value + // Currently we have no validation of the dictionary values during parsing, so there's no way to get + // a validation error that needs recording at this stage + var result = parser(value); + + if (validator is null || validator(result)) + { + telemetry.Record(key, value, recordValue: true, Origin); + return ConfigurationResult>.Valid(result); + } + + telemetry.Record(key, value, recordValue: true, Origin, TelemetryErrorCode.FailedValidation); + return ConfigurationResult>.Invalid(result); + } } } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs index 0c796dd510c9..c75ebb3386ee 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs @@ -371,6 +371,9 @@ public ClassConfigurationResultWithKey> AsDictionary public ClassConfigurationResultWithKey> AsDictionaryResult(bool allowOptionalMappings, char separator) => new(Telemetry, Key, recordValue: true, configurationResult: GetDictionaryResult(allowOptionalMappings, separator)); + public ClassConfigurationResultWithKey> AsDictionaryResult(Func> parser) + => new(Telemetry, Key, recordValue: true, configurationResult: GetDictionaryResult(parser)); + private ConfigurationResult GetStringResult(Func? validator, Func>? converter, bool recordValue) => converter is null ? GetResult(AsStringSelector, validator, recordValue) @@ -477,6 +480,27 @@ private ConfigurationResult> GetDictionaryResult(boo return result; } + + private ConfigurationResult> GetDictionaryResult(Func> parser) + { + var result = Source.GetDictionary(Key, Telemetry, validator: null, parser); + if (result.ShouldFallBack && FallbackKey1 is not null) + { + result = Source.GetDictionary(FallbackKey1, Telemetry, validator: null, parser); + } + + if (result.ShouldFallBack && FallbackKey2 is not null) + { + result = Source.GetDictionary(FallbackKey2, Telemetry, validator: null, parser); + } + + if (result.ShouldFallBack && FallbackKey3 is not null) + { + result = Source.GetDictionary(FallbackKey3, Telemetry, validator: null, parser); + } + + return result; + } } internal readonly struct StructConfigurationResultWithKey(IConfigurationTelemetry telemetry, string key, bool recordValue, ConfigurationResult configurationResult) diff --git a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs index 7adec0fed3c7..486b03ea1bd9 100644 --- a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs @@ -6,6 +6,7 @@ #nullable enable using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; @@ -37,7 +38,10 @@ namespace Datadog.Trace.Configuration public record TracerSettings { private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(); - private static readonly HashSet DefaultExperimentalFeatures = new HashSet(); + private static readonly HashSet DefaultExperimentalFeatures = new HashSet() + { + "DD_TAGS" + }; private readonly IConfigurationTelemetry _telemetry; // we cached the static instance here, because is being used in the hotpath @@ -149,7 +153,71 @@ _ when x.ToBoolean() is { } boolean => boolean, .WithKeys(ConfigurationKeys.OpenTelemetry.ResourceAttributes) .AsDictionaryResult(separator: '='); - var globalTags = config + Dictionary? globalTags = default; + if (ExperimentalFeaturesEnabled.Contains("DD_TAGS")) + { + // New behavior: If ExperimentalFeaturesEnabled configures DD_TAGS, we want to change DD_TAGS parsing to do the following: + // 1. If a comma is in the value, split on comma as before. Otherwise, split on space + // 2. Key-value pairs with empty values are allowed, instead of discarded + // 3. Key-value pairs without values (i.e. no `:` separator) are allowed and treated as key-value pairs with empty values, instead of discarded + Func> updatedTagsParser = (data) => + { + var dictionary = new ConcurrentDictionary(); + if (string.IsNullOrWhiteSpace(data)) + { + // return empty collection + return dictionary; + } + + char[] separatorChars = data.Contains(',') ? [','] : [' ']; + var entries = data.Split(separatorChars, StringSplitOptions.RemoveEmptyEntries); + + foreach (var entry in entries) + { + // we need Trim() before looking forthe separator so we can skip entries with no key + // (that is, entries with a leading separator, like ":value") + var trimmedEntry = entry.Trim(); + if (trimmedEntry.Length == 0 || trimmedEntry[0] == ':') + { + continue; + } + + var separatorIndex = trimmedEntry.IndexOf(':'); + if (separatorIndex < 0) + { + // entries with no separator are allowed (e.g. key1 and key3 in "key1, key2:value2, key3"), + // it's a key with no value. + var key = trimmedEntry; + dictionary[key] = string.Empty; + } + else if (separatorIndex > 0) + { + // if a separator is present with no value, we take the value to be empty (e.g. "key1:, key2: "). + // note we already did Trim() on the entire entry, so the key portion only needs TrimEnd(). + var key = trimmedEntry.Substring(0, separatorIndex).TrimEnd(); + var value = trimmedEntry.Substring(separatorIndex + 1).Trim(); + dictionary[key] = value; + } + } + + return dictionary; + }; + + globalTags = config + .WithKeys(ConfigurationKeys.GlobalTags, "DD_TRACE_GLOBAL_TAGS") + .AsDictionaryResult(parser: updatedTagsParser) + .OverrideWith( + RemapOtelTags(in otelTags), + ErrorLog, + () => new DefaultResult>(new Dictionary(), string.Empty)) + + // Filter out tags with empty keys, and trim whitespace + .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key)) + .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value?.Trim() ?? string.Empty); + } + else + { + globalTags = config .WithKeys(ConfigurationKeys.GlobalTags, "DD_TRACE_GLOBAL_TAGS") .AsDictionaryResult() .OverrideWith( @@ -157,16 +225,17 @@ _ when x.ToBoolean() is { } boolean => boolean, ErrorLog, () => new DefaultResult>(new Dictionary(), string.Empty)) - // Filter out tags with empty keys or empty values, and trim whitespace + // Filter out tags with empty keys or empty values, and trim whitespace .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key) && !string.IsNullOrWhiteSpace(kvp.Value)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); + } Environment = config .WithKeys(ConfigurationKeys.Environment) .AsString(); // DD_ENV has precedence over DD_TAGS - Environment = GetExplicitSettingOrTag(Environment, globalTags, Tags.Env, ConfigurationKeys.Environment); + Environment = GetExplicitSettingOrTag(Environment, globalTags!, Tags.Env, ConfigurationKeys.Environment); var otelServiceName = config.WithKeys(ConfigurationKeys.OpenTelemetry.ServiceName).AsStringResult(); var serviceName = config @@ -307,6 +376,9 @@ _ when x.ToBoolean() is { } boolean => boolean, RemoveClientServiceNamesEnabled = config .WithKeys(ConfigurationKeys.RemoveClientServiceNamesEnabled) .AsBool(defaultValue: false); + SpanPointersEnabled = config + .WithKeys(ConfigurationKeys.SpanPointersEnabled) + .AsBool(defaultValue: true); PeerServiceNameMappings = InitializeServiceNameMappings(config, ConfigurationKeys.PeerServiceNameMappings); @@ -1125,6 +1197,11 @@ public bool DiagnosticSourceEnabled /// internal bool RemoveClientServiceNamesEnabled { get; } + /// + /// Gets a value indicating whether to add span pointers on AWS requests. + /// + internal bool SpanPointersEnabled { get; } + /// /// Gets the metadata schema version /// diff --git a/tracer/src/Datadog.Trace/Debugger/Upload/SymbolUploadApi.cs b/tracer/src/Datadog.Trace/Debugger/Upload/SymbolUploadApi.cs index 762d6f13faa4..283af7e41b49 100644 --- a/tracer/src/Datadog.Trace/Debugger/Upload/SymbolUploadApi.cs +++ b/tracer/src/Datadog.Trace/Debugger/Upload/SymbolUploadApi.cs @@ -42,7 +42,7 @@ private SymbolUploadApi( discoveryService.SubscribeToChanges(c => Endpoint = c.SymbolDbEndpoint); } - public static IBatchUploadApi Create( + internal static IBatchUploadApi Create( IApiRequestFactory apiRequestFactory, IDiscoveryService discoveryService, IGitMetadataTagsProvider gitMetadataTagsProvider, @@ -90,18 +90,13 @@ public override async Task SendBatchAsync(ArraySegment symbols) } else { - using var memoryStream = new MemoryStream(); -#if NETFRAMEWORK - using (var gzipStream = new Vendors.ICSharpCode.SharpZipLib.GZip.GZipOutputStream(memoryStream)) -#else - using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) -#endif + var compressedSymbols = await CompressDataAsync(symbols).ConfigureAwait(false); + if (compressedSymbols == null) { - await gzipStream.WriteAsync(symbols.Array, 0, symbols.Array.Length).ConfigureAwait(false); - await gzipStream.FlushAsync().ConfigureAwait(false); + return false; } - symbolsItem = new MultipartFormItem("file", MimeTypes.Gzip, "file.gz", new ArraySegment(memoryStream.ToArray())); + symbolsItem = new MultipartFormItem("file", MimeTypes.Gzip, "file.gz", compressedSymbols.Value); } var items = new[] { symbolsItem, new MultipartFormItem("event", MimeTypes.Json, "event.json", _eventMetadata) }; @@ -130,5 +125,42 @@ public override async Task SendBatchAsync(ArraySegment symbols) return false; } + + internal async Task?> CompressDataAsync(ArraySegment data) + { + using var memoryStream = new MemoryStream(); + +#if NETFRAMEWORK + using (var gzipStream = new Vendors.ICSharpCode.SharpZipLib.GZip.GZipOutputStream(memoryStream)) +#else + using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress)) +#endif + { + await gzipStream.WriteAsync(data.Array!, data.Offset, data.Count).ConfigureAwait(false); + await gzipStream.FlushAsync().ConfigureAwait(false); + } + + var compressedData = memoryStream.ToArray(); + + // see here about the following validation: https://forensics.wiki/gzip/ + // minimum size for header + footer + if (compressedData.Length < 18) + { + Log.Error("Compression produced invalid data: size {Size} bytes is below minimum valid GZip size", property: compressedData.Length); + return null; + } + + // header magic numbers + if (compressedData[0] != 0x1F || compressedData[1] != 0x8B) + { + Log.Error( + "Compression produced invalid data: invalid GZip header {Header}", + BitConverter.ToString(System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Take(compressedData, 2)))); + + return null; + } + + return new ArraySegment(compressedData); + } } } diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs index 4fdc8921fb58..923039e18ff0 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs @@ -30,11 +30,11 @@ internal static partial class RaspRuleTypeExtensions public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType value) => value switch { - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;rule_type:lfi", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;rule_type:ssrf", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;rule_type:sql_injection", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;rule_type:command_injection;rule_variant:shell", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;event_rules_version;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;event_rules_version;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;event_rules_version;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", _ => value.ToString(), }; @@ -84,10 +84,10 @@ public static string[] GetNames() public static string[] GetDescriptions() => new [] { - "waf_version;rule_type:lfi", - "waf_version;rule_type:ssrf", - "waf_version;rule_type:sql_injection", - "waf_version;rule_type:command_injection;rule_variant:shell", - "waf_version;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;rule_type:lfi", + "waf_version;event_rules_version;rule_type:ssrf", + "waf_version;event_rules_version;rule_type:sql_injection", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs new file mode 100644 index 000000000000..0fdc8d77792a --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs @@ -0,0 +1,133 @@ +// +// 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 + +namespace Datadog.Trace.Telemetry.Metrics; + +/// +/// Extension methods for +/// +internal static partial class RaspRuleTypeMatchExtensions +{ + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 15; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Description] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch value) + => value switch + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess => "waf_version;event_rules_version;block:success;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess => "waf_version;event_rules_version;block:success;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess => "waf_version;event_rules_version;block:success;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure => "waf_version;event_rules_version;block:failure;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure => "waf_version;event_rules_version;block:failure;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure => "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + _ => value.ToString(), + }; + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch[] GetValues() + => new [] + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant, + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Ignores [Description] definitions. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + => new [] + { + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant), + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Uses [Description] definition if available, otherwise uses the name of the property + /// + /// An array of the names of the members defined in + public static string[] GetDescriptions() + => new [] + { + "waf_version;event_rules_version;block:success;rule_type:lfi", + "waf_version;event_rules_version;block:success;rule_type:ssrf", + "waf_version;event_rules_version;block:success;rule_type:sql_injection", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:failure;rule_type:lfi", + "waf_version;event_rules_version;block:failure;rule_type:ssrf", + "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + }; +} \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs index 363a5e43830a..7500ae6cf042 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs index 1f009e0918d2..6217252b104c 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs @@ -81,7 +81,7 @@ internal partial interface IMetricsTelemetryCollector public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1); public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, 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 9da1f3508715..37ecde449b32 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 partial class MetricsTelemetryCollector { - private const int CountLength = 613; + private const int CountLength = 623; /// /// Creates the buffer for the values. @@ -575,34 +575,44 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), // rasp.rule.eval, index = 520 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), + 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 = 525 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 530 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 535 + 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" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:ssrf" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:sql_injection" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:ssrf" }), + 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 = 540 + 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 = 545 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 = 539 + // instrum.user_auth.missing_user_login, index = 549 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" }), - // executed.source, index = 543 + // executed.source, index = 553 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -617,9 +627,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 = 557 + // executed.propagation, index = 567 new(null), - // executed.sink, index = 558 + // executed.sink, index = 568 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -647,9 +657,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 = 585 + // request.tainted, index = 595 new(null), - // suppressed.vulnerabilities, index = 586 + // suppressed.vulnerabilities, index = 596 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -685,7 +695,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, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 5, 5, 4, 4, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 15, 5, 4, 4, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -895,7 +905,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R Interlocked.Add(ref _buffer.Count[index], increment); } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { var index = 525 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); @@ -903,47 +913,47 @@ public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags. public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 540 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 545 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 539 + (int)tag; + var index = 549 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 543 + (int)tag; + var index = 553 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[557], increment); + Interlocked.Add(ref _buffer.Count[567], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 558 + (int)tag; + var index = 568 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[585], increment); + Interlocked.Add(ref _buffer.Count[595], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 596 + (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/NullMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs index eb750e63a8ad..9b6efbd64cec 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs index 4fdc8921fb58..923039e18ff0 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs @@ -30,11 +30,11 @@ internal static partial class RaspRuleTypeExtensions public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType value) => value switch { - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;rule_type:lfi", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;rule_type:ssrf", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;rule_type:sql_injection", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;rule_type:command_injection;rule_variant:shell", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;event_rules_version;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;event_rules_version;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;event_rules_version;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", _ => value.ToString(), }; @@ -84,10 +84,10 @@ public static string[] GetNames() public static string[] GetDescriptions() => new [] { - "waf_version;rule_type:lfi", - "waf_version;rule_type:ssrf", - "waf_version;rule_type:sql_injection", - "waf_version;rule_type:command_injection;rule_variant:shell", - "waf_version;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;rule_type:lfi", + "waf_version;event_rules_version;rule_type:ssrf", + "waf_version;event_rules_version;rule_type:sql_injection", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs new file mode 100644 index 000000000000..0fdc8d77792a --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs @@ -0,0 +1,133 @@ +// +// 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 + +namespace Datadog.Trace.Telemetry.Metrics; + +/// +/// Extension methods for +/// +internal static partial class RaspRuleTypeMatchExtensions +{ + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 15; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Description] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch value) + => value switch + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess => "waf_version;event_rules_version;block:success;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess => "waf_version;event_rules_version;block:success;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess => "waf_version;event_rules_version;block:success;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure => "waf_version;event_rules_version;block:failure;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure => "waf_version;event_rules_version;block:failure;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure => "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + _ => value.ToString(), + }; + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch[] GetValues() + => new [] + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant, + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Ignores [Description] definitions. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + => new [] + { + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant), + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Uses [Description] definition if available, otherwise uses the name of the property + /// + /// An array of the names of the members defined in + public static string[] GetDescriptions() + => new [] + { + "waf_version;event_rules_version;block:success;rule_type:lfi", + "waf_version;event_rules_version;block:success;rule_type:ssrf", + "waf_version;event_rules_version;block:success;rule_type:sql_injection", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:failure;rule_type:lfi", + "waf_version;event_rules_version;block:failure;rule_type:ssrf", + "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + }; +} \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs index 363a5e43830a..7500ae6cf042 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs index 1f009e0918d2..6217252b104c 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs @@ -81,7 +81,7 @@ internal partial interface IMetricsTelemetryCollector public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1); public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, 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 9da1f3508715..37ecde449b32 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 partial class MetricsTelemetryCollector { - private const int CountLength = 613; + private const int CountLength = 623; /// /// Creates the buffer for the values. @@ -575,34 +575,44 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), // rasp.rule.eval, index = 520 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), + 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 = 525 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 530 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 535 + 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" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:ssrf" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:sql_injection" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:ssrf" }), + 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 = 540 + 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 = 545 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 = 539 + // instrum.user_auth.missing_user_login, index = 549 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" }), - // executed.source, index = 543 + // executed.source, index = 553 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -617,9 +627,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 = 557 + // executed.propagation, index = 567 new(null), - // executed.sink, index = 558 + // executed.sink, index = 568 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -647,9 +657,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 = 585 + // request.tainted, index = 595 new(null), - // suppressed.vulnerabilities, index = 586 + // suppressed.vulnerabilities, index = 596 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -685,7 +695,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, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 5, 5, 4, 4, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 15, 5, 4, 4, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -895,7 +905,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R Interlocked.Add(ref _buffer.Count[index], increment); } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { var index = 525 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); @@ -903,47 +913,47 @@ public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags. public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 540 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 545 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 539 + (int)tag; + var index = 549 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 543 + (int)tag; + var index = 553 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[557], increment); + Interlocked.Add(ref _buffer.Count[567], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 558 + (int)tag; + var index = 568 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[585], increment); + Interlocked.Add(ref _buffer.Count[595], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 596 + (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/NullMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs index eb750e63a8ad..9b6efbd64cec 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs index 4fdc8921fb58..923039e18ff0 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs @@ -30,11 +30,11 @@ internal static partial class RaspRuleTypeExtensions public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType value) => value switch { - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;rule_type:lfi", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;rule_type:ssrf", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;rule_type:sql_injection", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;rule_type:command_injection;rule_variant:shell", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;event_rules_version;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;event_rules_version;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;event_rules_version;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", _ => value.ToString(), }; @@ -84,10 +84,10 @@ public static string[] GetNames() public static string[] GetDescriptions() => new [] { - "waf_version;rule_type:lfi", - "waf_version;rule_type:ssrf", - "waf_version;rule_type:sql_injection", - "waf_version;rule_type:command_injection;rule_variant:shell", - "waf_version;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;rule_type:lfi", + "waf_version;event_rules_version;rule_type:ssrf", + "waf_version;event_rules_version;rule_type:sql_injection", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs new file mode 100644 index 000000000000..0fdc8d77792a --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs @@ -0,0 +1,133 @@ +// +// 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 + +namespace Datadog.Trace.Telemetry.Metrics; + +/// +/// Extension methods for +/// +internal static partial class RaspRuleTypeMatchExtensions +{ + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 15; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Description] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch value) + => value switch + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess => "waf_version;event_rules_version;block:success;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess => "waf_version;event_rules_version;block:success;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess => "waf_version;event_rules_version;block:success;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure => "waf_version;event_rules_version;block:failure;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure => "waf_version;event_rules_version;block:failure;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure => "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + _ => value.ToString(), + }; + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch[] GetValues() + => new [] + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant, + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Ignores [Description] definitions. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + => new [] + { + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant), + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Uses [Description] definition if available, otherwise uses the name of the property + /// + /// An array of the names of the members defined in + public static string[] GetDescriptions() + => new [] + { + "waf_version;event_rules_version;block:success;rule_type:lfi", + "waf_version;event_rules_version;block:success;rule_type:ssrf", + "waf_version;event_rules_version;block:success;rule_type:sql_injection", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:failure;rule_type:lfi", + "waf_version;event_rules_version;block:failure;rule_type:ssrf", + "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + }; +} \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs index 363a5e43830a..7500ae6cf042 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs index 1f009e0918d2..6217252b104c 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs @@ -81,7 +81,7 @@ internal partial interface IMetricsTelemetryCollector public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1); public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, 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 9da1f3508715..37ecde449b32 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 partial class MetricsTelemetryCollector { - private const int CountLength = 613; + private const int CountLength = 623; /// /// Creates the buffer for the values. @@ -575,34 +575,44 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), // rasp.rule.eval, index = 520 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), + 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 = 525 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 530 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 535 + 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" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:ssrf" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:sql_injection" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:ssrf" }), + 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 = 540 + 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 = 545 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 = 539 + // instrum.user_auth.missing_user_login, index = 549 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" }), - // executed.source, index = 543 + // executed.source, index = 553 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -617,9 +627,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 = 557 + // executed.propagation, index = 567 new(null), - // executed.sink, index = 558 + // executed.sink, index = 568 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -647,9 +657,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 = 585 + // request.tainted, index = 595 new(null), - // suppressed.vulnerabilities, index = 586 + // suppressed.vulnerabilities, index = 596 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -685,7 +695,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, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 5, 5, 4, 4, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 15, 5, 4, 4, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -895,7 +905,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R Interlocked.Add(ref _buffer.Count[index], increment); } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { var index = 525 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); @@ -903,47 +913,47 @@ public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags. public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 540 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 545 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 539 + (int)tag; + var index = 549 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 543 + (int)tag; + var index = 553 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[557], increment); + Interlocked.Add(ref _buffer.Count[567], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 558 + (int)tag; + var index = 568 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[585], increment); + Interlocked.Add(ref _buffer.Count[595], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 596 + (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/NullMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs index eb750e63a8ad..9b6efbd64cec 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs index 4fdc8921fb58..923039e18ff0 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeExtensions_EnumExtensions.g.cs @@ -30,11 +30,11 @@ internal static partial class RaspRuleTypeExtensions public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType value) => value switch { - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;rule_type:lfi", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;rule_type:ssrf", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;rule_type:sql_injection", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;rule_type:command_injection;rule_variant:shell", - Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Lfi => "waf_version;event_rules_version;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.Ssrf => "waf_version;event_rules_version;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.SQlI => "waf_version;event_rules_version;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionShell => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType.CommandInjectionExec => "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", _ => value.ToString(), }; @@ -84,10 +84,10 @@ public static string[] GetNames() public static string[] GetDescriptions() => new [] { - "waf_version;rule_type:lfi", - "waf_version;rule_type:ssrf", - "waf_version;rule_type:sql_injection", - "waf_version;rule_type:command_injection;rule_variant:shell", - "waf_version;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;rule_type:lfi", + "waf_version;event_rules_version;rule_type:ssrf", + "waf_version;event_rules_version;rule_type:sql_injection", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec", }; } \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs new file mode 100644 index 000000000000..0fdc8d77792a --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/RaspRuleTypeMatchExtensions_EnumExtensions.g.cs @@ -0,0 +1,133 @@ +// +// 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 + +namespace Datadog.Trace.Telemetry.Metrics; + +/// +/// Extension methods for +/// +internal static partial class RaspRuleTypeMatchExtensions +{ + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 15; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Description] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch value) + => value switch + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess => "waf_version;event_rules_version;block:success;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess => "waf_version;event_rules_version;block:success;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess => "waf_version;event_rules_version;block:success;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess => "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure => "waf_version;event_rules_version;block:failure;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure => "waf_version;event_rules_version;block:failure;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure => "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure => "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant => "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + _ => value.ToString(), + }; + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch[] GetValues() + => new [] + { + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant, + Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant, + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Ignores [Description] definitions. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + => new [] + { + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlISuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecSuccess), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecFailure), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.LfiIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SsrfIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.SQlIIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionShellIrrelevant), + nameof(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch.CommandInjectionExecIrrelevant), + }; + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// Uses [Description] definition if available, otherwise uses the name of the property + /// + /// An array of the names of the members defined in + public static string[] GetDescriptions() + => new [] + { + "waf_version;event_rules_version;block:success;rule_type:lfi", + "waf_version;event_rules_version;block:success;rule_type:ssrf", + "waf_version;event_rules_version;block:success;rule_type:sql_injection", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:failure;rule_type:lfi", + "waf_version;event_rules_version;block:failure;rule_type:ssrf", + "waf_version;event_rules_version;block:failure;rule_type:sql_injection", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec", + "waf_version;event_rules_version;block:irrelevant;rule_type:lfi", + "waf_version;event_rules_version;block:irrelevant;rule_type:ssrf", + "waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell", + "waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec", + }; +} \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs index 363a5e43830a..7500ae6cf042 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs index 1f009e0918d2..6217252b104c 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/IMetricsTelemetryCollector_Count.g.cs @@ -81,7 +81,7 @@ internal partial interface IMetricsTelemetryCollector public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1); + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1); public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, 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 9da1f3508715..37ecde449b32 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 partial class MetricsTelemetryCollector { - private const int CountLength = 613; + private const int CountLength = 623; /// /// Creates the buffer for the values. @@ -575,34 +575,44 @@ private static AggregatedMetric[] GetCountBuffer() new(new[] { "truncation_reason:list_or_map_too_large" }), new(new[] { "truncation_reason:object_too_deep" }), // rasp.rule.eval, index = 520 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), + 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 = 525 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // rasp.timeout, index = 530 - new(new[] { "waf_version", "rule_type:lfi" }), - new(new[] { "waf_version", "rule_type:ssrf" }), - new(new[] { "waf_version", "rule_type:sql_injection" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:shell" }), - new(new[] { "waf_version", "rule_type:command_injection", "rule_variant:exec" }), - // instrum.user_auth.missing_user_id, index = 535 + 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" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:success", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:ssrf" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:sql_injection" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:shell" }), + new(new[] { "waf_version", "event_rules_version", "block:failure", "rule_type:command_injection", "rule_variant:exec" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:lfi" }), + new(new[] { "waf_version", "event_rules_version", "block:irrelevant", "rule_type:ssrf" }), + 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 = 540 + 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 = 545 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 = 539 + // instrum.user_auth.missing_user_login, index = 549 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" }), - // executed.source, index = 543 + // executed.source, index = 553 new(new[] { "source_type:http.request.body" }), new(new[] { "source_type:http.request.path" }), new(new[] { "source_type:http.request.parameter.name" }), @@ -617,9 +627,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 = 557 + // executed.propagation, index = 567 new(null), - // executed.sink, index = 558 + // executed.sink, index = 568 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -647,9 +657,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 = 585 + // request.tainted, index = 595 new(null), - // suppressed.vulnerabilities, index = 586 + // suppressed.vulnerabilities, index = 596 new(new[] { "vulnerability_type:none" }), new(new[] { "vulnerability_type:weak_cipher" }), new(new[] { "vulnerability_type:weak_hash" }), @@ -685,7 +695,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, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 5, 5, 4, 4, 14, 1, 27, 1, 27, }; + = new int[]{ 4, 80, 1, 3, 4, 2, 2, 4, 1, 1, 1, 22, 3, 2, 5, 5, 2, 1, 22, 3, 90, 90, 2, 44, 6, 1, 1, 80, 1, 22, 3, 2, 2, 5, 3, 5, 15, 5, 4, 4, 14, 1, 27, 1, 27, }; public void RecordCountLogCreated(Datadog.Trace.Telemetry.Metrics.MetricTags.LogLevel tag, int increment = 1) { @@ -895,7 +905,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R Interlocked.Add(ref _buffer.Count[index], increment); } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { var index = 525 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); @@ -903,47 +913,47 @@ public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags. public void RecordCountRaspTimeout(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) { - var index = 530 + (int)tag; + var index = 540 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserId(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 535 + (int)tag; + var index = 545 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountMissingUserLogin(Datadog.Trace.Telemetry.Metrics.MetricTags.AuthenticationFrameworkWithEventType tag, int increment = 1) { - var index = 539 + (int)tag; + var index = 549 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedSources(Datadog.Trace.Telemetry.Metrics.MetricTags.IastSourceType tag, int increment = 1) { - var index = 543 + (int)tag; + var index = 553 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastExecutedPropagations(int increment = 1) { - Interlocked.Add(ref _buffer.Count[557], increment); + Interlocked.Add(ref _buffer.Count[567], increment); } public void RecordCountIastExecutedSinks(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 558 + (int)tag; + var index = 568 + (int)tag; Interlocked.Add(ref _buffer.Count[index], increment); } public void RecordCountIastRequestTainted(int increment = 1) { - Interlocked.Add(ref _buffer.Count[585], increment); + Interlocked.Add(ref _buffer.Count[595], increment); } public void RecordCountIastSuppressedVulnerabilities(Datadog.Trace.Telemetry.Metrics.MetricTags.IastVulnerabilityType tag, int increment = 1) { - var index = 586 + (int)tag; + var index = 596 + (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/NullMetricsTelemetryCollector_Count.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs index eb750e63a8ad..9b6efbd64cec 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/NullMetricsTelemetryCollector_Count.g.cs @@ -156,7 +156,7 @@ public void RecordCountRaspRuleEval(Datadog.Trace.Telemetry.Metrics.MetricTags.R { } - public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleType tag, int increment = 1) + public void RecordCountRaspRuleMatch(Datadog.Trace.Telemetry.Metrics.MetricTags.RaspRuleTypeMatch tag, int increment = 1) { } diff --git a/tracer/src/Datadog.Trace/Propagators/ParseUtility.cs b/tracer/src/Datadog.Trace/Propagators/ParseUtility.cs index da74da6a21ef..01c61935016f 100644 --- a/tracer/src/Datadog.Trace/Propagators/ParseUtility.cs +++ b/tracer/src/Datadog.Trace/Propagators/ParseUtility.cs @@ -5,13 +5,10 @@ #nullable enable -using System; using System.Collections.Generic; -using System.Diagnostics.Contracts; using System.Globalization; using Datadog.Trace.Headers; using Datadog.Trace.Logging; -using Datadog.Trace.Util; namespace Datadog.Trace.Propagators { @@ -67,9 +64,15 @@ internal class ParseUtility return null; // IEnumerable version (different method to avoid try/finally in the caller) - static bool TryParse(IEnumerable headerValues, ref bool hasValue, out ulong result) + static bool TryParse(IEnumerable? headerValues, ref bool hasValue, out ulong result) { result = 0; + + if (headerValues is null) + { + return false; + } + foreach (string? headerValue in headerValues) { if (ulong.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) @@ -133,9 +136,15 @@ static bool TryParse(IEnumerable headerValues, ref bool hasValue, out u return null; // IEnumerable version (different method to avoid try/finally in the caller) - static bool TryParse(IEnumerable headerValues, ref bool hasValue, out int result) + static bool TryParse(IEnumerable? headerValues, ref bool hasValue, out int result) { result = 0; + + if (headerValues is null) + { + return false; + } + foreach (string? headerValue in headerValues) { if (int.TryParse(headerValue, out result)) @@ -175,8 +184,13 @@ static bool TryParse(IEnumerable headerValues, ref bool hasValue, out i return ParseStringIEnumerable(headerValues); // IEnumerable version (different method to avoid try/finally in the caller) - static string? ParseStringIEnumerable(IEnumerable headerValues) + static string? ParseStringIEnumerable(IEnumerable? headerValues) { + if (headerValues is null) + { + return null; + } + foreach (string? headerValue in headerValues) { if (!string.IsNullOrEmpty(headerValue)) @@ -211,8 +225,13 @@ static bool TryParse(IEnumerable headerValues, ref bool hasValue, out i return ParseStringIEnumerable(headerValues); // IEnumerable version (different method to avoid try/finally in the caller) - static string? ParseStringIEnumerable(IEnumerable headerValues) + static string? ParseStringIEnumerable(IEnumerable? headerValues) { + if (headerValues is null) + { + return null; + } + foreach (string? headerValue in headerValues) { if (!string.IsNullOrEmpty(headerValue)) diff --git a/tracer/src/Datadog.Trace/SpanContext.cs b/tracer/src/Datadog.Trace/SpanContext.cs index 07dbf526c401..4873389bcbc0 100644 --- a/tracer/src/Datadog.Trace/SpanContext.cs +++ b/tracer/src/Datadog.Trace/SpanContext.cs @@ -48,6 +48,11 @@ public partial class SpanContext : ISpanContext, IReadOnlyDictionary public static readonly ISpanContext None = new ReadOnlySpanContext(traceId: Trace.TraceId.Zero, spanId: 0, serviceName: null); + /// + /// A SpanContext with all fields set to zero or empty values, for span pointers. + /// + public static readonly SpanContext Zero = new(); + private string _rawTraceId; private string _rawSpanId; private string _origin; @@ -173,6 +178,13 @@ private SpanContext(TraceId traceId, string serviceName) } } + // Constructor for creating an empty span context. + private SpanContext() + { + TraceId128 = Trace.TraceId.Zero; // Directly set zero without the random generation + SpanId = 0; + } + /// /// Gets the parent context. /// diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/Count.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/Count.cs index 78819e10b067..9f9a84b7e7de 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/Count.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/Count.cs @@ -211,7 +211,7 @@ internal enum Count /// /// Counts the number of times a rule type has a match. Note that this can be inferred through the events sent to the backend. /// - [TelemetryMetric("rasp.rule.match", isCommon: true, NS.ASM)] RaspRuleMatch, + [TelemetryMetric("rasp.rule.match", isCommon: true, NS.ASM)] RaspRuleMatch, /// /// Counts the number of times a timeout was hit when evaluating a specific rule type. diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs index 99ac628c0e09..3d60efb3dbb8 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs @@ -298,11 +298,31 @@ public enum WafStatus [EnumExtensions] public enum RaspRuleType { - [Description("waf_version;rule_type:lfi")] Lfi = 0, - [Description("waf_version;rule_type:ssrf")] Ssrf = 1, - [Description("waf_version;rule_type:sql_injection")] SQlI = 2, - [Description("waf_version;rule_type:command_injection;rule_variant:shell")] CommandInjectionShell = 3, - [Description("waf_version;rule_type:command_injection;rule_variant:exec")] CommandInjectionExec = 4, + [Description("waf_version;event_rules_version;rule_type:lfi")] Lfi = 0, + [Description("waf_version;event_rules_version;rule_type:ssrf")] Ssrf = 1, + [Description("waf_version;event_rules_version;rule_type:sql_injection")] SQlI = 2, + [Description("waf_version;event_rules_version;rule_type:command_injection;rule_variant:shell")] CommandInjectionShell = 3, + [Description("waf_version;event_rules_version;rule_type:command_injection;rule_variant:exec")] CommandInjectionExec = 4, + } + + [EnumExtensions] + public enum RaspRuleTypeMatch + { + [Description("waf_version;event_rules_version;block:success;rule_type:lfi")] LfiSuccess = 0, + [Description("waf_version;event_rules_version;block:success;rule_type:ssrf")] SsrfSuccess = 1, + [Description("waf_version;event_rules_version;block:success;rule_type:sql_injection")] SQlISuccess = 2, + [Description("waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:shell")] CommandInjectionShellSuccess = 3, + [Description("waf_version;event_rules_version;block:success;rule_type:command_injection;rule_variant:exec")] CommandInjectionExecSuccess = 4, + [Description("waf_version;event_rules_version;block:failure;rule_type:lfi")] LfiFailure = 5, + [Description("waf_version;event_rules_version;block:failure;rule_type:ssrf")] SsrfFailure = 6, + [Description("waf_version;event_rules_version;block:failure;rule_type:sql_injection")] SQlIFailure = 7, + [Description("waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:shell")] CommandInjectionShellFailure = 8, + [Description("waf_version;event_rules_version;block:failure;rule_type:command_injection;rule_variant:exec")] CommandInjectionExecFailure = 9, + [Description("waf_version;event_rules_version;block:irrelevant;rule_type:lfi")] LfiIrrelevant = 10, + [Description("waf_version;event_rules_version;block:irrelevant;rule_type:ssrf")] SsrfIrrelevant = 11, + [Description("waf_version;event_rules_version;block:irrelevant;rule_type:sql_injection")] SQlIIrrelevant = 12, + [Description("waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:shell")] CommandInjectionShellIrrelevant = 13, + [Description("waf_version;event_rules_version;block:irrelevant;rule_type:command_injection;rule_variant:exec")] CommandInjectionExecIrrelevant = 14, } public enum TruncationReason diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/AWS/Shared/SpanPointersTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/AWS/Shared/SpanPointersTests.cs new file mode 100644 index 000000000000..0d8dac3cbf5f --- /dev/null +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/AutoInstrumentation/AWS/Shared/SpanPointersTests.cs @@ -0,0 +1,93 @@ +// +// 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.ClrProfiler.AutoInstrumentation.AWS.S3; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Shared; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using FluentAssertions; +using Moq; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests.AutoInstrumentation.AWS.Shared; + +public class SpanPointersTests +{ + [Theory] + [InlineData("some-bucket-a", "some-key.data", "ab12ef34", "some-bucket-a|some-key.data|ab12ef34")] + [InlineData("some-bucket-b", "some-key.data", "\"ab12ef34\"", "some-bucket-b|some-key.data|ab12ef34")] // eTag should be trimmed + [InlineData("some-bucket-c", "some-key.你好", "é🐶", "some-bucket-c|some-key.你好|é🐶")] // Unicode + public void ConcatenateComponents(string bucket, string key, string eTag, string expectedHash) + { + var components = SpanPointers.ConcatenateComponents(bucket, key, eTag); + + components.Should().Be(expectedHash); + } + + [Theory] + [InlineData("some-bucket", "some-key.data", "ab12ef34", "e721375466d4116ab551213fdea08413")] + [InlineData("some-bucket", "some-key.data", "\"ab12ef34\"", "e721375466d4116ab551213fdea08413")] // eTag should be trimmed + [InlineData("some-bucket", "some-key.你好", "ab12ef34", "d1333a04b9928ab462b5c6cadfa401f4")] // Unicode + [InlineData("some-bucket", "some-key.data", "ab12ef34-5", "2b90dffc37ebc7bc610152c3dc72af9f")] + public void GeneratePointerHash_ShouldGenerateValidHash(string bucket, string key, string eTag, string expectedHash) + { + var components = SpanPointers.ConcatenateComponents(bucket, key, eTag); + var hash = SpanPointers.GeneratePointerHash(components); + + hash.Should().Be(expectedHash); + } + + [Fact] + public void AddS3SpanPointer_ShouldAddCorrectSpanLink() + { + var tracer = GetTracer(); + var scope = AwsS3Common.CreateScope(tracer, "PutObject", out _); + var span = scope!.Span; + const string bucket = "test-bucket"; + const string key = "test-key"; + const string eTag = "\"test-etag\""; + SpanPointers.AddS3SpanPointer(span, bucket, key, eTag); + + span.SpanLinks.Should().ContainSingle("Should have exactly one span link"); + var link = span.SpanLinks[0]; + + link.Context.Should().Equal(SpanContext.Zero); + + // we can use Contain(key, value) because Attributes is "dictionary-like" + link.Attributes.Should().Contain("ptr.kind", "aws.s3.object"); + link.Attributes.Should().Contain("ptr.dir", "d"); + link.Attributes.Should().Contain("link.kind", "span-pointer"); + link.Attributes.Should().Contain("ptr.hash", "b7b8ca30a2b7a33d8412d7ca62bcad36"); + } + + [Fact] + public void AddS3SpanPointer_ShouldSkipMissingEtag() + { + var tracer = GetTracer(); + var scope = AwsS3Common.CreateScope(tracer, "PutObject", out _); + var span = scope!.Span; + const string bucket = "test-bucket"; + const string key = "test-key"; + const string? eTag = null; + SpanPointers.AddS3SpanPointer(span, bucket, key, eTag); + + span.SpanLinks.Should().BeNull(); + } + + private static Tracer GetTracer() + { + var collection = new NameValueCollection { { ConfigurationKeys.MetadataSchemaVersion, "v1" } }; + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new TracerSettings(source); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + return new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + } +} diff --git a/tracer/test/Datadog.Trace.Security.Unit.Tests/SecurityCoordinatorTests.cs b/tracer/test/Datadog.Trace.Security.Unit.Tests/SecurityCoordinatorTests.cs index cb584537e0d6..8522fcea9e1f 100644 --- a/tracer/test/Datadog.Trace.Security.Unit.Tests/SecurityCoordinatorTests.cs +++ b/tracer/test/Datadog.Trace.Security.Unit.Tests/SecurityCoordinatorTests.cs @@ -155,7 +155,7 @@ public void GivenSecurityCoordinatorInstanceWithResponseHeadersWritten_WheBlock_ try { - securityCoordinator?.ReportAndBlock(resultMock.Object); + securityCoordinator?.ReportAndBlock(resultMock.Object, () => Console.WriteLine("Telemetry reported")); Assert.Fail("Expected BlockException"); } catch (BlockException) diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs index 2bda0475d86d..ce00248960a4 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs @@ -22,7 +22,9 @@ public class ConfigurationSourceTests : IDisposable { private static readonly Dictionary TagsK1V1K2V2 = new() { { "k1", "v1" }, { "k2", "v2" } }; private static readonly Dictionary TagsK2V2 = new() { { "k2", "v2" } }; + private static readonly Dictionary TagsKey1Key2 = new() { { "key1", string.Empty }, { "key2", string.Empty } }; private static readonly Dictionary TagsWithColonsInValue = new() { { "k1", "v1" }, { "k2", "v2:with:colons" }, { "trailing", "colon:good:" } }; + private static readonly Dictionary TagsWithSpacesInValue = new() { { "key", "val" }, { "aKey", "aVal bKey:bVal cKey:" } }; private static readonly Dictionary HeaderTagsWithOptionalMappings = new() { { "header1", "tag1" }, { "header2", "Content-Type" }, { "header3", "Content-Type" }, { "header4", "C!!!ont_____ent----tYp!/!e" }, { "validheaderwithoutcolon", string.Empty } }; private static readonly Dictionary HeaderTagsWithDots = new() { { "header3", "my.header.with.dot" }, { "my.new.header.with.dot", string.Empty } }; private static readonly Dictionary HeaderTagsSameTag = new() { { "header1", "tag1" }, { "header2", "tag1" } }; @@ -34,6 +36,8 @@ public ConfigurationSourceTests() _envVars = GetTestData() .Select(allArgs => allArgs.Key) .Concat(GetGlobalTestData().Select(allArgs => allArgs.Key)) + .Concat(GetBreakingChangeTestData().Select(allArgs => allArgs.Key)) + .Concat([ConfigurationKeys.ExperimentalFeaturesEnabled]) .Distinct() .ToDictionary(key => key, key => Environment.GetEnvironmentVariable(key)); } @@ -89,6 +93,15 @@ public ConfigurationSourceTests() yield return (s => s.TraceId128BitLoggingEnabled, false); } + public static IEnumerable<(string Key, string Value, Func Getter, object Expected)> GetBreakingChangeTestData() + { + // Test edge cases that expose various discrepenacies with the Agent DD_TAGS parsing algorithm that we would like to support + yield return (ConfigurationKeys.GlobalTags, "k1:v1 k2:v2", s => s.GlobalTags, TagsK1V1K2V2); + yield return (ConfigurationKeys.GlobalTags, "key1,key2", s => s.GlobalTags, TagsKey1Key2); + yield return (ConfigurationKeys.GlobalTags, "key1,key2:", s => s.GlobalTags, TagsKey1Key2); + yield return (ConfigurationKeys.GlobalTags, "key :val, aKey : aVal bKey:bVal cKey:", s => s.GlobalTags, TagsWithSpacesInValue); + } + public static IEnumerable<(string Key, string Value, Func Getter, object Expected)> GetTestData() { yield return (ConfigurationKeys.TraceEnabled, "true", s => s.TraceEnabled, true); @@ -112,6 +125,12 @@ public ConfigurationSourceTests() yield return (ConfigurationKeys.GlobalTags, "k1:v1,k1:v2", s => s.GlobalTags.Count, 1); yield return (ConfigurationKeys.GlobalTags, "k1:v1, k2:v2:with:colons, :leading:colon:bad, trailing:colon:good:", s => s.GlobalTags, TagsWithColonsInValue); + // Test edge cases that expose various discrepenacies with the Agent DD_TAGS parsing algorithm that we would like to support + yield return (ConfigurationKeys.GlobalTags, "k1:v1 k2:v2", s => s.GlobalTags, new Dictionary() { { "k1", "v1 k2:v2" } }); + yield return (ConfigurationKeys.GlobalTags, "key1,key2", s => s.GlobalTags.Count, 0); + yield return (ConfigurationKeys.GlobalTags, "key1,key2:", s => s.GlobalTags.Count, 0); + yield return (ConfigurationKeys.GlobalTags, "key :val, aKey : aVal bKey:bVal cKey:", s => s.GlobalTags, TagsWithSpacesInValue); + #pragma warning disable 618 // App Analytics is deprecated but still supported yield return (ConfigurationKeys.GlobalAnalyticsEnabled, "true", s => s.AnalyticsEnabled, true); yield return (ConfigurationKeys.GlobalAnalyticsEnabled, "false", s => s.AnalyticsEnabled, false); @@ -166,73 +185,22 @@ public void DefaultSetting() } [Fact] - public void NameValueConfigurationSource() - { - foreach (var (key, value, settingGetter, expectedValue) in GetTestData()) - { - var collection = new NameValueCollection { { key, value } }; - IConfigurationSource source = new NameValueConfigurationSource(collection); - var settings = new TracerSettings(source); - object actualValue = settingGetter(settings); - // Assert.Equal(expectedValue, actualValue); - actualValue.Should().BeEquivalentTo(expectedValue); - } - } + public void NameValueConfigurationSource() => AssertNameValueConfigurationSource(GetTestData()); [Fact] - public void EnvironmentConfigurationSource() - { - foreach (var (key, value, settingGetter, expectedValue) in GetTestData()) - { - TracerSettings settings; - - if (key == "DD_SERVICE_NAME") - { - // We need to ensure DD_SERVICE is empty. - Environment.SetEnvironmentVariable(ConfigurationKeys.ServiceName, null, EnvironmentVariableTarget.Process); - settings = GetTracerSettings(key, value); - } - else if (key == ConfigurationKeys.AgentHost || key == ConfigurationKeys.AgentPort) - { - // We need to ensure all the agent URLs are empty. - Environment.SetEnvironmentVariable(ConfigurationKeys.AgentHost, null, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable(ConfigurationKeys.AgentPort, null, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable(ConfigurationKeys.AgentUri, null, EnvironmentVariableTarget.Process); + public void BreakingChanges_NameValueConfigurationSource() => AssertNameValueConfigurationSource(GetBreakingChangeTestData(), setExperimentalFeaturesEnabled: "all"); - settings = GetTracerSettings(key, value); - } - else - { - settings = GetTracerSettings(key, value); - } - - var actualValue = settingGetter(settings); - actualValue.Should().BeEquivalentTo(expectedValue, $"{key} should have correct value"); - ResetEnvironment(); - } + [Fact] + public void EnvironmentConfigurationSource() => AssertEnvironmentConfigurationSource(GetTestData()); - static TracerSettings GetTracerSettings(string key, string value) - { - Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process); - IConfigurationSource source = new EnvironmentConfigurationSource(); - return new TracerSettings(source); - } - } + [Fact] + public void BreakingChanges_EnvironmentConfigurationSource() => AssertEnvironmentConfigurationSource(GetBreakingChangeTestData(), setExperimentalFeaturesEnabled: "all"); [Fact] - public void JsonConfigurationSource() - { - foreach (var (key, value, settingGetter, expectedValue) in GetTestData()) - { - var config = new Dictionary { [key] = value }; - string json = JsonConvert.SerializeObject(config); - IConfigurationSource source = new JsonConfigurationSource(json); - var settings = new TracerSettings(source); + public void JsonConfigurationSource() => AssertJsonConfigurationSource(GetTestData()); - object actualValue = settingGetter(settings); - Assert.Equal(expectedValue, actualValue); - } - } + [Fact] + public void BreakingChanges_JsonConfigurationSource() => AssertJsonConfigurationSource(GetBreakingChangeTestData(), setExperimentalFeaturesEnabled: "all"); [Fact] public void GlobalDefaultSetting() @@ -335,6 +303,75 @@ public void TestHeaderTagsNormalization(bool headerTagsNormalizationFixEnabled, Assert.Equal(expectedValue, settings.HeaderTags); } + private void AssertNameValueConfigurationSource(IEnumerable<(string Key, string Value, Func Getter, object Expected)> testData, string setExperimentalFeaturesEnabled = "") + { + foreach (var (key, value, settingGetter, expectedValue) in testData) + { + var collection = new NameValueCollection { { key, value } }; + collection.Add(ConfigurationKeys.ExperimentalFeaturesEnabled, setExperimentalFeaturesEnabled); + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new TracerSettings(source); + object actualValue = settingGetter(settings); + // Assert.Equal(expectedValue, actualValue); + actualValue.Should().BeEquivalentTo(expectedValue); + } + } + + private void AssertEnvironmentConfigurationSource(IEnumerable<(string Key, string Value, Func Getter, object Expected)> testData, string setExperimentalFeaturesEnabled = "") + { + foreach (var (key, value, settingGetter, expectedValue) in testData) + { + TracerSettings settings; + + if (key == "DD_SERVICE_NAME") + { + // We need to ensure DD_SERVICE is empty. + Environment.SetEnvironmentVariable(ConfigurationKeys.ServiceName, null, EnvironmentVariableTarget.Process); + settings = GetTracerSettings(key, value, setExperimentalFeaturesEnabled); + } + else if (key == ConfigurationKeys.AgentHost || key == ConfigurationKeys.AgentPort) + { + // We need to ensure all the agent URLs are empty. + Environment.SetEnvironmentVariable(ConfigurationKeys.AgentHost, null, EnvironmentVariableTarget.Process); + Environment.SetEnvironmentVariable(ConfigurationKeys.AgentPort, null, EnvironmentVariableTarget.Process); + Environment.SetEnvironmentVariable(ConfigurationKeys.AgentUri, null, EnvironmentVariableTarget.Process); + + settings = GetTracerSettings(key, value, setExperimentalFeaturesEnabled); + } + else + { + settings = GetTracerSettings(key, value, setExperimentalFeaturesEnabled); + } + + var actualValue = settingGetter(settings); + actualValue.Should().BeEquivalentTo(expectedValue, $"{key} should have correct value"); + ResetEnvironment(); + } + + static TracerSettings GetTracerSettings(string key, string value, string setExperimentalFeaturesEnabled) + { + Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process); + Environment.SetEnvironmentVariable(ConfigurationKeys.ExperimentalFeaturesEnabled, setExperimentalFeaturesEnabled, EnvironmentVariableTarget.Process); + IConfigurationSource source = new EnvironmentConfigurationSource(); + return new TracerSettings(source); + } + } + + private void AssertJsonConfigurationSource(IEnumerable<(string Key, string Value, Func Getter, object Expected)> testData, string setExperimentalFeaturesEnabled = "") + { + foreach (var (key, value, settingGetter, expectedValue) in testData) + { + var config = new Dictionary { [key] = value }; + config.Add(ConfigurationKeys.ExperimentalFeaturesEnabled, setExperimentalFeaturesEnabled); + string json = JsonConvert.SerializeObject(config); + IConfigurationSource source = new JsonConfigurationSource(json); + var settings = new TracerSettings(source); + + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + } + private void ResetEnvironment() { foreach (var envVar in _envVars) diff --git a/tracer/test/Datadog.Trace.Tests/Propagators/ParseUtilityTests.cs b/tracer/test/Datadog.Trace.Tests/Propagators/ParseUtilityTests.cs index be7ba09b5766..e4dac05ee80c 100644 --- a/tracer/test/Datadog.Trace.Tests/Propagators/ParseUtilityTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Propagators/ParseUtilityTests.cs @@ -14,86 +14,96 @@ namespace Datadog.Trace.Tests.Propagators { public class ParseUtilityTests { + public static TheoryData, ulong?> UInt64 + => new() + { + { new[] { "42" }, 42 }, + { new[] { "4x" }, null }, + { new[] { "4x", "42" }, 42 }, // return first valid value + { new[] { string.Empty }, null }, + { new[] { (string)null }, null }, + { new List { "42" }, 42 }, + { new List { "4x" }, null }, + { new List { string.Empty }, null }, + { new List { null }, null }, + { null, null }, // null collection returns null + }; + + public static TheoryData, int?> Int32 + => new() + { + { new[] { "42" }, 42 }, + { new[] { "4x" }, null }, + { new[] { "4x", "42" }, 42 }, // return first valid value + { new[] { string.Empty }, null }, + { new[] { (string)null }, null }, + { new List { "42" }, 42 }, + { new List { "4x" }, null }, + { new List { string.Empty }, null }, + { new List { null }, null }, + { null, null }, // null collection returns null + }; + + public static TheoryData, string> String + => new() + { + { new[] { "42" }, "42" }, + { new[] { "4x" }, "4x" }, + { new[] { "4x", "42" }, "4x" }, // return first valid value + { new[] { string.Empty }, null }, // null or empty returns null + { new[] { (string)null }, null }, // null or empty returns null + { new List { "42" }, "42" }, + { new List { "4x" }, "4x" }, + { new List { string.Empty }, null }, // null or empty returns null + { new List { null }, null }, // null or empty returns null + { null, null }, // null collection returns null + }; + [Theory] - [InlineData("42", 42UL)] - [InlineData("4x", null)] - public void ParseUInt64Test(string actual, object expected) + [MemberData(nameof(UInt64))] + public void ParseUInt64Test(IEnumerable values, ulong? expected) { - var actualResult = ParseUtility.ParseUInt64( - (object)null, - new FuncGetter((carrier, name) => new[] { actual }), - string.Empty); - - actualResult.Should().Be((ulong?)expected); - - actualResult = ParseUtility.ParseUInt64( + var result = ParseUtility.ParseUInt64( (object)null, - new FuncGetter((carrier, name) => new List { actual }), + new FuncGetter((_, _) => values), string.Empty); - actualResult.Should().Be((ulong?)expected); + result.Should().Be(expected); } [Theory] - [InlineData("42", 42)] - [InlineData("4x", null)] - public void ParseInt32Test(string actual, object expected) + [MemberData(nameof(Int32))] + public void ParseInt32Test(IEnumerable values, int? expected) { - var actualResult = ParseUtility.ParseInt32( + var result = ParseUtility.ParseInt32( (object)null, - new FuncGetter((carrier, name) => new[] { actual }), + new FuncGetter((_, _) => values), string.Empty); - actualResult.Should().Be((int?)expected); - - actualResult = ParseUtility.ParseInt32( - (object)null, - new FuncGetter((carrier, name) => new List { actual }), - string.Empty); - - actualResult.Should().Be((int?)expected); + result.Should().Be(expected); } [Theory] - [InlineData("42", "42")] - [InlineData("4x", "4x")] - [InlineData("", null)] - [InlineData(null, null)] - public void ParseString(string actual, string expected) + [MemberData(nameof(String))] + public void ParseStringTest(IEnumerable values, string expected) { - var actualResult = ParseUtility.ParseString( + var result = ParseUtility.ParseString( (object)null, - new FuncGetter((carrier, name) => new[] { actual }), + new FuncGetter((_, _) => values), string.Empty); - actualResult.Should().Be(expected); - - actualResult = ParseUtility.ParseString( - (object)null, - new FuncGetter((carrier, name) => new List { actual }), - string.Empty); - - actualResult.Should().Be(expected); + result.Should().Be(expected); } [Theory] - [InlineData("42", "42")] - [InlineData("4x", "4x")] - [InlineData("", null)] - [InlineData(null, null)] - public void ParseStringWithHeaders(string actual, string expected) + [MemberData(nameof(String))] + public void ParseStringWithHeaders(IEnumerable values, string expected) { - var actualResult = ParseUtility.ParseString( - new HeaderStruct(() => new[] { actual }), - string.Empty); - - actualResult.Should().Be(expected); - - actualResult = ParseUtility.ParseString( - new HeaderStruct(() => new List { actual }), + var result = ParseUtility.ParseString( + new HeaderStruct(() => values), string.Empty); - actualResult.Should().Be(expected); + result.Should().Be(expected); } private readonly struct FuncGetter : ICarrierGetter diff --git a/tracer/test/Datadog.Trace.Tests/Snapshots/PublicApiTests.Datadog.Trace.AssemblyReferencesHaveNotChanged.netcoreapp3.1.verified.txt b/tracer/test/Datadog.Trace.Tests/Snapshots/PublicApiTests.Datadog.Trace.AssemblyReferencesHaveNotChanged.netcoreapp3.1.verified.txt index a0a9ee5f90bd..8232d4f20a02 100644 --- a/tracer/test/Datadog.Trace.Tests/Snapshots/PublicApiTests.Datadog.Trace.AssemblyReferencesHaveNotChanged.netcoreapp3.1.verified.txt +++ b/tracer/test/Datadog.Trace.Tests/Snapshots/PublicApiTests.Datadog.Trace.AssemblyReferencesHaveNotChanged.netcoreapp3.1.verified.txt @@ -7,6 +7,7 @@ Microsoft.AspNetCore.Routing.Abstractions, Version=2.0.0.0, Culture=neutral, Pub Microsoft.Extensions.Primitives, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 Microsoft.Net.Http.Headers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60 Microsoft.Win32.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a +System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 System.Collections, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a System.Collections.Concurrent, Version=4.0.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a System.Collections.NonGeneric, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/tracer/test/Datadog.Trace.Tests/Telemetry/Collectors/MetricsTelemetryCollectorTests.cs b/tracer/test/Datadog.Trace.Tests/Telemetry/Collectors/MetricsTelemetryCollectorTests.cs index efe2d4ad1bb4..c7d60c2678c3 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/Collectors/MetricsTelemetryCollectorTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/Collectors/MetricsTelemetryCollectorTests.cs @@ -107,7 +107,7 @@ static void IncrementOpenTelemetryConfigMetrics(MetricsTelemetryCollector collec collector.RecordCountWafInit(MetricTags.WafStatus.Success, 4); collector.RecordCountWafRequests(MetricTags.WafAnalysis.Normal, 5); collector.RecordCountRaspRuleEval(MetricTags.RaspRuleType.Lfi, 5); - collector.RecordCountRaspRuleMatch(MetricTags.RaspRuleType.Lfi, 3); + collector.RecordCountRaspRuleMatch(MetricTags.RaspRuleTypeMatch.LfiSuccess, 3); collector.RecordCountRaspTimeout(MetricTags.RaspRuleType.Lfi, 2); collector.RecordGaugeStatsBuckets(234); collector.RecordDistributionSharedInitTime(MetricTags.InitializationComponent.Total, 23); @@ -261,7 +261,7 @@ static void IncrementOpenTelemetryConfigMetrics(MetricsTelemetryCollector collec Metric = Count.RaspRuleEval.GetName(), Points = new[] { new { Value = 5 } }, Type = TelemetryMetricType.Count, - Tags = new[] { expectedWafTag, "rule_type:lfi" }, + Tags = new[] { expectedWafTag, expectedRulesetTag, "rule_type:lfi" }, Common = true, Namespace = NS.ASM, }, @@ -270,7 +270,7 @@ static void IncrementOpenTelemetryConfigMetrics(MetricsTelemetryCollector collec Metric = Count.RaspRuleMatch.GetName(), Points = new[] { new { Value = 3 } }, Type = TelemetryMetricType.Count, - Tags = new[] { expectedWafTag, "rule_type:lfi" }, + Tags = new[] { expectedWafTag, expectedRulesetTag, "block:success", "rule_type:lfi" }, Common = true, Namespace = NS.ASM, }, @@ -279,7 +279,7 @@ static void IncrementOpenTelemetryConfigMetrics(MetricsTelemetryCollector collec Metric = Count.RaspTimeout.GetName(), Points = new[] { new { Value = 2 } }, Type = TelemetryMetricType.Count, - Tags = new[] { expectedWafTag, "rule_type:lfi" }, + Tags = new[] { expectedWafTag, expectedRulesetTag, "rule_type:lfi" }, Common = true, Namespace = NS.ASM, }, diff --git a/tracer/test/Datadog.Trace.Tests/Telemetry/Metrics/common_metrics.json b/tracer/test/Datadog.Trace.Tests/Telemetry/Metrics/common_metrics.json index 8c5cb75ff461..33f351f54cac 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/Metrics/common_metrics.json +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/Metrics/common_metrics.json @@ -730,6 +730,7 @@ "rasp.rule.eval": { "tags": [ "waf_version", + "event_rules_version", "rule_type", "rule_variant" ], @@ -742,8 +743,10 @@ "rasp.rule.match": { "tags": [ "waf_version", + "event_rules_version", "rule_type", - "rule_variant" + "rule_variant", + "block" ], "metric_type": "count", "data_type": "matches", @@ -754,6 +757,7 @@ "rasp.timeout": { "tags": [ "waf_version", + "event_rules_version", "rule_type", "rule_variant" ], 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 a7e50fd3c7bc..3a8c68243711 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/config_norm_rules.json @@ -309,6 +309,7 @@ "dbm_propagation_mode": "dbm_propagation_mode", "trace.remove_root_span_laravel_queue": "trace_remove_root_span_laravel_queue_enabled", "trace.remove_autoinstrumentation_orphans": "trace_remove_auto_instrumentation_orphans_enabled", + "DD_TRACE_AWS_ADD_SPAN_POINTERS": "trace_aws_add_span_pointers", "DD_TRACE_CONFIG_FILE": "trace_config_file", "DD_DOTNET_TRACER_CONFIG_FILE": "trace_config_file", "DD_ENV": "env", diff --git a/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV0.verified.txt b/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV0.verified.txt index 5363da441c20..b26a0069de3f 100644 --- a/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV0.verified.txt +++ b/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV0.verified.txt @@ -74,7 +74,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_4, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -87,7 +97,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: GetObject, - aws.requestId: Guid_4, + aws.requestId: Guid_5, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -117,7 +127,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CopyObject, - aws.requestId: Guid_5, + aws.requestId: Guid_6, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -134,7 +144,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_7, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -147,7 +167,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_6, + aws.requestId: Guid_8, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -176,7 +196,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_7, + aws.requestId: Guid_9, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -206,7 +226,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObjects, - aws.requestId: Guid_8, + aws.requestId: Guid_10, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -235,7 +255,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: InitiateMultipartUpload, - aws.requestId: Guid_9, + aws.requestId: Guid_11, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -265,7 +285,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_10, + aws.requestId: Guid_12, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -295,7 +315,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_11, + aws.requestId: Guid_13, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -325,7 +345,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CompleteMultipartUpload, - aws.requestId: Guid_12, + aws.requestId: Guid_14, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -342,7 +362,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_15, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -355,7 +385,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListBuckets, - aws.requestId: Guid_13, + aws.requestId: Guid_16, aws.service: S3, aws_service: S3, component: aws-sdk, @@ -383,7 +413,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_14, + aws.requestId: Guid_17, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -412,7 +442,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_15, + aws.requestId: Guid_18, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -442,7 +472,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteBucket, - aws.requestId: Guid_16, + aws.requestId: Guid_19, aws.service: S3, aws_service: S3, bucketname: my-bucket, diff --git a/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV1.verified.txt b/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV1.verified.txt index ec4e780ec8f7..4fc3635d9aae 100644 --- a/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV1.verified.txt +++ b/tracer/test/snapshots/AwsS3Tests.NetCore.SchemaV1.verified.txt @@ -68,7 +68,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_4, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -81,7 +91,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: GetObject, - aws.requestId: Guid_4, + aws.requestId: Guid_5, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -108,7 +118,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CopyObject, - aws.requestId: Guid_5, + aws.requestId: Guid_6, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -122,7 +132,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_7, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -135,7 +155,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_6, + aws.requestId: Guid_8, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -161,7 +181,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_7, + aws.requestId: Guid_9, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -188,7 +208,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObjects, - aws.requestId: Guid_8, + aws.requestId: Guid_10, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -214,7 +234,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: InitiateMultipartUpload, - aws.requestId: Guid_9, + aws.requestId: Guid_11, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -241,7 +261,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_10, + aws.requestId: Guid_12, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -268,7 +288,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_11, + aws.requestId: Guid_13, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -295,7 +315,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CompleteMultipartUpload, - aws.requestId: Guid_12, + aws.requestId: Guid_14, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -309,7 +329,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_15, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -322,7 +352,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListBuckets, - aws.requestId: Guid_13, + aws.requestId: Guid_16, aws.service: S3, aws_service: S3, component: aws-sdk, @@ -345,7 +375,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_14, + aws.requestId: Guid_17, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -371,7 +401,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_15, + aws.requestId: Guid_18, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -398,7 +428,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteBucket, - aws.requestId: Guid_16, + aws.requestId: Guid_19, aws.service: S3, aws_service: S3, bucketname: my-bucket, diff --git a/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV0.verified.txt b/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV0.verified.txt index 8e6d2975eba6..25ed6efea0c0 100644 --- a/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV0.verified.txt +++ b/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV0.verified.txt @@ -74,7 +74,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_4, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -87,7 +97,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: GetObject, - aws.requestId: Guid_4, + aws.requestId: Guid_5, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -117,7 +127,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CopyObject, - aws.requestId: Guid_5, + aws.requestId: Guid_6, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -134,7 +144,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_7, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -147,7 +167,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_6, + aws.requestId: Guid_8, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -176,7 +196,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_7, + aws.requestId: Guid_9, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -206,7 +226,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObjects, - aws.requestId: Guid_8, + aws.requestId: Guid_10, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -235,7 +255,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: InitiateMultipartUpload, - aws.requestId: Guid_9, + aws.requestId: Guid_11, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -265,7 +285,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_10, + aws.requestId: Guid_12, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -295,7 +315,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_11, + aws.requestId: Guid_13, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -325,7 +345,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CompleteMultipartUpload, - aws.requestId: Guid_12, + aws.requestId: Guid_14, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -342,7 +362,17 @@ }, Metrics: { _dd.top_level: 1.0 - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_15, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -355,7 +385,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListBuckets, - aws.requestId: Guid_13, + aws.requestId: Guid_16, aws.service: S3, aws_service: S3, component: aws-sdk, @@ -383,7 +413,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_14, + aws.requestId: Guid_17, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -412,7 +442,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_15, + aws.requestId: Guid_18, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -442,7 +472,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteBucket, - aws.requestId: Guid_16, + aws.requestId: Guid_19, aws.service: S3, aws_service: S3, bucketname: my-bucket, diff --git a/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV1.verified.txt b/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV1.verified.txt index 4fbf14ee66bc..b9b9cfd94710 100644 --- a/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV1.verified.txt +++ b/tracer/test/snapshots/AwsS3Tests.NetFramework.SchemaV1.verified.txt @@ -68,7 +68,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_4, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -81,7 +91,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: GetObject, - aws.requestId: Guid_4, + aws.requestId: Guid_5, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -108,7 +118,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CopyObject, - aws.requestId: Guid_5, + aws.requestId: Guid_6, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -122,7 +132,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_7, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -135,7 +155,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_6, + aws.requestId: Guid_8, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -161,7 +181,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_7, + aws.requestId: Guid_9, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -188,7 +208,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObjects, - aws.requestId: Guid_8, + aws.requestId: Guid_10, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -214,7 +234,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: InitiateMultipartUpload, - aws.requestId: Guid_9, + aws.requestId: Guid_11, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -241,7 +261,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_10, + aws.requestId: Guid_12, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -268,7 +288,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: UploadPart, - aws.requestId: Guid_11, + aws.requestId: Guid_13, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -295,7 +315,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: CompleteMultipartUpload, - aws.requestId: Guid_12, + aws.requestId: Guid_14, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -309,7 +329,17 @@ peer.service: my-bucket, span.kind: client, _dd.peer.service.source: my-bucket - } + }, + SpanLinks: [ + { + Attributes: { + link.kind: span-pointer, + ptr.dir: d, + ptr.hash: Guid_15, + ptr.kind: aws.s3.object + } + } + ] }, { TraceId: Id_1, @@ -322,7 +352,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListBuckets, - aws.requestId: Guid_13, + aws.requestId: Guid_16, aws.service: S3, aws_service: S3, component: aws-sdk, @@ -345,7 +375,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: ListObjectsV2, - aws.requestId: Guid_14, + aws.requestId: Guid_17, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -371,7 +401,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteObject, - aws.requestId: Guid_15, + aws.requestId: Guid_18, aws.service: S3, aws_service: S3, bucketname: my-bucket, @@ -398,7 +428,7 @@ Tags: { aws.agent: dotnet-aws-sdk, aws.operation: DeleteBucket, - aws.requestId: Guid_16, + aws.requestId: Guid_19, aws.service: S3, aws_service: S3, bucketname: my-bucket,