Skip to content

[Config Registry] 7/8 Integration names to keys #7937

Merged
anna-git merged 4 commits intomasterfrom
anna/config-inversion-integration-names-to-keys-7
Jan 27, 2026
Merged

[Config Registry] 7/8 Integration names to keys #7937
anna-git merged 4 commits intomasterfrom
anna/config-inversion-integration-names-to-keys-7

Conversation

@anna-git
Copy link
Contributor

@anna-git anna-git commented Dec 10, 2025

Context

Part of Configuration Inversion (Step 6) - Stack progress:

  1. #7548 - Add GitLab step and JSON configuration file
  2. #7688 - Cleanup configuration / platform keys + source generator
  3. #7698 - Aliases handling via source generator
  4. #7689 - Analyzers for platform and ConfigurationBuilder
  5. #7931 - Replace manual ConfigurationKeys by generated ones in the whole solution
  6. #7932 - Forbid use of System.Environment methods and adapt everywhere
  7. #7937 - Integration names to generated keys (this PR)

Summary of changes

Extends the EnumExtensionsGenerator to generate IntegrationNameToKeys class for the IntegrationId enum, providing centralized configuration key mapping for integrations including enabled, analytics enabled, and analytics sample rate keys. Also fixes AdoNet instrumentation compilation error.

Reason for change

  • Eliminates code duplication in configuration key generation across the codebase
  • Provides compile-time safety for integration configuration key access
  • Centralizes key pattern definitions with proper documentation
  • Ensures consistency across all integration key formats (canonical, mixed case, short aliases)

Implementation details

  • Source Generator: Extended EnumExtensionsGenerator with GenerateIntegrationNameToKeys method that generates:
    • AllIntegrationEnabledKeys array containing all enabled configuration keys
    • GetIntegrationEnabledKeys(string) - returns enabled keys for an integration
    • GetIntegrationAnalyticsEnabledKeys(string) - returns analytics enabled keys (marked obsolete)
    • GetIntegrationAnalyticsSampleRateKeys(string) - returns analytics sample rate keys (marked obsolete)
    • Key pattern constants (IntegrationEnabledKeyPattern, AnalyticsEnabledKeyPattern, AnalyticsSampleRateKeyPattern)
  • Configuration: Updated ConfigurationBuilder.WithIntegrationAnalyticsKey and WithIntegrationAnalyticsSampleRateKey to use generated methods

Test coverage

  • Added CanGenerateIntegrationNameToKeysForIntegrationId - verifies complete generated output with all three methods
  • Added DoesNotGenerateIntegrationNameToKeysForNonIntegrationIdEnum - ensures generation only for IntegrationId enum
  • Added IntegrationNameToKeysGeneratesCorrectKeyFormats - validates key formats for various integration names
  • All tests verify obsolete attributes, key patterns, and switch expression logic

@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from dad2367 to f18f8e4 Compare December 10, 2025 11:44
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from e1c988c to ccacb2d Compare December 10, 2025 11:44
@anna-git anna-git changed the title Anna/config inversion integration names to keys 7 [Config Registry] 7/7 Integration names to keys Dec 10, 2025
@dd-trace-dotnet-ci-bot
Copy link

dd-trace-dotnet-ci-bot bot commented Dec 10, 2025

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (7937) and master.

✅ No regressions detected - check the details below

Full Metrics Comparison

FakeDbCommand

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration68.29 ± (68.31 - 68.51) ms68.61 ± (68.63 - 68.85) ms+0.5%✅⬆️
.NET Framework 4.8 - Bailout
duration72.34 ± (72.33 - 72.51) ms72.52 ± (72.38 - 72.69) ms+0.3%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1003.37 ± (1013.75 - 1025.63) ms1014.27 ± (1021.26 - 1030.34) ms+1.1%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms21.82 ± (21.79 - 21.85) ms21.77 ± (21.75 - 21.80) ms-0.2%
process.time_to_main_ms78.66 ± (78.52 - 78.80) ms78.77 ± (78.63 - 78.91) ms+0.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.91 ± (10.91 - 10.92) MB10.90 ± (10.90 - 10.91) MB-0.1%
runtime.dotnet.threads.count12 ± (12 - 12)12 ± (12 - 12)+0.0%
.NET Core 3.1 - Bailout
process.internal_duration_ms21.84 ± (21.82 - 21.86) ms21.83 ± (21.80 - 21.85) ms-0.1%
process.time_to_main_ms79.85 ± (79.75 - 79.95) ms79.81 ± (79.74 - 79.89) ms-0.0%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.94 ± (10.93 - 10.94) MB10.94 ± (10.93 - 10.94) MB-0.0%
runtime.dotnet.threads.count13 ± (13 - 13)13 ± (13 - 13)+0.0%
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms238.88 ± (235.19 - 242.58) ms246.05 ± (242.71 - 249.40) ms+3.0%✅⬆️
process.time_to_main_ms469.76 ± (469.13 - 470.39) ms475.38 ± (474.78 - 475.98) ms+1.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed48.46 ± (48.43 - 48.48) MB48.58 ± (48.56 - 48.61) MB+0.3%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)+0.1%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms20.67 ± (20.63 - 20.71) ms20.73 ± (20.70 - 20.75) ms+0.3%✅⬆️
process.time_to_main_ms68.49 ± (68.37 - 68.60) ms68.37 ± (68.27 - 68.48) ms-0.2%
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.62 ± (10.62 - 10.62) MB10.63 ± (10.63 - 10.64) MB+0.1%✅⬆️
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 6 - Bailout
process.internal_duration_ms20.46 ± (20.44 - 20.48) ms20.60 ± (20.58 - 20.63) ms+0.7%✅⬆️
process.time_to_main_ms68.97 ± (68.91 - 69.02) ms69.08 ± (69.01 - 69.14) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed10.67 ± (10.66 - 10.67) MB10.77 ± (10.75 - 10.79) MB+1.0%✅⬆️
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms245.72 ± (243.62 - 247.82) ms243.65 ± (240.99 - 246.32) ms-0.8%
process.time_to_main_ms447.43 ± (446.88 - 447.97) ms452.65 ± (452.21 - 453.09) ms+1.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed49.18 ± (49.15 - 49.21) MB49.40 ± (49.37 - 49.43) MB+0.5%✅⬆️
runtime.dotnet.threads.count28 ± (28 - 28)28 ± (28 - 28)-0.0%
.NET 8 - Baseline
process.internal_duration_ms18.79 ± (18.76 - 18.82) ms18.80 ± (18.78 - 18.83) ms+0.1%✅⬆️
process.time_to_main_ms67.17 ± (67.08 - 67.26) ms67.48 ± (67.37 - 67.59) ms+0.5%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.69 ± (7.68 - 7.70) MB7.66 ± (7.65 - 7.66) MB-0.4%
runtime.dotnet.threads.count10 ± (10 - 10)10 ± (10 - 10)+0.0%
.NET 8 - Bailout
process.internal_duration_ms18.79 ± (18.77 - 18.81) ms18.79 ± (18.76 - 18.81) ms-0.0%
process.time_to_main_ms68.38 ± (68.33 - 68.44) ms68.53 ± (68.47 - 68.58) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed7.76 ± (7.74 - 7.77) MB7.70 ± (7.70 - 7.71) MB-0.7%
runtime.dotnet.threads.count11 ± (11 - 11)11 ± (11 - 11)+0.0%
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms177.66 ± (176.71 - 178.60) ms177.99 ± (177.05 - 178.92) ms+0.2%✅⬆️
process.time_to_main_ms430.11 ± (429.35 - 430.88) ms434.82 ± (434.20 - 435.43) ms+1.1%✅⬆️
runtime.dotnet.exceptions.count0 ± (0 - 0)0 ± (0 - 0)+0.0%
runtime.dotnet.mem.committed36.61 ± (36.58 - 36.64) MB36.65 ± (36.61 - 36.68) MB+0.1%✅⬆️
runtime.dotnet.threads.count27 ± (26 - 27)27 ± (27 - 27)+0.5%✅⬆️

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration194.42 ± (194.23 - 195.02) ms193.80 ± (193.58 - 194.28) ms-0.3%
.NET Framework 4.8 - Bailout
duration197.03 ± (197.01 - 197.53) ms197.79 ± (197.63 - 198.50) ms+0.4%✅⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1120.70 ± (1125.52 - 1134.88) ms1144.24 ± (1148.26 - 1158.15) ms+2.1%✅⬆️
.NET Core 3.1 - Baseline
process.internal_duration_ms189.75 ± (189.38 - 190.11) ms187.89 ± (187.53 - 188.25) ms-1.0%
process.time_to_main_ms82.07 ± (81.82 - 82.31) ms81.38 ± (81.17 - 81.59) ms-0.8%
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.07 ± (16.05 - 16.09) MB16.13 ± (16.11 - 16.16) MB+0.4%✅⬆️
runtime.dotnet.threads.count20 ± (20 - 20)20 ± (20 - 20)+0.3%✅⬆️
.NET Core 3.1 - Bailout
process.internal_duration_ms187.27 ± (187.00 - 187.55) ms187.63 ± (187.32 - 187.94) ms+0.2%✅⬆️
process.time_to_main_ms82.38 ± (82.24 - 82.52) ms82.58 ± (82.44 - 82.73) ms+0.2%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed16.12 ± (16.09 - 16.15) MB16.11 ± (16.08 - 16.14) MB-0.1%
runtime.dotnet.threads.count21 ± (21 - 21)21 ± (21 - 21)+0.4%✅⬆️
.NET Core 3.1 - CallTarget+Inlining+NGEN
process.internal_duration_ms436.66 ± (433.97 - 439.35) ms426.69 ± (423.51 - 429.86) ms-2.3%
process.time_to_main_ms473.95 ± (473.47 - 474.44) ms480.84 ± (480.19 - 481.50) ms+1.5%✅⬆️
runtime.dotnet.exceptions.count3 ± (3 - 3)3 ± (3 - 3)+0.0%
runtime.dotnet.mem.committed58.65 ± (58.54 - 58.75) MB58.93 ± (58.81 - 59.06) MB+0.5%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 30)29 ± (29 - 30)+0.0%✅⬆️
.NET 6 - Baseline
process.internal_duration_ms192.67 ± (192.25 - 193.09) ms192.65 ± (192.30 - 193.00) ms-0.0%
process.time_to_main_ms70.28 ± (70.09 - 70.46) ms70.79 ± (70.56 - 71.01) ms+0.7%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.16 ± (16.04 - 16.28) MB16.05 ± (15.91 - 16.20) MB-0.7%
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (18 - 19)-1.3%
.NET 6 - Bailout
process.internal_duration_ms191.44 ± (191.16 - 191.71) ms191.39 ± (191.09 - 191.70) ms-0.0%
process.time_to_main_ms71.25 ± (71.13 - 71.37) ms71.22 ± (71.06 - 71.38) ms-0.0%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed16.13 ± (15.99 - 16.28) MB15.80 ± (15.63 - 15.97) MB-2.1%
runtime.dotnet.threads.count20 ± (20 - 20)19 ± (19 - 19)-3.3%
.NET 6 - CallTarget+Inlining+NGEN
process.internal_duration_ms438.23 ± (434.83 - 441.63) ms443.87 ± (440.53 - 447.21) ms+1.3%✅⬆️
process.time_to_main_ms451.61 ± (451.03 - 452.19) ms458.03 ± (457.50 - 458.56) ms+1.4%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed59.10 ± (58.96 - 59.23) MB58.98 ± (58.85 - 59.11) MB-0.2%
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)-0.0%
.NET 8 - Baseline
process.internal_duration_ms189.98 ± (189.60 - 190.37) ms190.05 ± (189.73 - 190.36) ms+0.0%✅⬆️
process.time_to_main_ms70.24 ± (70.02 - 70.46) ms70.19 ± (70.01 - 70.37) ms-0.1%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.72 ± (11.69 - 11.75) MB11.75 ± (11.72 - 11.78) MB+0.3%✅⬆️
runtime.dotnet.threads.count18 ± (18 - 18)18 ± (18 - 18)-0.5%
.NET 8 - Bailout
process.internal_duration_ms189.37 ± (189.09 - 189.66) ms189.55 ± (189.30 - 189.80) ms+0.1%✅⬆️
process.time_to_main_ms71.16 ± (71.03 - 71.29) ms71.09 ± (70.95 - 71.23) ms-0.1%
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed11.76 ± (11.73 - 11.78) MB11.80 ± (11.78 - 11.83) MB+0.4%✅⬆️
runtime.dotnet.threads.count19 ± (19 - 19)19 ± (19 - 19)+0.2%✅⬆️
.NET 8 - CallTarget+Inlining+NGEN
process.internal_duration_ms366.50 ± (364.91 - 368.09) ms367.86 ± (366.12 - 369.60) ms+0.4%✅⬆️
process.time_to_main_ms435.58 ± (434.92 - 436.24) ms442.33 ± (441.46 - 443.20) ms+1.6%✅⬆️
runtime.dotnet.exceptions.count4 ± (4 - 4)4 ± (4 - 4)+0.0%
runtime.dotnet.mem.committed48.26 ± (48.22 - 48.29) MB48.29 ± (48.25 - 48.32) MB+0.1%✅⬆️
runtime.dotnet.threads.count29 ± (29 - 29)29 ± (29 - 29)-0.3%
Comparison explanation

Execution-time benchmarks measure the whole time it takes to execute a program, and are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are highlighted in **red**. The following thresholds were used for comparing the execution times:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard.

Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph).

Duration charts
FakeDbCommand (.NET Framework 4.8)
gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (69ms)  : 67, 70
    master - mean (68ms)  : 67, 70

    section Bailout
    This PR (7937) - mean (73ms)  : 71, 74
    master - mean (72ms)  : 72, 73

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (1,026ms)  : 960, 1091
    master - mean (1,020ms)  : 931, 1109

Loading
FakeDbCommand (.NET Core 3.1)
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (106ms)  : 103, 109
    master - mean (106ms)  : 103, 108

    section Bailout
    This PR (7937) - mean (107ms)  : 106, 108
    master - mean (107ms)  : 106, 108

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (747ms)  : 697, 798
    master - mean (734ms)  : 673, 795

Loading
FakeDbCommand (.NET 6)
gantt
    title Execution time (ms) FakeDbCommand (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (94ms)  : 92, 96
    master - mean (94ms)  : 92, 96

    section Bailout
    This PR (7937) - mean (94ms)  : 93, 95
    master - mean (94ms)  : 93, 95

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (721ms)  : 670, 772
    master - mean (719ms)  : 686, 753

Loading
FakeDbCommand (.NET 8)
gantt
    title Execution time (ms) FakeDbCommand (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (92ms)  : 90, 95
    master - mean (92ms)  : 90, 94

    section Bailout
    This PR (7937) - mean (93ms)  : 92, 94
    master - mean (93ms)  : 92, 94

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (639ms)  : 627, 652
    master - mean (637ms)  : 618, 655

Loading
HttpMessageHandler (.NET Framework 4.8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (194ms)  : 191, 197
    master - mean (195ms)  : 190, 199

    section Bailout
    This PR (7937) - mean (198ms)  : 194, 202
    master - mean (197ms)  : 195, 200

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (1,153ms)  : 1081, 1225
    master - mean (1,130ms)  : 1063, 1197

Loading
HttpMessageHandler (.NET Core 3.1)
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (278ms)  : 271, 285
    master - mean (280ms)  : 272, 288

    section Bailout
    This PR (7937) - mean (279ms)  : 275, 282
    master - mean (278ms)  : 275, 281

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (942ms)  : 898, 986
    master - mean (940ms)  : 905, 976

Loading
HttpMessageHandler (.NET 6)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (272ms)  : 267, 277
    master - mean (271ms)  : 266, 277

    section Bailout
    This PR (7937) - mean (271ms)  : 267, 275
    master - mean (271ms)  : 267, 274

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (932ms)  : 882, 983
    master - mean (919ms)  : 868, 969

Loading
HttpMessageHandler (.NET 8)
gantt
    title Execution time (ms) HttpMessageHandler (.NET 8)
    dateFormat  x
    axisFormat %Q
    todayMarker off
    section Baseline
    This PR (7937) - mean (270ms)  : 265, 276
    master - mean (270ms)  : 264, 276

    section Bailout
    This PR (7937) - mean (270ms)  : 266, 274
    master - mean (270ms)  : 266, 275

    section CallTarget+Inlining+NGEN
    This PR (7937) - mean (841ms)  : 822, 860
    master - mean (834ms)  : 812, 856

Loading

@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from f18f8e4 to 303b602 Compare December 10, 2025 13:09
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from ccacb2d to cf34d67 Compare December 10, 2025 13:09
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 303b602 to 70df7c9 Compare December 10, 2025 14:26
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from cf34d67 to c8caa83 Compare December 10, 2025 14:26
@datadog-official

This comment has been minimized.

anna-git added a commit that referenced this pull request Dec 10, 2025
…nes in the whole solution (#7931)

(This PR is actually
#7697 that accidentally
got closed)

## Context

Part of **Configuration Inversion (Step 5)** - Stack progress:
1. [#7548](#7548) - Add
GitLab step and JSON configuration file
2. [#7688](#7688) -
Cleanup configuration / platform keys + source generator
3. [#7698](#7698) -
Aliases handling via source generator
4. [#7689](#7689) -
Analyzers for platform and ConfigurationBuilder
5. **→ [#7931](#7697) -
Replace manual ConfigurationKeys by generated ones in the whole solution
(this PR)**
6. [#7932](#7932) -
Forbid use of System.Environment methods and adapt everywhere
7. [#7937](#7937) -
Integration names to generated keys

## Summary of changes

Fixed the
[ConfigurationKeysGenerator](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigurationKeysGenerator.cs:21:0-958:1)
to properly read and apply the
[configuration_keys_mapping.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/configuration_keys_mapping.json:0:0-0:0)
file, and extracted common file header comments to a reusable constant.

**Key changes:**
- Fixed JSON array extraction in
[ParseMappingFile](cci:1://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigurationKeysGenerator.cs:350:4-524:5)
method - the generator was incorrectly trying to extract the
`"mappings"` field as an object instead of an array
- Extracted configuration generator comments to
`Constants.ConfigurationGeneratorComment` for reuse across multiple
generators
- Updated both
[ConfigurationKeysGenerator](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigurationKeysGenerator.cs:21:0-958:1)
and
[ConfigKeyAliasesSwitcherGenerator](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigKeyAliasesSwitcherGenerator.cs:24:0-340:1)
to use the shared constant
- Added documentation as to how to add a key now

## Reason for change

The
[configuration_keys_mapping.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/configuration_keys_mapping.json:0:0-0:0)
file was being ignored during code generation, causing the generator to
produce incorrect constant names. This meant that any manual edits to
constant names in the mapping file were not being respected, and the
generated code would use auto-generated names instead of the explicitly
mapped ones.

Additionally, the file header comments explaining that files are
auto-generated were duplicated across generators, violating DRY
principles.

## Implementation details

1. **Fixed array extraction logic**: Replaced the call to
[JsonReader.ExtractJsonObjectSection()](cci:1://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace.SourceGenerators/Configuration/JsonReader.cs:16:4-91:5)
with custom array extraction code that:
   - Finds the `"mappings":` key in the JSON
   - Locates the opening `[` bracket
   - Tracks bracket nesting to find the matching closing `]`
   - Extracts the complete array content

2. **Resolved variable scope issue**: Reused existing `inString` and
`escapeNext` variables from the outer scope instead of redeclaring them,
fixing compilation errors.

3. **Centralized header comments**: Created
`Constants.ConfigurationGeneratorComment` containing the standardized
auto-generation notice and updated both generators to use it.

## Test coverage

- Verified the generator builds successfully without errors
- The mapping file is now properly parsed and applied during code
generation
- Generated constant names now match the mappings defined in
[configuration_keys_mapping.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/configuration_keys_mapping.json:0:0-0:0)

## Other details

This fix ensures that the explicit naming conventions defined in
[configuration_keys_mapping.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/configuration_keys_mapping.json:0:0-0:0)
are respected, maintaining consistency with the existing codebase and
preventing future confusion when constant names don't match their
expected values.

---------

Co-authored-by: Andrew Lock <andrew.lock@datadoghq.com>
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 70df7c9 to d197570 Compare December 10, 2025 18:01
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from c8caa83 to 85c37d3 Compare December 10, 2025 18:01
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from d197570 to 272e31a Compare December 10, 2025 19:02
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from 85c37d3 to bea964f Compare December 10, 2025 19:02
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 272e31a to c89c676 Compare December 10, 2025 19:35
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from bea964f to d62b438 Compare December 10, 2025 19:35
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from c89c676 to 41c88a5 Compare December 11, 2025 10:58
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from d62b438 to ae8195d Compare December 11, 2025 10:58
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 41c88a5 to e091036 Compare December 23, 2025 19:35
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from ae8195d to 2a87981 Compare December 23, 2025 19:35
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from e091036 to b7ac294 Compare December 23, 2025 19:42
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from 2a87981 to c14af6e Compare December 23, 2025 19:42
@anna-git anna-git changed the title [Config Registry] 7/7 Integration names to keys [Config Registry] 7/8 Integration names to keys Dec 23, 2025
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from b7ac294 to f164b06 Compare January 5, 2026 13:37
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from c14af6e to 99e80f7 Compare January 5, 2026 13:37
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from f164b06 to 756c6b3 Compare January 5, 2026 14:27
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from 99e80f7 to 0d9d4be Compare January 5, 2026 14:27
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 756c6b3 to 60360fa Compare January 8, 2026 16:01
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 8461312 to be89b22 Compare January 13, 2026 12:36
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch 2 times, most recently from 9227c7e to a1ceb97 Compare January 14, 2026 10:20
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 353984d to de53524 Compare January 14, 2026 10:47
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch 2 times, most recently from 0af9145 to d16d6c6 Compare January 14, 2026 19:41
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from 26977ff to db36d61 Compare January 14, 2026 19:47
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from d16d6c6 to ff1db4e Compare January 14, 2026 19:47
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from db36d61 to 46a9848 Compare January 15, 2026 11:47
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from ff1db4e to 1bb6dc6 Compare January 15, 2026 11:47
Copy link
Member

@andrewlock andrewlock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in principal, but I think we need to make some tweaks to the generated code

context.AddSource(enumToGenerate.ExtensionsName + "_EnumExtensions.g.cs", SourceText.From(result, Encoding.UTF8));

// If this is the IntegrationId enum, also generate IntegrationNameToKeys
if (enumToGenerate.FullyQualifiedName == "Datadog.Trace.Configuration.IntegrationId")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels so hacky, but I love it 😂

sb.AppendLine(Constants.FileHeader);
sb.AppendLine("namespace Datadog.Trace.Configuration");
sb.AppendLine("{");
sb.AppendLine(" /// <summary>");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks neat, but doing these as individual sb.AppendLine is very expensive. You want to do as big a block as you can in general, so raw strings are the best option generally.

e.g.

sb.AppendLine(
Constants.FileHeader + // as long as this is a constant, the concat happens at compile time
"""

namespace Datadog.Trace.Configuration
{
    /// Generated mapping of integration names to their configuration keys.");
    /// </summary>");
    internal static partial class IntegrationNameToKeys");
    {
        private const string ObsoleteMessage = DeprecationMessages.AppAnalytics;");

        /// <summary>");
        /// All integration enabled keys (canonical + aliases).");
        /// </summary>");
        public static readonly string[] AllIntegrationEnabledKeys = new[]");
        {
""");

etc

It also means you don't need to escape anything, just copy-paste the code you expect in there, and "break out" where you need something specific (like the actual values) 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! chhanged in e33db01

Comment on lines +90 to +91
// Single loop to build array keys and all switch cases
foreach (var member in enumToGenerate.Names)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, I would have just iterated it 3 times, and append to the same stringbuilder instead of having multiple builders. The iteration is low overhead compared to the stringbuilder (which will each have to grow their internal array multiple times)

Copy link
Contributor Author

@anna-git anna-git Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep thank you changed in e33db01

Comment on lines +148 to +152
sb.AppendLine(" {");
sb.AppendLine(" string.Format(\"DD_TRACE_{0}_ENABLED\", integrationName.ToUpperInvariant()),");
sb.AppendLine(" string.Format(\"DD_TRACE_{0}_ENABLED\", integrationName),");
sb.AppendLine(" $\"DD_{integrationName}_ENABLED\"");
sb.AppendLine(" }");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting one tbh, do we even need this branch 🤔 Given we handle this at compile time, we know it will never be called. That said, throwing probably isn't great.

We might want to generate something more like this:

_ => GetEnabledFallbackFor(integrationName),

because it should generate smaller code, which has more chance of optimization, and the fallback will never be invoked,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks changed in e33db01

_source,
_telemetry,
integrationEnabledKeys[0],
integrationEnabledKeys.Skip(1).ToArray());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh no, Skip(1).ToArray() 🙁 We definitely don't want to do that, If we're going to need to do that, we should change the GetIntegrationEnabledKeys() API to return an array of the correct size (e.g. a "main" key plus an array of fallbacks).

If possible we should probably try to get away from using arrays at all... we may be able to use ReadOnlySpan<string> in some places, or we should use InlineArray (if we can), or worse case we should create a specialized type to avoid creating all these small arrays if possible.

Copy link
Contributor Author

@anna-git anna-git Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very good point fixed in e33db01

{
return integrationName switch
{
"HttpMessageHandler" => new[] { "DD_TRACE_HTTPMESSAGEHANDLER_ENABLED", "DD_TRACE_HttpMessageHandler_ENABLED", "DD_HttpMessageHandler_ENABLED" },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use collection expressions wherever possible

Suggested change
"HttpMessageHandler" => new[] { "DD_TRACE_HTTPMESSAGEHANDLER_ENABLED", "DD_TRACE_HttpMessageHandler_ENABLED", "DD_HttpMessageHandler_ENABLED" },
"HttpMessageHandler" => ["DD_TRACE_HTTPMESSAGEHANDLER_ENABLED", "DD_TRACE_HttpMessageHandler_ENABLED", "DD_HttpMessageHandler_ENABLED"],

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in e33db01

/// <summary>
/// All integration enabled keys (canonical + aliases).
/// </summary>
public static readonly string[] AllIntegrationEnabledKeys = new[]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, this is only called in a test. But the array will be created as soon as we call IntegrationNameToKeys.Something. We can solve that by making it a method instead (and also marking it as only to be called in tests)

Suggested change
public static readonly string[] AllIntegrationEnabledKeys = new[]
[TestingOnly]
public static readonly string[] GetAllIntegrationEnabledKeys() => new[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in e33db01

@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch 3 times, most recently from 472f9f9 to 57ec51a Compare January 19, 2026 11:51
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from b481629 to d8e691c Compare January 19, 2026 15:43
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from 57ec51a to d1c5ab9 Compare January 19, 2026 15:43
@anna-git anna-git force-pushed the anna/config-inversion-prevent-direct-env-use-6 branch from d8e691c to cafe31e Compare January 19, 2026 16:36
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from d1c5ab9 to d15b826 Compare January 19, 2026 16:36
Base automatically changed from anna/config-inversion-prevent-direct-env-use-6 to master January 20, 2026 11:03
anna-git added a commit that referenced this pull request Jan 20, 2026
…apt everywhere (#7932)

## Context

Part of **Configuration Inversion (Step 6)** - Stack progress:
1. [#7548](#7548) - Add
GitLab step and JSON configuration file
2. [#7688](#7688) -
Cleanup configuration / platform keys + source generator
3. [#7698](#7698) -
Aliases handling via source generator
4. [#7689](#7689) -
Analyzers for platform and ConfigurationBuilder
5. [#7931](#7931) -
Replace manual ConfigurationKeys by generated ones in the whole solution
6. **→ [#7932](#7932) -
Forbid use of System.Environment methods and adapt everywhere (this
PR)**
7. [#7937](#7937) -
Integration names to generated keys

I'll update the PR summary to mention the YAML documentation file:

## Summary of changes

Banned direct `System.Environment.GetEnvironmentVariable()` usage and
migrated all environment variable access to use `EnvironmentHelpers`
with strongly-typed
[ConfigurationKeys](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs:15:0-737:1)
and `PlatformKeys` constants.

### Key changes:
- **Banned `System.Environment.GetEnvironmentVariable()`** via
`BannedApiAnalyzers`
- **Added `EnvironmentGetEnvironmentVariableAnalyzer` (DD0009)** to
enforce
[ConfigurationKeys](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs:15:0-737:1)/`PlatformKeys`
usage only
- **Nested `PlatformKeys` by category** (Ci, Aws, AzureAppService,
ServiceFabric, DotNet)
- **Migrated ~50+ files** across CI Visibility, AWS Lambda, AppSec,
Telemetry, Profiler, and Agent components
- **Added missing keys** to
[supported-configurations.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/supported-configurations.json:0:0-0:0)
and their documentation to
[supported-configurations-docs.yaml](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/supported-configurations-docs.yaml:0:0-0:0)

## Reason for change

Direct `System.Environment.GetEnvironmentVariable()` calls with string
literals are error-prone. Centralizing through `EnvironmentHelpers` with
strongly-typed constants provides compile-time validation,
discoverability, and refactoring safety.

## Implementation details

1. **Banned API enforcement** - Added `BannedSymbols.txt` and configured
`.editorconfig` to treat RS0030 as error (vendored code excluded)
2. **Custom analyzer** - DD0009 validates all `EnvironmentHelpers` calls
accept only
[ConfigurationKeys](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs:15:0-737:1)/`PlatformKeys`
constants, rejecting hardcoded strings
3. **PlatformKeys organization** - Nested by category for better
discoverability
4. **EnvironmentHelpers refactoring** - Added overloads for nested class
constants, maintained backward compatibility
5. **Configuration documentation** - Added missing configuration keys to
[supported-configurations.json](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/supported-configurations.json:0:0-0:0)
and comprehensive XML documentation to
[supported-configurations-docs.yaml](cci:7://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Configuration/supported-configurations-docs.yaml:0:0-0:0),
which the source generator uses to generate XML doc comments in
[ConfigurationKeys](cci:2://file:///Users/anna.yafi/go/src/github.com/DataDog/dd-trace-dotnet3/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/ConfigurationKeys.g.cs:15:0-737:1)
classes

## Test coverage

- ✅ Comprehensive analyzer tests covering valid/invalid scenarios
- ✅ All existing unit tests pass
- ✅ Banned API analyzer correctly flags direct `System.Environment`
usage

## Other details

+2,600/-940 lines. No breaking changes, negligible performance impact.
@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch from d15b826 to 884fe46 Compare January 20, 2026 11:07
@duncanpharvey duncanpharvey removed their request for review January 20, 2026 17:35
@duncanpharvey
Copy link
Contributor

Removing @DataDog/serverless-azure-and-gcp as a reviewer since I don't see any Azure or GCP related changes. Maybe there were some changes before a force push but I don't see any now.

@anna-git anna-git force-pushed the anna/config-inversion-integration-names-to-keys-7 branch 2 times, most recently from f03a983 to 46c691d Compare January 26, 2026 19:15
@pr-commenter
Copy link

pr-commenter bot commented Jan 26, 2026

Benchmarks

Benchmark execution time: 2026-01-27 10:41:58

Comparing candidate commit 72c8d09 in PR branch anna/config-inversion-integration-names-to-keys-7 with baseline commit 7ca59f6 in branch master.

Found 5 performance improvements and 9 performance regressions! Performance is the same for 164 metrics, 14 unstable metrics.

scenario:Benchmarks.Trace.AgentWriterBenchmark.WriteAndFlushEnrichedTraces net6.0

  • 🟥 execution_time [+18.664ms; +19.008ms] or [+18.125%; +18.460%]

scenario:Benchmarks.Trace.Asm.AppSecEncoderBenchmark.EncodeLegacyArgs netcoreapp3.1

  • 🟥 execution_time [+18.406ms; +18.984ms] or [+10.108%; +10.425%]

scenario:Benchmarks.Trace.AspNetCoreBenchmark.SendRequest net6.0

  • 🟥 execution_time [+71.266ms; +73.445ms] or [+77.094%; +79.451%]

scenario:Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark.WriteAndFlushEnrichedTraces netcoreapp3.1

  • 🟥 execution_time [+21.053ms; +24.513ms] or [+15.956%; +18.578%]
  • 🟥 throughput [-148.179op/s; -110.520op/s] or [-9.395%; -7.007%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OptimizedCharSliceWithPool net6.0

  • 🟩 execution_time [-118.465µs; -113.988µs] or [-10.474%; -10.078%]
  • 🟩 throughput [+99.275op/s; +103.261op/s] or [+11.228%; +11.679%]

scenario:Benchmarks.Trace.CharSliceBenchmark.OriginalCharSlice net6.0

  • 🟥 execution_time [+101.770µs; +161.306µs] or [+5.325%; +8.439%]

scenario:Benchmarks.Trace.ILoggerBenchmark.EnrichedLog net6.0

  • 🟩 execution_time [-17.655ms; -13.832ms] or [-8.310%; -6.510%]

scenario:Benchmarks.Trace.Log4netBenchmark.EnrichedLog netcoreapp3.1

  • 🟥 execution_time [+26.205ms; +29.400ms] or [+15.081%; +16.920%]

scenario:Benchmarks.Trace.SingleSpanAspNetCoreBenchmark.SingleSpanAspNetCore netcoreapp3.1

  • 🟩 throughput [+17482691.663op/s; +18909814.087op/s] or [+7.730%; +8.361%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishSpan net6.0

  • 🟩 execution_time [-21.704ms; -17.610ms] or [-9.981%; -8.099%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes net6.0

  • 🟥 execution_time [+11.595ms; +12.211ms] or [+5.812%; +6.120%]

scenario:Benchmarks.Trace.SpanBenchmark.StartFinishTwoScopes netcoreapp3.1

  • 🟥 execution_time [+13.280ms; +18.754ms] or [+6.704%; +9.467%]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants