diff --git a/tracer/missing-nullability-files.csv b/tracer/missing-nullability-files.csv index 0e16a61fbc1e..776bc0495cd2 100644 --- a/tracer/missing-nullability-files.csv +++ b/tracer/missing-nullability-files.csv @@ -88,7 +88,7 @@ src/Datadog.Trace/Configuration/ConfigurationKeys.Iast.cs src/Datadog.Trace/Configuration/ConfigurationKeys.Logging.cs src/Datadog.Trace/Configuration/ConfigurationKeys.Rcm.cs src/Datadog.Trace/Configuration/DbmPropagationLevel.cs -src/Datadog.Trace/Configuration/DeprecationMessages.cs +src/Datadog.Trace/Configuration/DeprecationConstants.cs src/Datadog.Trace/Configuration/IDynamicConfigurationManager.cs src/Datadog.Trace/Configuration/IntegrationRegistry.cs src/Datadog.Trace/Configuration/TracerSettingsConstants.cs diff --git a/tracer/src/Datadog.Trace.Manual/Configuration/ImmutableTracerSettings.cs b/tracer/src/Datadog.Trace.Manual/Configuration/ImmutableTracerSettings.cs index 589abff97b72..4f8c7f7c0b75 100644 --- a/tracer/src/Datadog.Trace.Manual/Configuration/ImmutableTracerSettings.cs +++ b/tracer/src/Datadog.Trace.Manual/Configuration/ImmutableTracerSettings.cs @@ -131,7 +131,7 @@ public bool TraceEnabled /// /// #pragma warning restore CS1574 - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public bool AnalyticsEnabled { [Instrumented] diff --git a/tracer/src/Datadog.Trace.Manual/Configuration/TracerSettings.cs b/tracer/src/Datadog.Trace.Manual/Configuration/TracerSettings.cs index 7f7b6d535445..6fbf4c3a1aba 100644 --- a/tracer/src/Datadog.Trace.Manual/Configuration/TracerSettings.cs +++ b/tracer/src/Datadog.Trace.Manual/Configuration/TracerSettings.cs @@ -214,7 +214,7 @@ public string? ServiceVersion /// on some predetermined integrations. /// See the documentation for more details. /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public bool AnalyticsEnabled { [Instrumented] diff --git a/tracer/src/Datadog.Trace.Manual/Datadog.Trace.Manual.csproj b/tracer/src/Datadog.Trace.Manual/Datadog.Trace.Manual.csproj index 8d8b77aee590..215960943379 100644 --- a/tracer/src/Datadog.Trace.Manual/Datadog.Trace.Manual.csproj +++ b/tracer/src/Datadog.Trace.Manual/Datadog.Trace.Manual.csproj @@ -26,7 +26,8 @@ - + diff --git a/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigKeyAliasesSwitcherGenerator.cs b/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigKeyAliasesSwitcherGenerator.cs new file mode 100644 index 000000000000..f4ecf736bb57 --- /dev/null +++ b/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigKeyAliasesSwitcherGenerator.cs @@ -0,0 +1,341 @@ +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using Datadog.Trace.SourceGenerators.Configuration; +using Datadog.Trace.SourceGenerators.Helpers; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +/// +/// Source generator that reads supported-configurations.json and generates a switch case +/// for configuration key matching with alias support. +/// +[Generator] +public class ConfigKeyAliasesSwitcherGenerator : IIncrementalGenerator +{ + private const string SupportedConfigurationsFileName = "supported-configurations.json"; + private const string MainKeyParamName = "mainKey"; + private const string ClassName = "ConfigKeyAliasesSwitcher"; + + /// + public void Initialize(IncrementalGeneratorInitializationContext context) + { + // Get the supported-configurations.json file and parse only the aliases section + // We only track changes to the aliases section since that's what affects the generated code + var additionalText = context.AdditionalTextsProvider + .Where(static file => Path.GetFileName(file.Path).Equals(SupportedConfigurationsFileName, StringComparison.OrdinalIgnoreCase)) + .WithTrackingName(TrackingNames.ConfigurationKeysAdditionalText); + + var aliasSection = additionalText.Collect() + .Select(static (files, ct) => + { + if (files.Length == 0) + { + // No supported-configurations.json file found + return new Result( + string.Empty, + new EquatableArray( + [ + CreateDiagnosticInfo("DDSG0003", "Configuration file not found", $"The file '{SupportedConfigurationsFileName}' was not found. Make sure the supported-configurations.json file exists and is included as an AdditionalFile.", DiagnosticSeverity.Error) + ])); + } + + // Extract from the first (and should be only) file + return ExtractAliasesSection(files[0], ct); + }); + + var aliasesContent = aliasSection.Select(static (extractResult, ct) => + { + if (extractResult.Errors.Count > 0) + { + // Return the errors from extraction + return new Result(null!, extractResult.Errors); + } + + return ParseAliasesContent(extractResult.Value, ct); + }) + .WithTrackingName(TrackingNames.ConfigurationKeysParseConfiguration); + + // Always generate source code, even when there are errors + // This ensures compilation doesn't fail due to missing generated types + context.RegisterSourceOutput( + aliasesContent, + static (spc, result) => Execute(spc, result)); + } + + private static void Execute(SourceProductionContext context, Result result) + { + // Report any diagnostics first + foreach (var diagnostic in result.Errors) + { + context.ReportDiagnostic(Diagnostic.Create(diagnostic.Descriptor, diagnostic.Location?.ToLocation())); + } + + // Generate source code even if there are errors (use empty configuration as fallback) + var configurationAliases = result.Value ?? new ConfigurationAliases(new Dictionary()); + var compilationUnit = GenerateConfigurationKeyMatcher(configurationAliases); + var generatedSource = compilationUnit.NormalizeWhitespace().ToFullString(); + context.AddSource($"{ClassName}.g.cs", SourceText.From(generatedSource, Encoding.UTF8)); + } + + private static Result ExtractAliasesSection(AdditionalText file, CancellationToken cancellationToken) + { + try + { + var sourceText = file.GetText(cancellationToken); + if (sourceText is null) + { + return new Result( + string.Empty, + new EquatableArray( + [ + CreateDiagnosticInfo("DDSG0003", "Configuration file not found", $"The file '{file.Path}' could not be read. Make sure the supported-configurations.json file exists and is included as an AdditionalFile.", DiagnosticSeverity.Error) + ])); + } + + var jsonContent = sourceText.ToString(); + + // Extract only the aliases section from the JSON + var aliasesSection = JsonReader.ExtractJsonObjectSection(jsonContent, "aliases"); + return new Result(aliasesSection ?? string.Empty, default); + } + catch (Exception ex) + { + return new Result( + string.Empty, + new EquatableArray( + [ + CreateDiagnosticInfo("DDSG0004", "Configuration file read error", $"Failed to read configuration file '{file.Path}': {ex.Message}", DiagnosticSeverity.Error) + ])); + } + } + + private static Result ParseAliasesContent(string aliasesContent, CancellationToken cancellationToken) + { + try + { + if (string.IsNullOrEmpty(aliasesContent)) + { + // Empty aliases section is valid - just return empty configuration + return new Result(new ConfigurationAliases(new Dictionary()), default); + } + + cancellationToken.ThrowIfCancellationRequested(); + + // Parse only the aliases section + var aliases = JsonReader.ParseAliasesFromJson(aliasesContent); + var configurationData = new ConfigurationAliases(aliases); + + return new Result(configurationData, default); + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + return new Result( + null!, + new EquatableArray( + [ + CreateDiagnosticInfo("DDSG0002", "Aliases parsing error", $"Failed to parse aliases section: {ex.Message}") + ])); + } + } + + private static DiagnosticInfo CreateDiagnosticInfo(string id, string title, string message, DiagnosticSeverity severity = DiagnosticSeverity.Warning) + { + var descriptor = new DiagnosticDescriptor( + id, + title, + message, + "Configuration", + severity, + isEnabledByDefault: true); + + return new DiagnosticInfo(descriptor, Location.None); + } + + private static CompilationUnitSyntax GenerateConfigurationKeyMatcher(ConfigurationAliases configurationAliases) + { + var getAliasesMethod = GenerateGetAliasesMethod(configurationAliases); + + var classDeclaration = ClassDeclaration(ClassName) + .WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.PartialKeyword))) + .WithLeadingTrivia( + Comment("/// "), + Comment("/// Generated configuration key matcher that handles main keys and aliases."), + Comment("/// ")) + .WithMembers( + List( + [ + getAliasesMethod + ])); + + var namespaceDeclaration = FileScopedNamespaceDeclaration( + QualifiedName( + QualifiedName( + IdentifierName("Datadog"), + IdentifierName("Trace")), + IdentifierName("Configuration"))) + .WithMembers(SingletonList(classDeclaration)); + + return CompilationUnit() + .WithLeadingTrivia( + Comment("// "), + CarriageReturnLineFeed) + .WithUsings( + SingletonList( + UsingDirective(IdentifierName("System")))) + .WithMembers(SingletonList(namespaceDeclaration)); + } + + private static MethodDeclarationSyntax GenerateGetAliasesMethod(ConfigurationAliases configurationAliases) + { + var switchSections = new List(); + + // Add cases for keys that have aliases + foreach (var alias in configurationAliases.Aliases.OrderBy(a => a.Key)) + { + var mainKey = alias.Key; + var aliasKeys = alias.Value; + + var arrayElements = aliasKeys + .OrderBy(a => a) + .Select(aliasKey => LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(aliasKey))) + .Cast() + .ToArray(); + + var arrayCreation = ArrayCreationExpression( + ArrayType(PredefinedType(Token(SyntaxKind.StringKeyword))) + .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression()))))) + .WithInitializer(InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList(arrayElements))); + + var switchSection = SwitchSection() + .WithLabels( + SingletonList( + CaseSwitchLabel(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(mainKey))))) + .WithStatements(SingletonList(ReturnStatement(arrayCreation))); + switchSections.Add(switchSection); + } + + // Add default case + var defaultSection = SwitchSection() + .WithLabels(SingletonList(DefaultSwitchLabel())) + .WithStatements( + SingletonList( + ReturnStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("Array"), + GenericName("Empty") + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + PredefinedType(Token(SyntaxKind.StringKeyword)))))))))); + switchSections.Add(defaultSection); + + var switchStatement = SwitchStatement(IdentifierName(MainKeyParamName)) + .WithSections(List(switchSections)); + + return MethodDeclaration( + ArrayType(PredefinedType(Token(SyntaxKind.StringKeyword))) + .WithRankSpecifiers(SingletonList(ArrayRankSpecifier(SingletonSeparatedList(OmittedArraySizeExpression())))), + "GetAliases") + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier(MainKeyParamName)) + .WithType(PredefinedType(Token(SyntaxKind.StringKeyword)))))) + .WithLeadingTrivia( + Comment("/// "), + Comment("/// Gets all aliases for the given configuration key."), + Comment("/// "), + Comment($"/// The configuration key."), + Comment("/// An array of aliases for the key, or empty array if no aliases exist.")) + .WithBody(Block(switchStatement)); + } + + private sealed class ConfigurationAliases(Dictionary aliases) : IEquatable + { + public Dictionary Aliases { get; } = aliases; + + public bool Equals(ConfigurationAliases? other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + // Proper content comparison for change detection + if (Aliases.Count != other.Aliases.Count) + { + return false; + } + + foreach (var kvp in Aliases) + { + if (!other.Aliases.TryGetValue(kvp.Key, out var otherAliases)) + { + return false; + } + + if (kvp.Value.Length != otherAliases.Length) + { + return false; + } + + for (int i = 0; i < kvp.Value.Length; i++) + { + if (kvp.Value[i] != otherAliases[i]) + { + return false; + } + } + } + + return true; + } + + public override bool Equals(object? obj) + { + return ReferenceEquals(this, obj) || (obj is ConfigurationAliases other && Equals(other)); + } + + public override int GetHashCode() + { + var hash = new System.HashCode(); + hash.Add(Aliases.Count); + + // Include content in hash for proper change detection + foreach (var kvp in Aliases.OrderBy(x => x.Key)) + { + hash.Add(kvp.Key); + foreach (var alias in kvp.Value.OrderBy(x => x)) + { + hash.Add(alias); + } + } + + return hash.ToHashCode(); + } + } +} diff --git a/tracer/src/Datadog.Trace.SourceGenerators/Configuration/JsonReader.cs b/tracer/src/Datadog.Trace.SourceGenerators/Configuration/JsonReader.cs new file mode 100644 index 000000000000..22bc32852efc --- /dev/null +++ b/tracer/src/Datadog.Trace.SourceGenerators/Configuration/JsonReader.cs @@ -0,0 +1,198 @@ + // +// 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. +// + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.SourceGenerators.Configuration; + +/// +/// Json reader as we can't really use vendored libraries here, for framework compatibility reasons +/// +internal static class JsonReader +{ + internal static string ExtractJsonObjectSection(string json, string sectionName) + { + var searchPattern = $"\"{sectionName}\":"; + var startIndex = json.IndexOf(searchPattern, StringComparison.Ordinal); + if (startIndex == -1) + { + return string.Empty; + } + + // Move to the start of the object value + startIndex += searchPattern.Length; + + // Skip whitespace to find the opening brace + while (startIndex < json.Length && char.IsWhiteSpace(json[startIndex])) + { + startIndex++; + } + + if (startIndex >= json.Length || json[startIndex] != '{') + { + return string.Empty; + } + + // Find the matching closing brace + var braceCount = 0; + var endIndex = startIndex; + var inString = false; + var escapeNext = false; + + for (int i = startIndex; i < json.Length; i++) + { + var ch = json[i]; + + if (escapeNext) + { + escapeNext = false; + continue; + } + + if (ch == '\\') + { + escapeNext = true; + continue; + } + + if (ch == '"') + { + inString = !inString; + continue; + } + + if (!inString) + { + if (ch == '{') + { + braceCount++; + } + else if (ch == '}') + { + braceCount--; + if (braceCount == 0) + { + endIndex = i; + break; + } + } + } + } + + if (braceCount != 0) + { + return string.Empty; + } + + return json.Substring(startIndex, endIndex - startIndex + 1); + } + + internal static Dictionary ParseAliasesFromJson(string aliasesJson) + { + var aliases = new Dictionary(); + var inString = false; + var escapeNext = false; + var currentToken = new StringBuilder(); + var currentKey = string.Empty; + var currentAliases = new List(); + var inArray = false; + var collectingKey = true; + + // Skip opening and closing braces + for (int i = 1; i < aliasesJson.Length - 1; i++) + { + var ch = aliasesJson[i]; + + if (escapeNext) + { + if (inString) + { + currentToken.Append(ch); + } + + escapeNext = false; + continue; + } + + if (ch == '\\') + { + if (inString) + { + currentToken.Append(ch); + } + + escapeNext = true; + continue; + } + + if (ch == '"') + { + if (!inString) + { + // Start of string + inString = true; + currentToken.Clear(); + } + else + { + // End of string + inString = false; + var tokenValue = currentToken.ToString(); + + if (collectingKey) + { + currentKey = tokenValue; + collectingKey = false; + } + else if (inArray) + { + currentAliases.Add(tokenValue); + } + } + + continue; + } + + if (inString) + { + currentToken.Append(ch); + continue; + } + + // Handle structural characters outside of strings + switch (ch) + { + case '[': + inArray = true; + currentAliases.Clear(); + break; + + case ']': + inArray = false; + if (!string.IsNullOrEmpty(currentKey) && currentAliases.Count > 0) + { + aliases[currentKey] = currentAliases.ToArray(); + } + + break; + + case ',': + if (!inArray) + { + // End of key-value pair, reset for next key + collectingKey = true; + currentKey = string.Empty; + currentAliases.Clear(); + } + + break; + } + } + + return aliases; + } +} diff --git a/tracer/src/Datadog.Trace.SourceGenerators/Helpers/TrackingNames.cs b/tracer/src/Datadog.Trace.SourceGenerators/Helpers/TrackingNames.cs index e3b3434eaf87..c5fc2cf65257 100644 --- a/tracer/src/Datadog.Trace.SourceGenerators/Helpers/TrackingNames.cs +++ b/tracer/src/Datadog.Trace.SourceGenerators/Helpers/TrackingNames.cs @@ -31,4 +31,10 @@ internal class TrackingNames public const string AssemblyCallTargetDefinitionSource = nameof(AssemblyCallTargetDefinitionSource); public const string AdoNetCallTargetDefinitionSource = nameof(AdoNetCallTargetDefinitionSource); public const string AdoNetSignatures = nameof(AdoNetSignatures); + + // Configuration key matcher + public const string ConfigurationKeysParseConfiguration = nameof(ConfigurationKeysParseConfiguration); + public const string ConfigurationKeyMatcherDiagnostics = nameof(ConfigurationKeyMatcherDiagnostics); + public const string ConfigurationKeyMatcherValidData = nameof(ConfigurationKeyMatcherValidData); + public const string ConfigurationKeysAdditionalText = nameof(ConfigurationKeysAdditionalText); } diff --git a/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs b/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs index 05dd3bfa7bbc..6fc45d039f62 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs +++ b/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs @@ -54,9 +54,10 @@ internal static class ProcessConfiguration if (logDirectory == null) { -#pragma warning disable 618 // ProfilerLogPath is deprecated but still supported - var nativeLogFile = config.WithKeys(ConfigurationKeys.ProfilerLogPath).AsString(); -#pragma warning restore 618 + // ProfilerLogPath is deprecated but still supported. For now, we bypass the WithKeys analyzer, but later we want to pull deprecations differently as part of centralized file +#pragma warning disable DD0008, 618 + var nativeLogFile = config.WithKeys(DeprecationConstants.ProfilerLogPath).AsString(); +#pragma warning restore DD0008, 618 if (!string.IsNullOrEmpty(nativeLogFile)) { logDirectory = Path.GetDirectoryName(nativeLogFile); diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj index 26660f1f4bea..13a17be31188 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj @@ -59,7 +59,7 @@ - + diff --git a/tracer/src/Datadog.Trace/AppSec/SecuritySettings.cs b/tracer/src/Datadog.Trace/AppSec/SecuritySettings.cs index fedf165fb326..5ed0a7ca38a6 100644 --- a/tracer/src/Datadog.Trace/AppSec/SecuritySettings.cs +++ b/tracer/src/Datadog.Trace/AppSec/SecuritySettings.cs @@ -124,7 +124,7 @@ public SecuritySettings(IConfigurationSource? source, IConfigurationTelemetry te UserEventsAutoInstrumentationMode = UserTrackingIdentMode; } - ApiSecurityEnabled = config.WithKeys(ConfigurationKeys.AppSec.ApiSecurityEnabled, "DD_EXPERIMENTAL_API_SECURITY_ENABLED") + ApiSecurityEnabled = config.WithKeys(ConfigurationKeys.AppSec.ApiSecurityEnabled) .AsBool(true); ApiSecuritySampleDelay = config.WithKeys(ConfigurationKeys.AppSec.ApiSecuritySampleDelay) diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.Logging.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.Logging.cs index 865069164c69..230c65aa13d9 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.Logging.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.Logging.cs @@ -29,17 +29,9 @@ internal static partial class ConfigurationKeys /// public const string LogRateLimit = "DD_TRACE_LOGGING_RATE"; - /// - /// Configuration key for setting the path to the .NET Tracer native log file. - /// This also determines the output folder of the .NET Tracer managed log files. - /// Overridden by if present. - /// - [Obsolete(DeprecationMessages.LogPath)] - public const string ProfilerLogPath = "DD_TRACE_LOG_PATH"; - /// /// Configuration key for setting the directory of the .NET Tracer logs. - /// Overrides the value in if present. + /// Overrides the value in if present. /// Default value is "%ProgramData%"\Datadog .NET Tracer\logs\" on Windows /// or "/var/log/datadog/dotnet/" on Linux. /// diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs index 8ba109b9d858..a7ef5101da56 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationKeys.cs @@ -148,7 +148,7 @@ internal static partial class ConfigurationKeys /// Configuration key for enabling or disabling default Analytics. /// /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public const string GlobalAnalyticsEnabled = "DD_TRACE_ANALYTICS_ENABLED"; /// diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs index 878451db00ad..6fec65b2dc50 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs @@ -58,6 +58,8 @@ public void Add(IConfigurationSource source) [PublicApi] IEnumerator IEnumerable.GetEnumerator() => _sources.GetEnumerator(); + public bool IsPresent(string key) => _sources.Any(source => source.IsPresent(key)); + /// public ConfigurationResult GetString(string key, IConfigurationTelemetry telemetry, Func? validator, bool recordValue) { diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryConfigurationSource.cs index 8774fc579262..34cf3dd4f65c 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryConfigurationSource.cs @@ -21,6 +21,8 @@ public DictionaryConfigurationSource(IReadOnlyDictionary diction public override ConfigurationOrigins Origin => ConfigurationOrigins.Code; + public override bool IsPresent(string key) => _dictionary.ContainsKey(key); + protected override string? GetString(string key) { _dictionary.TryGetValue(key, out var value); diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs index 36cf6e8a463c..0ff89c43c00a 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/DictionaryObjectConfigurationSource.cs @@ -30,6 +30,8 @@ public DictionaryObjectConfigurationSource(IReadOnlyDictionary protected IReadOnlyDictionary Dictionary { get; } + public bool IsPresent(string key) => Dictionary.ContainsKey(key); + protected virtual bool TryGetValue(string key, out object? value) => Dictionary.TryGetValue(key, out value); diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/EnvironmentConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/EnvironmentConfigurationSource.cs index a38f7154e3b4..1ebff5a90381 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/EnvironmentConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/EnvironmentConfigurationSource.cs @@ -34,5 +34,7 @@ internal class EnvironmentConfigurationSource : StringConfigurationSource return null; } + + public override bool IsPresent(string key) => GetString(key) is not null; } } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/GlobalConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/GlobalConfigurationSource.cs index 2d86b261ddd2..3ae3d30ff2b6 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/GlobalConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/GlobalConfigurationSource.cs @@ -97,7 +97,7 @@ internal static bool TryLoadJsonConfigurationFile(IConfigurationSource configura // if environment variable is not set, look for default file name in the current directory var configurationFileName = new ConfigurationBuilder(configurationSource, telemetry) - .WithKeys(ConfigurationKeys.ConfigurationFileName, "DD_DOTNET_TRACER_CONFIG_FILE") + .WithKeys(ConfigurationKeys.ConfigurationFileName) .AsString( getDefaultValue: () => Path.Combine(baseDirectory ?? GetCurrentDirectory(), "datadog.json"), validator: null); diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/HandsOffConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/HandsOffConfigurationSource.cs index 45c63d0033e8..4f7dde92c4cd 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/HandsOffConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/HandsOffConfigurationSource.cs @@ -24,4 +24,6 @@ internal sealed class HandsOffConfigurationSource(Dictionary con _configurations.TryGetValue(key, out var value); return value; } + + public override bool IsPresent(string key) => _configurations.ContainsKey(key); } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs index 852241d8c0ed..ac0792dce6e8 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/IConfigurationSource.cs @@ -23,6 +23,11 @@ public interface IConfigurationSource /// public ConfigurationOrigins Origin { get; } + /// + /// Gets a value indicating whether the key is present in the configuration source. + /// + bool IsPresent(string key); + /// /// 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 df1dc9c84de6..f53bb7ee6ec8 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/JsonConfigurationSource.cs @@ -78,6 +78,8 @@ private protected JsonConfigurationSource(string json, ConfigurationOrigins orig internal bool TreatNullDictionaryAsEmpty { get; set; } = true; + public bool IsPresent(string key) => SelectToken(key) is not null; + /// /// Creates a new instance /// by loading the JSON string from the specified file. diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NameValueConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NameValueConfigurationSource.cs index 040beeaac4ca..4f25d4783ce7 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NameValueConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NameValueConfigurationSource.cs @@ -46,5 +46,7 @@ internal NameValueConfigurationSource(NameValueCollection nameValueCollection, C { return _nameValueCollection[key]; } + + public override bool IsPresent(string key) => !string.IsNullOrEmpty(_nameValueCollection[key]); } } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs index 456a100fe577..996e5d583334 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/NullConfigurationSource.cs @@ -41,4 +41,6 @@ public ConfigurationResult> GetDictionary(string key public ConfigurationResult GetAs(string key, IConfigurationTelemetry telemetry, Func> converter, Func? validator, bool recordValue) => ConfigurationResult.NotFound(); + + public bool IsPresent(string key) => false; } diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs index b22d9bcec633..95e48e88128d 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/StringConfigurationSource.cs @@ -114,6 +114,8 @@ internal abstract class StringConfigurationSource : IConfigurationSource protected abstract string? GetString(string key); + public abstract bool IsPresent(string key); + /// public ConfigurationResult GetString(string key, IConfigurationTelemetry telemetry, Func? validator, bool recordValue) { diff --git a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs index 0f7d7f7bf4fd..4ba02536c5c7 100644 --- a/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs +++ b/tracer/src/Datadog.Trace/Configuration/ConfigurationSources/Telemetry/ConfigurationBuilder.cs @@ -19,35 +19,46 @@ internal readonly struct ConfigurationBuilder(IConfigurationSource source, IConf public HasKeys WithKeys(string key) => new(_source, _telemetry, key); - public HasKeys WithKeys(string key, string fallbackKey) => new(_source, _telemetry, key, fallbackKey); - - public HasKeys WithKeys(string key, string fallbackKey1, string fallbackKey2) => new(_source, _telemetry, key, fallbackKey1, fallbackKey2); - - public HasKeys WithKeys(string key, string fallbackKey1, string fallbackKey2, string fallbackKey3) => new(_source, _telemetry, key, fallbackKey1, fallbackKey2, fallbackKey3); - - internal readonly struct HasKeys + public HasKeys WithIntegrationKey(string integrationName) => new( + _source, + _telemetry, + string.Format(IntegrationSettings.IntegrationEnabledKey, integrationName.ToUpperInvariant()), + [ + string.Format(IntegrationSettings.IntegrationEnabledKey, integrationName), + $"DD_{integrationName}_ENABLED" + ]); + + public HasKeys WithIntegrationAnalyticsKey(string integrationName) => new( + _source, + _telemetry, +#pragma warning disable 618 // App analytics is deprecated, but still used + string.Format(IntegrationSettings.AnalyticsEnabledKey, integrationName.ToUpperInvariant()), + [ + string.Format(IntegrationSettings.AnalyticsEnabledKey, integrationName), +#pragma warning restore 618 + $"DD_{integrationName}_ANALYTICS_ENABLED" + ]); + + public HasKeys WithIntegrationAnalyticsSampleRateKey(string integrationName) => new( + _source, + _telemetry, +#pragma warning disable 618 // App analytics is deprecated, but still used + string.Format(IntegrationSettings.AnalyticsSampleRateKey, integrationName.ToUpperInvariant()), + [ + string.Format(IntegrationSettings.AnalyticsSampleRateKey, integrationName), +#pragma warning restore 618 + $"DD_{integrationName}_ANALYTICS_SAMPLE_RATE" + ]); + + internal readonly struct HasKeys(IConfigurationSource source, IConfigurationTelemetry telemetry, string key, string[]? providedAliases = null) { - public HasKeys(IConfigurationSource source, IConfigurationTelemetry telemetry, string key, string? fallbackKey1 = null, string? fallbackKey2 = null, string? fallbackKey3 = null) - { - Source = source; - Telemetry = telemetry; - Key = key; - FallbackKey1 = fallbackKey1; - FallbackKey2 = fallbackKey2; - FallbackKey3 = fallbackKey3; - } + private readonly string[]? _providedAliases = providedAliases; - private IConfigurationSource Source { get; } + private IConfigurationSource Source { get; } = source; - private IConfigurationTelemetry Telemetry { get; } + private IConfigurationTelemetry Telemetry { get; } = telemetry; - private string Key { get; } - - private string? FallbackKey1 { get; } - - private string? FallbackKey2 { get; } - - private string? FallbackKey3 { get; } + private string Key { get; } = key; // **************** // String accessors @@ -493,23 +504,9 @@ private ConfigurationResult GetAs(Func? validator, FuncThe raw private ConfigurationResult GetResult(Func?, bool, ConfigurationResult> selector, Func? validator, bool recordValue) { - var result = selector(Source, Key, Telemetry, validator, recordValue); - if (result.ShouldFallBack && FallbackKey1 is not null) - { - result = selector(Source, FallbackKey1, Telemetry, validator, recordValue); - } - - if (result.ShouldFallBack && FallbackKey2 is not null) - { - result = selector(Source, FallbackKey2, Telemetry, validator, recordValue); - } - - if (result.ShouldFallBack && FallbackKey3 is not null) - { - result = selector(Source, FallbackKey3, Telemetry, validator, recordValue); - } - - return result; + var source = Source; + var telemetry = Telemetry; + return GetResultWithFallback(key => selector(source, key, telemetry, validator, recordValue)); } /// @@ -523,62 +520,48 @@ private ConfigurationResult GetResult(FuncThe raw private ConfigurationResult GetResult(Func?, Func>, bool, ConfigurationResult> selector, Func? validator, Func> converter, bool recordValue) { - var result = selector(Source, Key, Telemetry, validator, converter, recordValue); - if (result.ShouldFallBack && FallbackKey1 is not null) - { - result = selector(Source, FallbackKey1, Telemetry, validator, converter, recordValue); - } - - if (result.ShouldFallBack && FallbackKey2 is not null) - { - result = selector(Source, FallbackKey2, Telemetry, validator, converter, recordValue); - } - - if (result.ShouldFallBack && FallbackKey3 is not null) - { - result = selector(Source, FallbackKey3, Telemetry, validator, converter, recordValue); - } - - return result; + var source = Source; + var telemetry = Telemetry; + return GetResultWithFallback(key => selector(source, key, telemetry, validator, converter, recordValue)); } private ConfigurationResult> GetDictionaryResult(bool allowOptionalMappings, char separator) { - var result = Source.GetDictionary(Key, Telemetry, validator: null, allowOptionalMappings, separator); - if (result.ShouldFallBack && FallbackKey1 is not null) - { - result = Source.GetDictionary(FallbackKey1, Telemetry, validator: null, allowOptionalMappings, separator); - } - - if (result.ShouldFallBack && FallbackKey2 is not null) - { - result = Source.GetDictionary(FallbackKey2, Telemetry, validator: null, allowOptionalMappings, separator); - } - - if (result.ShouldFallBack && FallbackKey3 is not null) - { - result = Source.GetDictionary(FallbackKey3, Telemetry, validator: null, allowOptionalMappings, separator); - } - - return result; + var source = Source; + var telemetry = Telemetry; + return GetResultWithFallback(key => source.GetDictionary(key, telemetry, validator: null, allowOptionalMappings, separator)); } 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); - } + var source = Source; + var telemetry = Telemetry; + return GetResultWithFallback(key => source.GetDictionary(key, telemetry, validator: null, parser)); + } - if (result.ShouldFallBack && FallbackKey2 is not null) + /// + /// Common method that handles key resolution and alias fallback logic + /// + /// The method to call for each key + /// The type being retrieved + /// The raw + private ConfigurationResult GetResultWithFallback(Func> selector) + { + var result = selector(Key); + if (!result.ShouldFallBack) { - result = Source.GetDictionary(FallbackKey2, Telemetry, validator: null, parser); + return result; } - if (result.ShouldFallBack && FallbackKey3 is not null) + string[] aliases = _providedAliases ?? ConfigKeyAliasesSwitcher.GetAliases(Key); + + foreach (var alias in aliases) { - result = Source.GetDictionary(FallbackKey3, Telemetry, validator: null, parser); + result = selector(alias); + if (!result.ShouldFallBack) + { + break; + } } return result; @@ -606,10 +589,9 @@ public static StructConfigurationResultWithKey Create(IConfigurationTeleme public static StructConfigurationResultWithKey Create(IConfigurationTelemetry telemetry, string key, ConfigurationResult configurationResult) => new(telemetry, key, configurationResult); - public static StructConfigurationResultWithKey Create(IConfigurationTelemetry telemetry, string key, ConfigurationResult configurationResult) - => new(telemetry, key, configurationResult); + public static StructConfigurationResultWithKey Create(IConfigurationTelemetry telemetry, string key, ConfigurationResult configurationResult) => new(telemetry, key, configurationResult); - [return:NotNullIfNotNull(nameof(defaultValue))] + [return: NotNullIfNotNull(nameof(defaultValue))] public T? WithDefault(T? defaultValue) { if (ConfigurationResult is { Result: { } ddResult, IsValid: true }) @@ -623,7 +605,7 @@ public static StructConfigurationResultWithKey Create(IConfigurationTele public T WithDefault(T defaultValue) { - if (ConfigurationResult is { Result: { } ddResult, IsValid: true }) + if (ConfigurationResult is { Result: var ddResult, IsValid: true }) { return ddResult; } diff --git a/tracer/src/Datadog.Trace/Configuration/DeprecationMessages.cs b/tracer/src/Datadog.Trace/Configuration/DeprecationConstants.cs similarity index 55% rename from tracer/src/Datadog.Trace/Configuration/DeprecationMessages.cs rename to tracer/src/Datadog.Trace/Configuration/DeprecationConstants.cs index d6e015d0be5b..ed984834ce45 100644 --- a/tracer/src/Datadog.Trace/Configuration/DeprecationMessages.cs +++ b/tracer/src/Datadog.Trace/Configuration/DeprecationConstants.cs @@ -1,13 +1,18 @@ -// +// // 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. // +using System; + namespace Datadog.Trace.Configuration { - internal static class DeprecationMessages + internal static class DeprecationConstants { public const string AppAnalytics = "App Analytics has been replaced by Tracing without Limits. For more information see https://docs.datadoghq.com/tracing/legacy_app_analytics/"; - public const string LogPath = "DD_TRACE_LOG_PATH is deprecated. Use DD_TRACE_LOG_DIRECTORY instead"; + public const string ProfilerLogPathObsoleteMessage = "DD_TRACE_LOG_PATH is deprecated. Use DD_TRACE_LOG_DIRECTORY instead"; + + [Obsolete(ProfilerLogPathObsoleteMessage)] + public const string ProfilerLogPath = "DD_TRACE_LOG_PATH"; } } diff --git a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs index 885f7541fbad..b76ced8ddd97 100644 --- a/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/ExporterSettings.cs @@ -445,11 +445,11 @@ public Raw(IConfigurationSource source, IConfigurationTelemetry telemetry) TracesUnixDomainSocketPath = config.WithKeys(ConfigurationKeys.TracesUnixDomainSocketPath).AsString(); TraceAgentHost = config - .WithKeys(ConfigurationKeys.AgentHost, "DD_TRACE_AGENT_HOSTNAME", "DATADOG_TRACE_AGENT_HOSTNAME") + .WithKeys(ConfigurationKeys.AgentHost) .AsString(); TraceAgentPort = config - .WithKeys(ConfigurationKeys.AgentPort, "DATADOG_TRACE_AGENT_PORT") + .WithKeys(ConfigurationKeys.AgentPort) .AsInt32(); MetricsUrl = config.WithKeys(ConfigurationKeys.MetricsUri).AsString(); diff --git a/tracer/src/Datadog.Trace/Configuration/IntegrationSettings.cs b/tracer/src/Datadog.Trace/Configuration/IntegrationSettings.cs index 91bc57339596..0a3de39e8dff 100644 --- a/tracer/src/Datadog.Trace/Configuration/IntegrationSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/IntegrationSettings.cs @@ -6,6 +6,7 @@ #nullable enable using System; +using System.Collections.Generic; using Datadog.Trace.Configuration.Telemetry; namespace Datadog.Trace.Configuration @@ -18,18 +19,18 @@ public class IntegrationSettings : IEquatable /// /// Configuration key pattern for enabling or disabling an integration. /// - public const string IntegrationEnabled = "DD_TRACE_{0}_ENABLED"; + public const string IntegrationEnabledKey = "DD_TRACE_{0}_ENABLED"; /// /// Configuration key pattern for enabling or disabling Analytics in an integration. /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public const string AnalyticsEnabledKey = "DD_TRACE_{0}_ANALYTICS_ENABLED"; /// /// Configuration key pattern for setting Analytics sampling rate in an integration. /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public const string AnalyticsSampleRateKey = "DD_TRACE_{0}_ANALYTICS_SAMPLE_RATE"; /// @@ -39,7 +40,7 @@ public class IntegrationSettings : IEquatable /// The to use when retrieving configuration values. /// Has the integration been explicitly disabled /// The fallback values to use. Only used in manual instrumentation scenarios - internal IntegrationSettings(string? integrationName, IConfigurationSource? source, bool isExplicitlyDisabled, IntegrationSettings? fallback = null) + internal IntegrationSettings(string integrationName, IConfigurationSource? source, bool isExplicitlyDisabled, IntegrationSettings? fallback = null) { if (integrationName is null) { @@ -50,32 +51,19 @@ internal IntegrationSettings(string? integrationName, IConfigurationSource? sour // We don't record these in telemetry, because they're blocked anyway var config = new ConfigurationBuilder(source ?? NullConfigurationSource.Instance, NullConfigurationTelemetry.Instance); - var upperName = integrationName.ToUpperInvariant(); Enabled = isExplicitlyDisabled ? false : config - .WithKeys( - string.Format(IntegrationEnabled, upperName), - string.Format(IntegrationEnabled, integrationName), - string.Format(IntegrationEnabled, integrationName), - $"DD_{integrationName}_ENABLED") - .AsBool() - ?? fallback?.Enabled; + .WithIntegrationKey(integrationName) + .AsBool() ?? fallback?.AnalyticsEnabled; #pragma warning disable 618 // App analytics is deprecated, but still used AnalyticsEnabled = config - .WithKeys( - string.Format(AnalyticsEnabledKey, upperName), - string.Format(AnalyticsEnabledKey, integrationName), - $"DD_{integrationName}_ANALYTICS_ENABLED") - .AsBool() - ?? fallback?.AnalyticsEnabled; + .WithIntegrationAnalyticsKey(integrationName) + .AsBool() ?? fallback?.AnalyticsEnabled; AnalyticsSampleRate = config - .WithKeys( - string.Format(AnalyticsSampleRateKey, upperName), - string.Format(AnalyticsSampleRateKey, integrationName), - $"DD_{integrationName}_ANALYTICS_SAMPLE_RATE") + .WithIntegrationAnalyticsSampleRateKey(integrationName) .AsDouble(fallback?.AnalyticsSampleRate ?? 1.0); #pragma warning restore 618 } diff --git a/tracer/src/Datadog.Trace/Configuration/MutableSettings.cs b/tracer/src/Datadog.Trace/Configuration/MutableSettings.cs index df5690c7aa7a..ffa6d950d658 100644 --- a/tracer/src/Datadog.Trace/Configuration/MutableSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/MutableSettings.cs @@ -195,7 +195,7 @@ private MutableSettings( /// See the documentation for more details. /// /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public bool AnalyticsEnabled { get; } /// @@ -525,7 +525,7 @@ internal bool IsIntegrationEnabled(IntegrationId integration, bool defaultValue return false; } - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] internal double? GetIntegrationAnalyticsSampleRate(IntegrationId integration, bool enabledWithGlobalSetting) { var integrationSettings = Integrations[integration]; @@ -607,7 +607,7 @@ public static MutableSettings Create( }; globalTags = config - .WithKeys(ConfigurationKeys.GlobalTags, "DD_TRACE_GLOBAL_TAGS") + .WithKeys(ConfigurationKeys.GlobalTags) .AsDictionaryResult(parser: updatedTagsParser) .OverrideWith( RemapOtelTags(in otelTags), @@ -621,7 +621,7 @@ public static MutableSettings Create( else { globalTags = config - .WithKeys(ConfigurationKeys.GlobalTags, "DD_TRACE_GLOBAL_TAGS") + .WithKeys(ConfigurationKeys.GlobalTags) .AsDictionaryResult() .OverrideWith( RemapOtelTags(in otelTags), @@ -642,7 +642,7 @@ public static MutableSettings Create( var otelServiceName = config.WithKeys(ConfigurationKeys.OpenTelemetry.ServiceName).AsStringResult(); var serviceName = config - .WithKeys(ConfigurationKeys.ServiceName, "DD_SERVICE_NAME") + .WithKeys(ConfigurationKeys.ServiceName) .AsStringResult() .OverrideWith(in otelServiceName, errorLog); @@ -728,7 +728,7 @@ public static MutableSettings Create( #pragma warning disable 618 // this parameter has been replaced but may still be used var maxTracesSubmittedPerSecond = config - .WithKeys(ConfigurationKeys.TraceRateLimit, ConfigurationKeys.MaxTracesSubmittedPerSecond) + .WithKeys(ConfigurationKeys.TraceRateLimit) #pragma warning restore 618 .AsInt32(defaultValue: 100); @@ -775,17 +775,13 @@ public static MutableSettings Create( .AsBool(defaultValue: false); var httpServerErrorStatusCodesString = config -#pragma warning disable 618 // This config key has been replaced but may still be used - .WithKeys(ConfigurationKeys.HttpServerErrorStatusCodes, ConfigurationKeys.DeprecatedHttpServerErrorStatusCodes) -#pragma warning restore 618 + .WithKeys(ConfigurationKeys.HttpServerErrorStatusCodes) .AsString(defaultValue: "500-599"); var httpServerErrorStatusCodes = ParseHttpCodesToArray(httpServerErrorStatusCodesString); var httpClientErrorStatusCodesString = config -#pragma warning disable 618 // This config key has been replaced but may still be used - .WithKeys(ConfigurationKeys.HttpClientErrorStatusCodes, ConfigurationKeys.DeprecatedHttpClientErrorStatusCodes) -#pragma warning restore 618 + .WithKeys(ConfigurationKeys.HttpClientErrorStatusCodes) .AsString(defaultValue: "400-499"); var httpClientErrorStatusCodes = ParseHttpCodesToArray(httpClientErrorStatusCodesString); diff --git a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs index 0aa27424f471..60f3d0da0cb6 100644 --- a/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs +++ b/tracer/src/Datadog.Trace/Configuration/TracerSettings.cs @@ -133,7 +133,7 @@ internal TracerSettings(IConfigurationSource? source, IConfigurationTelemetry te ? ParsingResult.Success(result: false) : ParsingResult.Failure()); IsActivityListenerEnabled = config - .WithKeys(ConfigurationKeys.FeatureFlags.OpenTelemetryEnabled, "DD_TRACE_ACTIVITY_LISTENER_ENABLED") + .WithKeys(ConfigurationKeys.FeatureFlags.OpenTelemetryEnabled) .AsBoolResult() .OverrideWith(in otelActivityListenerEnabled, ErrorLog, defaultValue: false); @@ -204,7 +204,7 @@ not null when string.Equals(value, "otlp", StringComparison.OrdinalIgnoreCase) = .AsInt32(defaultValue: 7_500); OtlpMetricsProtocol = config - .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsProtocol, ConfigurationKeys.OpenTelemetry.ExporterOtlpProtocol) + .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsProtocol) .GetAs( defaultValue: new(OtlpProtocol.HttpProtobuf, "http/protobuf"), converter: x => x switch @@ -242,14 +242,14 @@ not null when string.Equals(x, "http/json", StringComparison.OrdinalIgnoreCase) converter: uriString => new Uri(uriString)); OtlpMetricsHeaders = config - .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsHeaders, ConfigurationKeys.OpenTelemetry.ExporterOtlpHeaders) + .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsHeaders) .AsDictionaryResult(separator: '=') .WithDefault(new DefaultResult>(new Dictionary(), "[]")) .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value?.Trim() ?? string.Empty); OtlpMetricsTimeoutMs = config - .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsTimeoutMs, ConfigurationKeys.OpenTelemetry.ExporterOtlpTimeoutMs) + .WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpMetricsTimeoutMs) .AsInt32(defaultValue: 10_000); OtlpMetricsTemporalityPreference = config @@ -429,14 +429,14 @@ not null when string.Equals(x, "lowmemory", StringComparison.OrdinalIgnoreCase) converter: otelConverter); PropagationStyleInject = config - .WithKeys(ConfigurationKeys.PropagationStyleInject, "DD_PROPAGATION_STYLE_INJECT", ConfigurationKeys.PropagationStyle) - .GetAsClassResult( - validator: injectionValidator, // invalid individual values are rejected later - converter: style => TrimSplitString(style, commaSeparator)) - .OverrideWith(in otelPropagation, ErrorLog, getDefaultPropagationHeaders); + .WithKeys(ConfigurationKeys.PropagationStyleInject) + .GetAsClassResult( + validator: injectionValidator, // invalid individual values are rejected later + converter: style => TrimSplitString(style, commaSeparator)) + .OverrideWith(in otelPropagation, ErrorLog, getDefaultPropagationHeaders); PropagationStyleExtract = config - .WithKeys(ConfigurationKeys.PropagationStyleExtract, "DD_PROPAGATION_STYLE_EXTRACT", ConfigurationKeys.PropagationStyle) + .WithKeys(ConfigurationKeys.PropagationStyleExtract) .GetAsClassResult( validator: injectionValidator, // invalid individual values are rejected later converter: style => TrimSplitString(style, commaSeparator)) @@ -487,7 +487,7 @@ not null when string.Equals(x, "lowmemory", StringComparison.OrdinalIgnoreCase) .Value; IpHeader = config - .WithKeys(ConfigurationKeys.IpHeader, ConfigurationKeys.AppSec.CustomIpHeader) + .WithKeys(ConfigurationKeys.IpHeader) .AsString(); IpHeaderEnabled = config @@ -780,7 +780,7 @@ not null when string.Equals(x, "lowmemory", StringComparison.OrdinalIgnoreCase) public ExporterSettings Exporter { get; } /// - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] public bool AnalyticsEnabled => MutableSettings.AnalyticsEnabled; /// @@ -1231,7 +1231,7 @@ internal bool IsErrorStatusCode(int statusCode, bool serverStatusCode) internal bool IsIntegrationEnabled(IntegrationId integration, bool defaultValue = true) => DynamicSettings.TraceEnabled != false && MutableSettings.IsIntegrationEnabled(integration, defaultValue); - [Obsolete(DeprecationMessages.AppAnalytics)] + [Obsolete(DeprecationConstants.AppAnalytics)] internal double? GetIntegrationAnalyticsSampleRate(IntegrationId integration, bool enabledWithGlobalSetting) => MutableSettings.GetIntegrationAnalyticsSampleRate(integration, enabledWithGlobalSetting); diff --git a/tracer/src/Datadog.Trace/Datadog.Trace.csproj b/tracer/src/Datadog.Trace/Datadog.Trace.csproj index f7c0749e6db7..06bc93bbe009 100644 --- a/tracer/src/Datadog.Trace/Datadog.Trace.csproj +++ b/tracer/src/Datadog.Trace/Datadog.Trace.csproj @@ -156,4 +156,16 @@ $(DefineConstants);ENABLE_IL2CPP + + + PreserveNewest + + + + + + + + + \ No newline at end of file diff --git a/tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplaySettings.cs b/tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplaySettings.cs index c9681749780b..5ee568a0f250 100644 --- a/tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplaySettings.cs +++ b/tracer/src/Datadog.Trace/Debugger/ExceptionAutoInstrumentation/ExceptionReplaySettings.cs @@ -22,9 +22,7 @@ public ExceptionReplaySettings(IConfigurationSource? source, IConfigurationTelem source ??= NullConfigurationSource.Instance; var config = new ConfigurationBuilder(source, telemetry); -#pragma warning disable CS0612 // Type or member is obsolete - var erEnabledResult = config.WithKeys(ConfigurationKeys.Debugger.ExceptionReplayEnabled, fallbackKey: ConfigurationKeys.Debugger.ExceptionDebuggingEnabled).AsBoolResult(); -#pragma warning restore CS0612 // Type or member is obsolete + var erEnabledResult = config.WithKeys(ConfigurationKeys.Debugger.ExceptionReplayEnabled).AsBoolResult(); Enabled = erEnabledResult.WithDefault(false); CanBeEnabled = erEnabledResult.ConfigurationResult is not { IsValid: true, Result: false }; diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs new file mode 100644 index 000000000000..15211f06d6a0 --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs @@ -0,0 +1,115 @@ +using System; + +namespace Datadog.Trace.Configuration; +/// +/// Generated configuration key matcher that handles main keys and aliases. +/// +internal static partial class ConfigKeyAliasesSwitcher +{ + /// + /// Gets all aliases for the given configuration key. + /// + /// The configuration key. + /// An array of aliases for the key, or empty array if no aliases exist. + public static string[] GetAliases(string mainKey) + { + switch (mainKey) + { + case "DD_AGENT_HOST": + return new string[] + { + "DATADOG_TRACE_AGENT_HOSTNAME_OPTIMIZED", + "DD_TRACE_AGENT_HOSTNAME" + }; + case "DD_API_SECURITY_ENABLED": + return new string[] + { + "DD_EXPERIMENTAL_API_SECURITY_ENABLED" + }; + case "DD_EXCEPTION_REPLAY_ENABLED": + return new string[] + { + "DD_EXCEPTION_DEBUGGING_ENABLED" + }; + case "DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": + return new string[] + { + "DD_INTERNAL_RCM_POLL_INTERVAL" + }; + case "DD_SERVICE": + return new string[] + { + "DD_SERVICE_NAME" + }; + case "DD_TAGS": + return new string[] + { + "DD_TRACE_GLOBAL_TAGS" + }; + case "DD_TRACE_AGENT_PORT": + return new string[] + { + "DATADOG_TRACE_AGENT_PORT" + }; + case "DD_TRACE_CLIENT_IP_HEADER": + return new string[] + { + "DD_APPSEC_IPHEADER" + }; + case "DD_TRACE_CONFIG_FILE": + return new string[] + { + "DD_DOTNET_TRACER_CONFIG_FILE" + }; + case "DD_TRACE_HTTP_CLIENT_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_CLIENT_ERROR_STATUSES" + }; + case "DD_TRACE_HTTP_SERVER_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_SERVER_ERROR_STATUSES" + }; + case "DD_TRACE_OTEL_ENABLED": + return new string[] + { + "DD_TRACE_ACTIVITY_LISTENER_ENABLED" + }; + case "DD_TRACE_PROPAGATION_STYLE_EXTRACT": + return new string[] + { + "DD_PROPAGATION_STYLE_EXTRACT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_PROPAGATION_STYLE_INJECT": + return new string[] + { + "DD_PROPAGATION_STYLE_INJECT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_RATE_LIMIT": + return new string[] + { + "DD_MAX_TRACES_PER_SECOND" + }; + case "OTEL_EXPORTER_OTLP_METRICS_HEADERS": + return new string[] + { + "OTEL_EXPORTER_OTLP_HEADERS" + }; + case "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": + return new string[] + { + "OTEL_EXPORTER_OTLP_PROTOCOL" + }; + case "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": + return new string[] + { + "OTEL_EXPORTER_OTLP_TIMEOUT" + }; + default: + return Array.Empty(); + } + } +}// diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs new file mode 100644 index 000000000000..15211f06d6a0 --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs @@ -0,0 +1,115 @@ +using System; + +namespace Datadog.Trace.Configuration; +/// +/// Generated configuration key matcher that handles main keys and aliases. +/// +internal static partial class ConfigKeyAliasesSwitcher +{ + /// + /// Gets all aliases for the given configuration key. + /// + /// The configuration key. + /// An array of aliases for the key, or empty array if no aliases exist. + public static string[] GetAliases(string mainKey) + { + switch (mainKey) + { + case "DD_AGENT_HOST": + return new string[] + { + "DATADOG_TRACE_AGENT_HOSTNAME_OPTIMIZED", + "DD_TRACE_AGENT_HOSTNAME" + }; + case "DD_API_SECURITY_ENABLED": + return new string[] + { + "DD_EXPERIMENTAL_API_SECURITY_ENABLED" + }; + case "DD_EXCEPTION_REPLAY_ENABLED": + return new string[] + { + "DD_EXCEPTION_DEBUGGING_ENABLED" + }; + case "DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": + return new string[] + { + "DD_INTERNAL_RCM_POLL_INTERVAL" + }; + case "DD_SERVICE": + return new string[] + { + "DD_SERVICE_NAME" + }; + case "DD_TAGS": + return new string[] + { + "DD_TRACE_GLOBAL_TAGS" + }; + case "DD_TRACE_AGENT_PORT": + return new string[] + { + "DATADOG_TRACE_AGENT_PORT" + }; + case "DD_TRACE_CLIENT_IP_HEADER": + return new string[] + { + "DD_APPSEC_IPHEADER" + }; + case "DD_TRACE_CONFIG_FILE": + return new string[] + { + "DD_DOTNET_TRACER_CONFIG_FILE" + }; + case "DD_TRACE_HTTP_CLIENT_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_CLIENT_ERROR_STATUSES" + }; + case "DD_TRACE_HTTP_SERVER_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_SERVER_ERROR_STATUSES" + }; + case "DD_TRACE_OTEL_ENABLED": + return new string[] + { + "DD_TRACE_ACTIVITY_LISTENER_ENABLED" + }; + case "DD_TRACE_PROPAGATION_STYLE_EXTRACT": + return new string[] + { + "DD_PROPAGATION_STYLE_EXTRACT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_PROPAGATION_STYLE_INJECT": + return new string[] + { + "DD_PROPAGATION_STYLE_INJECT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_RATE_LIMIT": + return new string[] + { + "DD_MAX_TRACES_PER_SECOND" + }; + case "OTEL_EXPORTER_OTLP_METRICS_HEADERS": + return new string[] + { + "OTEL_EXPORTER_OTLP_HEADERS" + }; + case "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": + return new string[] + { + "OTEL_EXPORTER_OTLP_PROTOCOL" + }; + case "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": + return new string[] + { + "OTEL_EXPORTER_OTLP_TIMEOUT" + }; + default: + return Array.Empty(); + } + } +}// diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs new file mode 100644 index 000000000000..15211f06d6a0 --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs @@ -0,0 +1,115 @@ +using System; + +namespace Datadog.Trace.Configuration; +/// +/// Generated configuration key matcher that handles main keys and aliases. +/// +internal static partial class ConfigKeyAliasesSwitcher +{ + /// + /// Gets all aliases for the given configuration key. + /// + /// The configuration key. + /// An array of aliases for the key, or empty array if no aliases exist. + public static string[] GetAliases(string mainKey) + { + switch (mainKey) + { + case "DD_AGENT_HOST": + return new string[] + { + "DATADOG_TRACE_AGENT_HOSTNAME_OPTIMIZED", + "DD_TRACE_AGENT_HOSTNAME" + }; + case "DD_API_SECURITY_ENABLED": + return new string[] + { + "DD_EXPERIMENTAL_API_SECURITY_ENABLED" + }; + case "DD_EXCEPTION_REPLAY_ENABLED": + return new string[] + { + "DD_EXCEPTION_DEBUGGING_ENABLED" + }; + case "DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": + return new string[] + { + "DD_INTERNAL_RCM_POLL_INTERVAL" + }; + case "DD_SERVICE": + return new string[] + { + "DD_SERVICE_NAME" + }; + case "DD_TAGS": + return new string[] + { + "DD_TRACE_GLOBAL_TAGS" + }; + case "DD_TRACE_AGENT_PORT": + return new string[] + { + "DATADOG_TRACE_AGENT_PORT" + }; + case "DD_TRACE_CLIENT_IP_HEADER": + return new string[] + { + "DD_APPSEC_IPHEADER" + }; + case "DD_TRACE_CONFIG_FILE": + return new string[] + { + "DD_DOTNET_TRACER_CONFIG_FILE" + }; + case "DD_TRACE_HTTP_CLIENT_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_CLIENT_ERROR_STATUSES" + }; + case "DD_TRACE_HTTP_SERVER_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_SERVER_ERROR_STATUSES" + }; + case "DD_TRACE_OTEL_ENABLED": + return new string[] + { + "DD_TRACE_ACTIVITY_LISTENER_ENABLED" + }; + case "DD_TRACE_PROPAGATION_STYLE_EXTRACT": + return new string[] + { + "DD_PROPAGATION_STYLE_EXTRACT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_PROPAGATION_STYLE_INJECT": + return new string[] + { + "DD_PROPAGATION_STYLE_INJECT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_RATE_LIMIT": + return new string[] + { + "DD_MAX_TRACES_PER_SECOND" + }; + case "OTEL_EXPORTER_OTLP_METRICS_HEADERS": + return new string[] + { + "OTEL_EXPORTER_OTLP_HEADERS" + }; + case "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": + return new string[] + { + "OTEL_EXPORTER_OTLP_PROTOCOL" + }; + case "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": + return new string[] + { + "OTEL_EXPORTER_OTLP_TIMEOUT" + }; + default: + return Array.Empty(); + } + } +}// diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs new file mode 100644 index 000000000000..15211f06d6a0 --- /dev/null +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/ConfigKeyAliasesSwitcherGenerator/ConfigKeyAliasesSwitcher.g.cs @@ -0,0 +1,115 @@ +using System; + +namespace Datadog.Trace.Configuration; +/// +/// Generated configuration key matcher that handles main keys and aliases. +/// +internal static partial class ConfigKeyAliasesSwitcher +{ + /// + /// Gets all aliases for the given configuration key. + /// + /// The configuration key. + /// An array of aliases for the key, or empty array if no aliases exist. + public static string[] GetAliases(string mainKey) + { + switch (mainKey) + { + case "DD_AGENT_HOST": + return new string[] + { + "DATADOG_TRACE_AGENT_HOSTNAME_OPTIMIZED", + "DD_TRACE_AGENT_HOSTNAME" + }; + case "DD_API_SECURITY_ENABLED": + return new string[] + { + "DD_EXPERIMENTAL_API_SECURITY_ENABLED" + }; + case "DD_EXCEPTION_REPLAY_ENABLED": + return new string[] + { + "DD_EXCEPTION_DEBUGGING_ENABLED" + }; + case "DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": + return new string[] + { + "DD_INTERNAL_RCM_POLL_INTERVAL" + }; + case "DD_SERVICE": + return new string[] + { + "DD_SERVICE_NAME" + }; + case "DD_TAGS": + return new string[] + { + "DD_TRACE_GLOBAL_TAGS" + }; + case "DD_TRACE_AGENT_PORT": + return new string[] + { + "DATADOG_TRACE_AGENT_PORT" + }; + case "DD_TRACE_CLIENT_IP_HEADER": + return new string[] + { + "DD_APPSEC_IPHEADER" + }; + case "DD_TRACE_CONFIG_FILE": + return new string[] + { + "DD_DOTNET_TRACER_CONFIG_FILE" + }; + case "DD_TRACE_HTTP_CLIENT_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_CLIENT_ERROR_STATUSES" + }; + case "DD_TRACE_HTTP_SERVER_ERROR_STATUSES": + return new string[] + { + "DD_HTTP_SERVER_ERROR_STATUSES" + }; + case "DD_TRACE_OTEL_ENABLED": + return new string[] + { + "DD_TRACE_ACTIVITY_LISTENER_ENABLED" + }; + case "DD_TRACE_PROPAGATION_STYLE_EXTRACT": + return new string[] + { + "DD_PROPAGATION_STYLE_EXTRACT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_PROPAGATION_STYLE_INJECT": + return new string[] + { + "DD_PROPAGATION_STYLE_INJECT", + "DD_TRACE_PROPAGATION_STYLE" + }; + case "DD_TRACE_RATE_LIMIT": + return new string[] + { + "DD_MAX_TRACES_PER_SECOND" + }; + case "OTEL_EXPORTER_OTLP_METRICS_HEADERS": + return new string[] + { + "OTEL_EXPORTER_OTLP_HEADERS" + }; + case "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": + return new string[] + { + "OTEL_EXPORTER_OTLP_PROTOCOL" + }; + case "OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": + return new string[] + { + "OTEL_EXPORTER_OTLP_TIMEOUT" + }; + default: + return Array.Empty(); + } + } +}// diff --git a/tracer/src/Datadog.Trace/Logging/Internal/DatadogLoggingFactory.cs b/tracer/src/Datadog.Trace/Logging/Internal/DatadogLoggingFactory.cs index 7102761718f9..53a16228dd9f 100644 --- a/tracer/src/Datadog.Trace/Logging/Internal/DatadogLoggingFactory.cs +++ b/tracer/src/Datadog.Trace/Logging/Internal/DatadogLoggingFactory.cs @@ -170,12 +170,15 @@ internal static string GetLogDirectory(IConfigurationTelemetry telemetry) private static string GetLogDirectory(IConfigurationSource source, IConfigurationTelemetry telemetry) { - var logDirectory = new ConfigurationBuilder(source, telemetry).WithKeys(ConfigurationKeys.LogDirectory).AsString(); + var configurationBuilder = new ConfigurationBuilder(source, telemetry); + var logDirectory = configurationBuilder.WithKeys(ConfigurationKeys.LogDirectory).AsString(); if (string.IsNullOrEmpty(logDirectory)) { -#pragma warning disable 618 // ProfilerLogPath is deprecated but still supported - var nativeLogFile = new ConfigurationBuilder(source, telemetry).WithKeys(ConfigurationKeys.ProfilerLogPath).AsString(); -#pragma warning restore 618 + // todo, handle in phase 2 with deprecations +// ProfilerLogPath is deprecated but still supported. For now, we bypass the WithKeys analyzer, but later we want to pull deprecations differently as part of centralized file +#pragma warning disable DD0008, 618 + var nativeLogFile = configurationBuilder.WithKeys(DeprecationConstants.ProfilerLogPath).AsString(); +#pragma warning restore DD0008, 618 if (!string.IsNullOrEmpty(nativeLogFile)) { diff --git a/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RemoteConfigurationSettings.cs b/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RemoteConfigurationSettings.cs index a9d7ca01ad0a..b666f5b452c5 100644 --- a/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RemoteConfigurationSettings.cs +++ b/tracer/src/Datadog.Trace/RemoteConfigurationManagement/RemoteConfigurationSettings.cs @@ -24,9 +24,7 @@ public RemoteConfigurationSettings(IConfigurationSource? configurationSource, IC TracerVersion = TracerConstants.ThreePartVersion; var pollInterval = new ConfigurationBuilder(configurationSource, telemetry) -#pragma warning disable CS0618 - .WithKeys(ConfigurationKeys.Rcm.PollInterval, ConfigurationKeys.Rcm.PollIntervalInternal) -#pragma warning restore CS0618 + .WithKeys(ConfigurationKeys.Rcm.PollInterval) .AsDouble(DefaultPollIntervalSeconds, pollInterval => pollInterval is > 0 and <= 5); PollInterval = TimeSpan.FromSeconds(pollInterval.Value); diff --git a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/DbScopeFactoryTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/DbScopeFactoryTests.cs index a5a3666c4fa7..4ee0f3ca6e10 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/DbScopeFactoryTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.Managed.Tests/DbScopeFactoryTests.cs @@ -102,8 +102,8 @@ public async Task CreateDbCommandScope_ReturnNullForAdoNetDisabledIntegration(Ty var tracerSettings = TracerSettings.Create(new() { - { string.Format(IntegrationSettings.IntegrationEnabled, integrationName), "true" }, - { string.Format(IntegrationSettings.IntegrationEnabled, nameof(IntegrationId.AdoNet)), "false" }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, integrationName), "true" }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, nameof(IntegrationId.AdoNet)), "false" }, }); await using var tracer = TracerHelper.CreateWithFakeAgent(tracerSettings); @@ -750,7 +750,7 @@ private static ScopedTracer CreateTracerWithIntegrationEnabled(string integratio // Set up tracer var tracerSettings = TracerSettings.Create(new() { - { string.Format(IntegrationSettings.IntegrationEnabled, integrationName), enabled }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, integrationName), enabled }, }); return TracerHelper.Create(tracerSettings); } diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs index 79074ab882d7..35c0a10d9a1e 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs @@ -90,7 +90,7 @@ public void SettingsRespectsOverride(bool initiallyEnabled) var name = nameof(IntegrationId.Kafka); var source = new NameValueConfigurationSource(new() { - { string.Format(IntegrationSettings.IntegrationEnabled, name), initiallyEnabled.ToString() }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, name), initiallyEnabled.ToString() }, }); var settings = new IntegrationSettings(name, source: source, isExplicitlyDisabled: true); @@ -105,7 +105,7 @@ public void SettingsRespectsOriginalIfNotOverridden(bool initiallyEnabled) var name = nameof(IntegrationId.Kafka); var source = new NameValueConfigurationSource(new() { - { string.Format(IntegrationSettings.IntegrationEnabled, name), initiallyEnabled.ToString() }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, name), initiallyEnabled.ToString() }, }); var settings = new IntegrationSettings(name, source: source, isExplicitlyDisabled: false); diff --git a/tracer/test/Datadog.Trace.Tests/Configuration/Telemetry/ConfigurationBuilderTests.cs b/tracer/test/Datadog.Trace.Tests/Configuration/Telemetry/ConfigurationBuilderTests.cs index db61d2e95271..b3b6252dcc66 100644 --- a/tracer/test/Datadog.Trace.Tests/Configuration/Telemetry/ConfigurationBuilderTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Configuration/Telemetry/ConfigurationBuilderTests.cs @@ -35,7 +35,8 @@ public IConfigurationSource GetSource(IDictionary values) var data = new NameValueCollection(); foreach (var kvp in values) { - data.Add(kvp.Key, kvp.Value?.ToString()); + // use FormattableString.Invariant as europeans might have 1.23.ToString()=1,23 which makes tests fail + data.Add(kvp.Key, kvp.Value is null ? null : FormattableString.Invariant($"{kvp.Value}")); } return new NameValueConfigurationSource(data); diff --git a/tracer/test/Datadog.Trace.Tests/Logging/DatadogLoggingFactoryTests.cs b/tracer/test/Datadog.Trace.Tests/Logging/DatadogLoggingFactoryTests.cs index 7ec11ae82ed5..284691ad1123 100644 --- a/tracer/test/Datadog.Trace.Tests/Logging/DatadogLoggingFactoryTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Logging/DatadogLoggingFactoryTests.cs @@ -32,7 +32,7 @@ public void UsesLogDirectoryWhenItExists(string obsoleteLogDirectory) { { ConfigurationKeys.LogDirectory, logDirectory }, #pragma warning disable CS0618 - { ConfigurationKeys.ProfilerLogPath, obsoleteLogDirectory }, + { DeprecationConstants.ProfilerLogPath, obsoleteLogDirectory }, #pragma warning restore CS0618 }); @@ -55,7 +55,7 @@ public void UsesObsoleteLogDirectoryWhenAvailable(string logDirectory) { { ConfigurationKeys.LogDirectory, logDirectory }, #pragma warning disable CS0618 - { ConfigurationKeys.ProfilerLogPath, obsoleteLogPath }, + { DeprecationConstants.ProfilerLogPath, obsoleteLogPath }, #pragma warning restore CS0618 }); @@ -76,7 +76,7 @@ public void UsesEnvironmentFallBackWhenBothNull(string logDirectory, string obso { { ConfigurationKeys.LogDirectory, logDirectory }, #pragma warning disable CS0618 - { ConfigurationKeys.ProfilerLogPath, obsoleteLogDirectory }, + { DeprecationConstants.ProfilerLogPath, obsoleteLogDirectory }, #pragma warning restore CS0618 }); diff --git a/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/ManualInstrumentationLegacyConfigurationSourceTests.cs b/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/ManualInstrumentationLegacyConfigurationSourceTests.cs index 1dec3714089e..ccad1421e844 100644 --- a/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/ManualInstrumentationLegacyConfigurationSourceTests.cs +++ b/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/ManualInstrumentationLegacyConfigurationSourceTests.cs @@ -31,7 +31,7 @@ public void GetIntegrationEnabled_SupportedValues_ReturnsExpectedValues(int id) { var integrationId = (IntegrationId)id; var name = IntegrationRegistry.GetName(integrationId).ToUpperInvariant(); - var enabledKey = string.Format(IntegrationSettings.IntegrationEnabled, name); + var enabledKey = string.Format(IntegrationSettings.IntegrationEnabledKey, name); var actual = ManualInstrumentationLegacyConfigurationSource.GetIntegrationEnabled(enabledKey); @@ -57,7 +57,7 @@ public void GetIntegrationEnabled_ForUnsupportedValues_ReturnsNull(int id) { var integrationId = (IntegrationId)id; var name = IntegrationRegistry.GetName(integrationId).ToUpperInvariant(); - var enabledKey = string.Format(IntegrationSettings.IntegrationEnabled, name); + var enabledKey = string.Format(IntegrationSettings.IntegrationEnabledKey, name); var actual = ManualInstrumentationLegacyConfigurationSource.GetIntegrationEnabled(enabledKey); diff --git a/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/SettingsInstrumentationTests.cs b/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/SettingsInstrumentationTests.cs index 45afb8baad92..250976057a06 100644 --- a/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/SettingsInstrumentationTests.cs +++ b/tracer/test/Datadog.Trace.Tests/ManualInstrumentation/SettingsInstrumentationTests.cs @@ -341,7 +341,7 @@ private static TracerSettings GetAndAssertAutomaticTracerSettings() { ConfigurationKeys.TraceEnabled, false }, { ConfigurationKeys.TracerMetricsEnabled, true }, { ConfigurationKeys.AgentUri, "http://localhost:1234" }, - { string.Format(IntegrationSettings.IntegrationEnabled, nameof(IntegrationId.Aerospike)), "false" }, + { string.Format(IntegrationSettings.IntegrationEnabledKey, nameof(IntegrationId.Aerospike)), "false" }, { string.Format(IntegrationSettings.AnalyticsEnabledKey, nameof(IntegrationId.Grpc)), "true" }, { string.Format(IntegrationSettings.AnalyticsSampleRateKey, nameof(IntegrationId.Couchbase)), 0.5 }, }); diff --git a/tracer/test/Datadog.Trace.Tests/Telemetry/ConfigurationTests.cs b/tracer/test/Datadog.Trace.Tests/Telemetry/ConfigurationTests.cs index 18a30161d180..44362da34ba3 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/ConfigurationTests.cs +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/ConfigurationTests.cs @@ -58,6 +58,8 @@ public class ConfigurationTests "DD_INSTRUMENTATION_INSTALL_TIME", "DD_INJECTION_ENABLED", "DD_INJECT_FORCE", + // deprecated alias + "DATADOG_TRACE_AGENT_HOSTNAME_OPTIMIZED" }; // These are the keys that are used in the integration registry which are _not_ sent to telemetry, so we can ignore them