This guide explains how to add new configuration keys to the .NET Tracer. Configuration keys are automatically generated from a single YAML source file using source generators.
Configuration keys in the .NET Tracer are defined in a single source file:
tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml- Defines the configuration keys, their environment variable names, types, defaults, optional aliases, constant name overrides, and XML documentation.
Two source generators read this file at build time:
-
ConfigurationKeysGenerator- Generates the configuration key constants:ConfigurationKeys.g.cs- Main configuration keys class with all constantsConfigurationKeys.<Product>.g.cs- Product-specific partial classes (e.g.,ConfigurationKeys.OpenTelemetry.g.cs)
-
ConfigurationKeyMatcherGenerator- Generates the fallback/alias resolution logic:ConfigurationKeyMatcher.g.cs- Handles key lookups with fallback chain support
Add your new configuration key to tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml, specifying
an implementation string (A being the default one, as shown below) and specifying the product if required. Any product name
is allowed, but try to reuse the existing ones (see Common products) if it makes sense, as they will create another partial class, ie
ConfigurationKeys.ProductName.cs. Without a product name, the keys will go in the main class, ConfigurationKeys.cs.
Required fields (mandatory):
implementation: The implementation identifierAbeing the default one, it needs to match the registry implementation with the same type and default values
scope: Declares which runtime components read this variable. Valid values:managed— read only by managed (C#) code; aConfigurationKeys.*constant is generatednative— read only by native (C++) code; no C# constant is generated, but the entry is required in this registry for coverage trackingmanaged, native— read by both; a C# constant is generated
type: The type of the configuration value (for examplestring,boolean,int,decimal)default: The default value applied by the tracer when the env var is not set. Usenullif there is no default.documentation: XML documentation for the key (supports<see>,<seealso>,<c>tags; do not include<summary>tags). Required for all entries — the source generator emits a build error (DDSG0008) when missing.
Optional fields:
product: Groups the key into a product-specific partial class (e.g.,OpenTelemetry)aliases: A list of fallback environment variable names checked in order when the primary key is not foundconst_name: Overrides the auto-generated constant name (useful for backward compatibility). Formanaged, the default is PascalCase.sensitive: Marks a credential-bearing value. Usetrueonly when the configuration value itself must never be recorded in telemetry. The value must betrueorfalse(case-insensitive); any other value is a YAML parse error.
These fields are mandatory to keep the configuration registry complete and to ensure consistent behavior and documentation across products.
Example:
version: '2'
supportedConfigurations:
DD_TRACE_SAMPLE_RATE:
- implementation: A
scope: managed
type: decimal
default: null
documentation: |-
Configuration key for setting the global sampling rate.
Value should be between 0.0 and 1.0.
OTEL_EXPORTER_OTLP_TIMEOUT:
- implementation: A
scope: managed
type: int
default: null
product: OpenTelemetry
documentation: |-
Configuration key for the general OTLP export timeout in milliseconds.
Default value is 10000ms.This generates:
ConfigurationKeys.TraceSampleRate(no product)ConfigurationKeys.OpenTelemetry.ExporterOtlpTimeout(with product)
Configuration keys can have aliases that are checked in order of appearance when the primary key is not found. Add them to the aliases property of the configuration entry in supported-configurations.yaml:
supportedConfigurations:
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT:
- implementation: A
scope: managed
type: int
default: null
product: OpenTelemetry
aliases:
- OTEL_EXPORTER_OTLP_TIMEOUT
documentation: |-
Configuration key for the timeout in milliseconds for OTLP logs export.
Falls back to <see cref="ConfigurationKeys.OpenTelemetry.ExporterOtlpTimeoutMs"/> if not set.
Default value is 10000ms (10 seconds).
<seealso cref="Datadog.Trace.Configuration.TracerSettings.OtlpLogsTimeoutMs"/>How it works:
- The configuration system first looks for
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT - If not found, it automatically checks
OTEL_EXPORTER_OTLP_TIMEOUT(the alias) - If still not found, it uses the default value
The ConfigKeyAliasesSwitcherGenerator source generator automatically generates the alias resolution logic from the aliases field. No additional code is needed - just use the primary configuration key constant and the aliases are handled transparently.
Use cases:
- Specific → General fallback: A specific key (e.g., logs timeout) falls back to a general key (e.g., overall timeout)
- Backward compatibility: Renamed keys can fall back to their old names to maintain compatibility
- Hierarchical configuration: More specific settings fall back to broader settings
By default, the source generator automatically converts environment variable names to PascalCase constant names:
DD_TRACE_ENABLED→TraceEnabledOTEL_EXPORTER_OTLP_TIMEOUT→ExporterOtlpTimeout
If you need to explicitly control the constant name (e.g., for backward compatibility), add a const_name field to the configuration entry in supported-configurations.yaml:
supportedConfigurations:
DD_YOUR_CUSTOM_KEY:
- implementation: A
scope: managed
type: string
default: null
const_name: YourPreferredConstantName
documentation: Your documentation here.Note: The const_name field exists primarily for backward compatibility with existing constant names. For new
keys, it's recommended to let the generator automatically deduce the name from the environment variable, unless the
result is not acceptable.
Build the Datadog.Trace project to run the source generator, either using Nuke or by building the project directly from the command line or your IDE:
# From repository root
dotnet build tracer/src/Datadog.Trace/Datadog.Trace.csprojThe generator will create/update files in:
tracer/src/Datadog.Trace/Generated/<tfm>/Datadog.Trace.SourceGenerators/ConfigurationKeysGenerator/
Generated files:
ConfigurationKeys.g.cs- Main file with all keysConfigurationKeys.<Product>.g.cs- Product-specific partial classes (if usingproductfield)
After building, you can use the generated constant in your code:
// Without product grouping
var enabled = source.GetBool(ConfigurationKeys.TraceEnabled);
// With product grouping
var timeout = source.GetInt32(ConfigurationKeys.OpenTelemetry.ExporterOtlpLogsTimeout);Note: The generated constants are in the Datadog.Trace.Configuration namespace.
The codebase includes Roslyn analyzers that enforce the use of configuration keys from the ConfigurationKeys classes:
ConfigurationBuilderWithKeysAnalyzer- Enforces thatConfigurationBuilder.WithKeys()method calls only accept string constants fromConfigurationKeysorPlatformKeysclasses, not hardcoded strings or variables.
For keys marked sensitive: true, the analyzer also enforces telemetry redaction at compile time. Read a sensitive string through AsRedactedString() or AsRedactedStringResult(). Use AsRedactedDictionaryResult() for dictionary-valued settings, or AsStringResult(..., recordValue: false) when the explicit false is a compile-time constant. Other accessors and storing the intermediate WithKeys() result are rejected because they could record the value.
var apiKey = config.WithKeys(ConfigurationKeys.ApiKey).AsRedactedString();
var result = config.WithKeys(ConfigurationKeys.ApiKey)
.AsStringResult(validator: null, converter: null, recordValue: false);
var headers = config.WithKeys(ConfigurationKeys.OpenTelemetry.ExporterOtlpLogsHeaders)
.AsRedactedDictionaryResult(separator: '=');Aliases use the normal WithKeys() fallback chain. When a sensitive primary key falls back to an alias, the selected value remains redacted because the redacted accessor records no value in telemetry.
- DD0007: Triggers when hardcoded string literals are used instead of configuration key constants
- DD0008: Triggers when variables or expressions are used instead of configuration key constants
- DD0015: Triggers when a sensitive configuration key is not read through
AsRedactedString,AsRedactedStringResult,AsRedactedDictionaryResult, orAsStringResultwith compile-timerecordValue: false - DD0016: Triggers when the analyzer cannot load exactly one valid
supported-configurations.yamladditional file
EnvironmentGetEnvironmentVariableAnalyzer- Enforces thatEnvironmentHelpers.GetEnvironmentVariable()and related methods only accept constants fromConfigurationKeysorPlatformKeysclasses.
- DD0011: Triggers when hardcoded string literals are used instead of configuration key constants
- DD0012: Triggers when variables or expressions are used instead of configuration key constants
- Banned API Analyzer - Uses Microsoft's
BannedApiAnalyzerspackage to prevent direct usage ofSystem.Environment.GetEnvironmentVariable()throughout the codebase.
Configuration:
BannedSymbols.txt(tracer/src/Datadog.Trace.Tools.Analyzers/ConfigurationAnalyzers/BannedSymbols.txt) - Defines banned APIs with custom error messages.editorconfig- Configures RS0030 diagnostic severity as error, with exceptions for vendored code andEnvironmentConfigurationSource.cs
- RS0030: Triggers when banned APIs are used (e.g.,
System.Environment.GetEnvironmentVariable())
These analyzers help prevent typos and ensure consistency across the codebase by enforcing compile-time validation of configuration keys.
- Verify generation: Check that your key appears in the generated files
- Integration tests: Test the configuration key in real scenarios where it's used
- Documentation: Verify the
documentationfield renders correctly in the generated XML docs
Note: Configuration keys are reported in telemetry with their raw names; the Datadog backend handles normalization, so there is no local normalization rules file to update.
Use the product field to organize related keys into nested classes:
supportedConfigurations:
OTEL_EXPORTER_OTLP_ENDPOINT:
- implementation: A
scope: managed
type: string
default: null
product: OpenTelemetry
documentation: Configuration key for the OTLP exporter endpoint.Generates: ConfigurationKeys.OpenTelemetry.ExporterOtlpEndpoint
OpenTelemetry- OpenTelemetry-related keysCIVisibility- CI Visibility keysTelemetry- Telemetry configurationAppSec- Application SecurityDebugger- Dynamic InstrumentationIast- Interactive Application Security TestingFeatureFlags- Feature flag togglesProxy- Proxy configurationDebug- Debug/diagnostic keys
supported-configurations.yaml:
supportedConfigurations:
DD_TRACE_SAMPLE_RATE:
- implementation: A
scope: managed
type: decimal
default: null
documentation: |-
Configuration key for setting the global sampling rate.
Value should be between 0.0 and 1.0.
Default value is 1.0 (100% sampling).
<seealso cref="Datadog.Trace.Configuration.TracerSettings.GlobalSamplingRate"/>Usage:
var rate = source.GetDouble(ConfigurationKeys.GlobalSamplingRate);supported-configurations.yaml:
supportedConfigurations:
OTEL_EXPORTER_OTLP_LOGS_TIMEOUT:
- implementation: A
scope: managed
type: int
default: null
product: OpenTelemetry
aliases:
- OTEL_EXPORTER_OTLP_TIMEOUT
documentation: |-
Configuration key for the timeout in milliseconds for OTLP logs export.
Falls back to <see cref="ConfigurationKeys.OpenTelemetry.ExporterOtlpTimeout"/> if not set.
Default value is 10000ms.
<seealso cref="Datadog.Trace.Configuration.TracerSettings.OtlpLogsTimeoutMs"/>
OTEL_EXPORTER_OTLP_TIMEOUT:
- implementation: A
scope: managed
type: int
default: null
product: OpenTelemetry
documentation: |-
Configuration key for the general OTLP export timeout in milliseconds.
Used as alias for specific timeout configurations.
Default value is 10000ms.Usage:
// Reads OTEL_EXPORTER_OTLP_LOGS_TIMEOUT, automatically falls back to OTEL_EXPORTER_OTLP_TIMEOUT
var timeout = source.GetInt32(ConfigurationKeys.OpenTelemetry.ExporterOtlpLogsTimeout);supported-configurations.yaml:
supportedConfigurations:
DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED:
- implementation: A
scope: managed
type: boolean
default: 'true'
product: FeatureFlags
documentation: |-
Enables generating 128-bit trace ids instead of 64-bit trace ids.
Note that a 128-bit trace id may be received from an upstream service or from
an Activity even if we are not generating them ourselves.
Default value is <c>true</c> (enabled).Usage:
var enabled = source.GetBool(ConfigurationKeys.FeatureFlags.TraceId128BitGenerationEnabled);Solution: Clean and rebuild:
dotnet clean tracer/src/Datadog.Trace/Datadog.Trace.csproj
dotnet build tracer/src/Datadog.Trace/Datadog.Trace.csprojCheck:
- YAML key matches the environment variable name exactly (case-sensitive)
- YAML syntax is valid (proper indentation, correct field names)
- Build succeeded without errors
- Looking in the correct namespace/product class
Check:
- The
documentationfield is present in the configuration entry - YAML syntax is correct (proper indentation, pipe
|or|-for multi-line) - XML tags are properly closed
- Rebuild after YAML changes
Check:
- Alias key exists as its own entry in
supportedConfigurations aliaseslist is in correct order (first alias is tried first)- Both
ConfigurationKeysGeneratorandConfigKeyAliasesSwitcherGeneratorran successfully during build
- Source generators:
tracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigurationKeysGenerator.cs- Generates configuration key constantstracer/src/Datadog.Trace.SourceGenerators/Configuration/ConfigKeyAliasesSwitcherGenerator.cs- Generates alias resolution logic
- Configuration source:
tracer/src/Datadog.Trace/Configuration/supported-configurations.yaml- Single source of truth for all configuration keys, aliases, constant name overrides, and documentation - Generated output:
tracer/src/Datadog.Trace/Generated/<tfm>/Datadog.Trace.SourceGenerators/