From d54b417f1303c96f742a37eb073148f0bd44eb2a Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Mon, 22 Sep 2025 09:29:46 +0200 Subject: [PATCH 1/7] [File-based] add Propagators --- .../EnvironmentConfigurationSdkHelper.cs | 2 +- .../PropagatorConfiguration.cs | 72 +++++++++++++++++++ .../YamlConfiguration.cs | 7 ++ .../Configurations/SdkSettings.cs | 10 ++- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs index eb29c16bd5..8e23943a75 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs @@ -12,7 +12,7 @@ public static void UseEnvironmentVariables(SdkSettings settings) SetSdkTextMapPropagator(settings.Propagators); } - private static void SetSdkTextMapPropagator(IList settingsPropagators) + private static void SetSdkTextMapPropagator(IReadOnlyList settingsPropagators) { if (settingsPropagators.Count == 0) { diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs new file mode 100644 index 0000000000..49e049e2fc --- /dev/null +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs @@ -0,0 +1,72 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Vendors.YamlDotNet.Serialization; + +namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; + +internal class PropagatorConfiguration +{ + /// + /// Gets or sets the composite propagator configuration. + /// + [YamlMember(Alias = "composite")] + public Dictionary? Composite { get; set; } + + /// + /// Gets or sets the composite list for the propagator. + /// + [YamlMember(Alias = "composite_list")] + public string? CompositeList { get; set; } + + public IReadOnlyList GetEnabledPropagators() + { + var seenPropagators = new HashSet(); + var resolvedPropagators = new List(); + var propagators = new List(); + + if (Composite != null) + { + foreach (var key in Composite.Keys) + { + if (seenPropagators.Add(key)) + { + resolvedPropagators.Add(key); + } + } + } + + if (!string.IsNullOrEmpty(CompositeList)) + { + var list = CompositeList!.Split(Constants.ConfigurationValues.Separator); + foreach (var item in list) + { + if (seenPropagators.Add(item)) + { + resolvedPropagators.Add(item); + } + } + } + + foreach (var propagatorName in resolvedPropagators) + { + switch (propagatorName.ToLowerInvariant()) + { + case Constants.ConfigurationValues.Propagators.W3CTraceContext: + propagators.Add(Propagator.W3CTraceContext); + break; + case Constants.ConfigurationValues.Propagators.W3CBaggage: + propagators.Add(Propagator.W3CBaggage); + break; + case Constants.ConfigurationValues.Propagators.B3Multi: + propagators.Add(Propagator.B3Multi); + break; + case Constants.ConfigurationValues.Propagators.B3Single: + propagators.Add(Propagator.B3Single); + break; + } + } + + return propagators; + } +} diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs index 8e0fbf259e..c12e911a78 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs @@ -22,4 +22,11 @@ internal class YamlConfiguration /// [YamlMember(Alias = "resource")] public ResourceConfiguration? Resource { get; set; } + + /// + /// Gets or sets the text map context propagator configuration. + /// If omitted, a noop propagator is used. + /// + [YamlMember(Alias = "propagator")] + public PropagatorConfiguration? Propagator { get; set; } } diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/SdkSettings.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/SdkSettings.cs index 98fdb8c10c..ce6aa61317 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/SdkSettings.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/SdkSettings.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; using OpenTelemetry.AutoInstrumentation.Logging; namespace OpenTelemetry.AutoInstrumentation.Configurations; @@ -15,14 +16,19 @@ internal class SdkSettings : Settings /// /// Gets the list of propagators to be used. /// - public IList Propagators { get; private set; } = new List(); + public IReadOnlyList Propagators { get; private set; } = []; protected override void OnLoadEnvVar(Configuration configuration) { Propagators = ParsePropagator(configuration); } - private static IList ParsePropagator(Configuration configuration) + protected override void OnLoadFile(YamlConfiguration configuration) + { + Propagators = configuration.Propagator?.GetEnabledPropagators() ?? []; + } + + private static List ParsePropagator(Configuration configuration) { var propagatorEnvVar = configuration.GetString(ConfigurationKeys.Sdk.Propagators); var propagators = new List(); From 6ae1132be31da8bf311a87e03192cdbaa935c4e1 Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Mon, 22 Sep 2025 09:47:25 +0200 Subject: [PATCH 2/7] use switch expression --- .../EnvironmentConfigurationSdkHelper.cs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs index 8e23943a75..17c022ca9e 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationSdkHelper.cs @@ -43,18 +43,13 @@ private static void SetSdkTextMapPropagator(IReadOnlyList settingsPr private static TextMapPropagator GetTextMapPropagator(Propagator propagator) { - switch (propagator) + return propagator switch { - case Propagator.W3CTraceContext: - return new TraceContextPropagator(); - case Propagator.W3CBaggage: - return new BaggagePropagator(); - case Propagator.B3Multi: - return new Extensions.Propagators.B3Propagator(singleHeader: false); - case Propagator.B3Single: - return new Extensions.Propagators.B3Propagator(singleHeader: true); - } - - throw new ArgumentOutOfRangeException(nameof(propagator), propagator, "Propagator has an unexpected value."); + Propagator.W3CTraceContext => new TraceContextPropagator(), + Propagator.W3CBaggage => new BaggagePropagator(), + Propagator.B3Multi => new Extensions.Propagators.B3Propagator(singleHeader: false), + Propagator.B3Single => new Extensions.Propagators.B3Propagator(singleHeader: true), + _ => throw new ArgumentOutOfRangeException(nameof(propagator), propagator, "Propagator has an unexpected value."), + }; } } From bc654b21cb5c0d84d0fa05b189147fa21475666d Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Tue, 23 Sep 2025 10:05:18 +0200 Subject: [PATCH 3/7] [FileBased] Add Propagator Tests --- .../FileBased/FilebasedSdkSettingsTests.cs | 89 +++++++++++++++++++ .../FileBased/Files/TestPropagatorFile.yaml | 9 ++ .../Files/TestPropagatorFileEnvVars.yaml | 4 + .../FileBased/Parser/ParserPropagatorTests.cs | 46 ++++++++++ ...Telemetry.AutoInstrumentation.Tests.csproj | 6 ++ 5 files changed, 154 insertions(+) create mode 100644 test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs create mode 100644 test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFile.yaml create mode 100644 test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFileEnvVars.yaml create mode 100644 test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPropagatorTests.cs diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs new file mode 100644 index 0000000000..8478bd6d77 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs @@ -0,0 +1,89 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.AutoInstrumentation.Configurations; +using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration; +using Xunit; + +namespace OpenTelemetry.AutoInstrumentation.Tests.Configurations.FileBased; + +public class FilebasedSdkSettingsTests +{ + [Fact] + public void LoadFile_CompositeOnlyPropagators() + { + var propagator = new PropagatorConfiguration + { + Composite = new Dictionary + { + { "tracecontext", new object() }, + { "baggage", new object() } + } + }; + + var conf = new YamlConfiguration { Propagator = propagator }; + var settings = new SdkSettings(); + + settings.LoadFile(conf); + + Assert.Equal(2, settings.Propagators.Count); + Assert.Contains(Propagator.W3CTraceContext, settings.Propagators); + Assert.Contains(Propagator.W3CBaggage, settings.Propagators); + } + + [Fact] + public void LoadFile_CompositeListOnlyPropagators() + { + var propagator = new PropagatorConfiguration + { + CompositeList = "b3multi,b3" + }; + + var conf = new YamlConfiguration { Propagator = propagator }; + var settings = new SdkSettings(); + + settings.LoadFile(conf); + + Assert.Equal(2, settings.Propagators.Count); + Assert.Contains(Propagator.B3Multi, settings.Propagators); + Assert.Contains(Propagator.B3Single, settings.Propagators); + } + + [Fact] + public void LoadFile_CompositeAndCompositeList_AreMergedWithoutDuplicates() + { + var propagator = new PropagatorConfiguration + { + Composite = new Dictionary + { + { "tracecontext", new object() }, + { "baggage", new object() } + }, + CompositeList = "tracecontext,b3" + }; + + var conf = new YamlConfiguration { Propagator = propagator }; + var settings = new SdkSettings(); + + settings.LoadFile(conf); + + Assert.Equal(3, settings.Propagators.Count); + Assert.Contains(Propagator.W3CTraceContext, settings.Propagators); + Assert.Contains(Propagator.W3CBaggage, settings.Propagators); + Assert.Contains(Propagator.B3Single, settings.Propagators); + } + + [Fact] + public void GetEnabledPropagators_UnknownValues_AreIgnored() + { + var config = new PropagatorConfiguration + { + CompositeList = "invalid,b3multi" + }; + + var result = config.GetEnabledPropagators(); + + Assert.Single(result); + Assert.Equal(Propagator.B3Multi, result[0]); + } +} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFile.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFile.yaml new file mode 100644 index 0000000000..67f0b924c1 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFile.yaml @@ -0,0 +1,9 @@ +file_format: "1.0-rc.1" + +propagator: + composite: + tracecontext: + baggage: + b3: + b3multi: + diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFileEnvVars.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFileEnvVars.yaml new file mode 100644 index 0000000000..813611f2d6 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPropagatorFileEnvVars.yaml @@ -0,0 +1,4 @@ +file_format: "1.0-rc.1" + +propagator: + composite_list: ${OTEL_PROPAGATORS} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPropagatorTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPropagatorTests.cs new file mode 100644 index 0000000000..06eed5b1d5 --- /dev/null +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPropagatorTests.cs @@ -0,0 +1,46 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Xunit; +using YamlParser = OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration.Parser.Parser; + +namespace OpenTelemetry.AutoInstrumentation.Tests.Configurations.FileBased.Parser; + +[Collection("Non-Parallel Collection")] +public class ParserPropagatorTests +{ + [Fact] + public void Parse_FullConfigYaml_ShouldPopulateModelCorrectly() + { + var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestPropagatorFile.yaml"); + + Assert.NotNull(config); + Assert.NotNull(config.Propagator); + Assert.NotNull(config.Propagator.Composite); + var composite = config.Propagator.Composite; + Assert.Null(config.Propagator.CompositeList); + + string[] expectedPropagators = [ + "tracecontext", "baggage", "b3", "b3multi", + ]; + + foreach (var expected in expectedPropagators) + { + Assert.Contains(expected, composite.Keys); + } + } + + [Fact] + public void Parse_EnvVarYaml_ShouldPopulateModelCompletely() + { + Environment.SetEnvironmentVariable("OTEL_PROPAGATORS", "tracecontext,baggage,b3,b3multi"); + + var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestPropagatorFileEnvVars.yaml"); + + Assert.NotNull(config); + Assert.NotNull(config.Propagator); + Assert.NotNull(config.Propagator.CompositeList); + Assert.Null(config.Propagator.Composite); + Assert.Equal("tracecontext,baggage,b3,b3multi", config.Propagator.CompositeList); + } +} diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj index 50c9bfa3f0..f565fcde4f 100644 --- a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj @@ -12,9 +12,15 @@ + + PreserveNewest + PreserveNewest + + PreserveNewest + PreserveNewest From 640940131619c264c6e8dba8c30827642fd8454e Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Mon, 29 Sep 2025 12:47:55 +0200 Subject: [PATCH 4/7] [File-Based] Add Propagator configuration docs --- docs/file-based-configuration.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/file-based-configuration.md b/docs/file-based-configuration.md index 9ef632ca60..acb80648b6 100644 --- a/docs/file-based-configuration.md +++ b/docs/file-based-configuration.md @@ -30,6 +30,27 @@ For more details, see: [OpenTelemetry YAML File Format Specification](https://gi ## Configuration Examples +### Propagator Configuration + +You can configure text map context propagators directly in YAML or via the +`OTEL_PROPAGATORS` environment variable. +For more details and updates, see: [Propagators list and documentation](config.md/#propagators) +To disable a propagator, comment out or remove its corresponding entry. + +``` yaml +# If no propagators are specified, none will be added automatically. +propagator: + # Composite propagators are evaluated together. + # Entries from .composite_list are appended here (duplicates are filtered out). + composite: + tracecontext: # W3C Trace Context propagator + baggage: # W3C Baggage propagator + b3: # B3 single-header propagator + b3multi: # B3 multi-header propagator + # Alternatively, configure via a comma-separated list (same format as OTEL_PROPAGATORS). + composite_list: ${OTEL_PROPAGATORS} +``` + ### Resource Configuration You can configure resource attributes directly in YAML or via the From a19d41f6eab0a79aaa6f18bafd4883ff71f9a592 Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Tue, 30 Sep 2025 11:55:10 +0200 Subject: [PATCH 5/7] Enchance GetEnabledPropagators() --- .../PropagatorConfiguration.cs | 57 ++++++------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs index 49e049e2fc..afecedab15 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PropagatorConfiguration.cs @@ -21,51 +21,28 @@ internal class PropagatorConfiguration public IReadOnlyList GetEnabledPropagators() { - var seenPropagators = new HashSet(); - var resolvedPropagators = new List(); - var propagators = new List(); - - if (Composite != null) + if (Composite is null && string.IsNullOrEmpty(CompositeList)) { - foreach (var key in Composite.Keys) - { - if (seenPropagators.Add(key)) - { - resolvedPropagators.Add(key); - } - } + return []; } - if (!string.IsNullOrEmpty(CompositeList)) - { - var list = CompositeList!.Split(Constants.ConfigurationValues.Separator); - foreach (var item in list) - { - if (seenPropagators.Add(item)) - { - resolvedPropagators.Add(item); - } - } - } + var propagatorNames = (Composite?.Keys ?? Enumerable.Empty()) + .Concat(!string.IsNullOrEmpty(CompositeList) + ? CompositeList!.Split(Constants.ConfigurationValues.Separator) + : []) + .Distinct(); - foreach (var propagatorName in resolvedPropagators) - { - switch (propagatorName.ToLowerInvariant()) + var propagators = propagatorNames + .Select(name => name switch { - case Constants.ConfigurationValues.Propagators.W3CTraceContext: - propagators.Add(Propagator.W3CTraceContext); - break; - case Constants.ConfigurationValues.Propagators.W3CBaggage: - propagators.Add(Propagator.W3CBaggage); - break; - case Constants.ConfigurationValues.Propagators.B3Multi: - propagators.Add(Propagator.B3Multi); - break; - case Constants.ConfigurationValues.Propagators.B3Single: - propagators.Add(Propagator.B3Single); - break; - } - } + Constants.ConfigurationValues.Propagators.W3CTraceContext => Propagator.W3CTraceContext, + Constants.ConfigurationValues.Propagators.W3CBaggage => Propagator.W3CBaggage, + Constants.ConfigurationValues.Propagators.B3Multi => Propagator.B3Multi, + Constants.ConfigurationValues.Propagators.B3Single => Propagator.B3Single, + _ => null + }) + .OfType() + .ToList(); return propagators; } From 62af6ffdd305abb83a068d76d5dacc66e854060f Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Tue, 30 Sep 2025 13:35:10 +0200 Subject: [PATCH 6/7] Add Empty propagator test/refactor --- .../FileBased/FilebasedSdkSettingsTests.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs index 8478bd6d77..7b272bad9f 100644 --- a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs +++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedSdkSettingsTests.cs @@ -74,16 +74,32 @@ public void LoadFile_CompositeAndCompositeList_AreMergedWithoutDuplicates() } [Fact] - public void GetEnabledPropagators_UnknownValues_AreIgnored() + public void LoadFile_GetEnabledPropagators_Empty() { - var config = new PropagatorConfiguration + var propagator = new PropagatorConfiguration(); + + var conf = new YamlConfiguration { Propagator = propagator }; + var settings = new SdkSettings(); + + settings.LoadFile(conf); + + Assert.Empty(settings.Propagators); + } + + [Fact] + public void LoadFile_GetEnabledPropagators_UnknownValues_AreIgnored() + { + var propagator = new PropagatorConfiguration { CompositeList = "invalid,b3multi" }; - var result = config.GetEnabledPropagators(); + var conf = new YamlConfiguration { Propagator = propagator }; + var settings = new SdkSettings(); + + settings.LoadFile(conf); - Assert.Single(result); - Assert.Equal(Propagator.B3Multi, result[0]); + Assert.Single(settings.Propagators); + Assert.Equal(Propagator.B3Multi, settings.Propagators[0]); } } From c35d39fa790953f172f421e5e6017d38462e0f2c Mon Sep 17 00:00:00 2001 From: Yevhenii Solomchenko Date: Tue, 7 Oct 2025 12:14:18 +0200 Subject: [PATCH 7/7] Fix formatting in file-based configuration documentation --- docs/file-based-configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/file-based-configuration.md b/docs/file-based-configuration.md index c431c96f9b..847287e155 100644 --- a/docs/file-based-configuration.md +++ b/docs/file-based-configuration.md @@ -102,3 +102,4 @@ propagator: b3multi: # B3 multi-header propagator # Alternatively, configure via a comma-separated list (same format as OTEL_PROPAGATORS). composite_list: ${OTEL_PROPAGATORS} +```