diff --git a/docs/file-based-configuration.md b/docs/file-based-configuration.md
index e779ba1e85..1c662dc2c6 100644
--- a/docs/file-based-configuration.md
+++ b/docs/file-based-configuration.md
@@ -81,4 +81,21 @@ resource:
operatingsystem: # Detects OS-level attributes (os.*)
process: # Detects process-level attributes (process.*)
processruntime: # Detects process runtime attributes (process.runtime.*)
-```
+```
+
+### Plugins Configuration
+
+For more details and updates about Plugins Configuration, see:
+[Plugins documentation](plugins.md)
+
+``` yaml
+plugins/development:
+ # Configure plugins. Entries have higher priority than entries from .plugins_list.
+ # List of plugins to load. Each entry is the full type name, followed by the assembly name.
+ # For example: MyNamespace.MyPlugin, MyAssembly, Version=1.0.0, Culture=neutral, PublicKeyToken=null
+ plugins:
+ - Test1.Plugins.Plugin, Test1.Plugins, Version=1.0.0, Culture=neutral, PublicKeyToken=null
+ - Test2.Plugins.Plugin, Test2.Plugins
+ # Alternatively, configure via a colon-separated list (same format as OTEL_DOTNET_AUTO_PLUGINS).
+ plugins_list: ${OTEL_DOTNET_AUTO_PLUGINS}
+```
diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PluginsConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PluginsConfiguration.cs
new file mode 100644
index 0000000000..e3b9bd2eda
--- /dev/null
+++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/PluginsConfiguration.cs
@@ -0,0 +1,47 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+using Vendors.YamlDotNet.Serialization;
+
+namespace OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration;
+
+internal class PluginsConfiguration
+{
+ ///
+ /// Gets or sets the list of plugins.
+ ///
+ [YamlMember(Alias = "plugins")]
+ public List? Plugins { get; set; }
+
+ ///
+ /// Gets or sets the plugins list.
+ ///
+ [YamlMember(Alias = "plugins_list")]
+ public string? PluginsList { get; set; }
+
+ public List ParsePlugins()
+ {
+ var uniquePlugins = new HashSet();
+
+ if (Plugins != null)
+ {
+ foreach (var plugin in Plugins)
+ {
+ if (!string.IsNullOrWhiteSpace(plugin))
+ {
+ uniquePlugins.Add(plugin.Trim());
+ }
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(PluginsList))
+ {
+ foreach (var plugin in PluginsList!.Split(Constants.ConfigurationValues.DotNetQualifiedNameSeparator))
+ {
+ uniquePlugins.Add(plugin.Trim());
+ }
+ }
+
+ return uniquePlugins.ToList();
+ }
+}
diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs
index 62a3b94821..bde75b5426 100644
--- a/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs
+++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/FileBasedConfiguration/YamlConfiguration.cs
@@ -49,4 +49,10 @@ internal class YamlConfiguration
///
[YamlMember(Alias = "no_code/development")]
public NoCodeConfiguration? NoCode { get; set; }
+
+ ///
+ /// Gets or sets the plugins configuration.
+ ///
+ [YamlMember(Alias = "plugins/development")]
+ public PluginsConfiguration? Plugins { get; set; }
}
diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/GeneralSettings.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/GeneralSettings.cs
index 5af9978bca..09ecaeb41e 100644
--- a/src/OpenTelemetry.AutoInstrumentation/Configurations/GeneralSettings.cs
+++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/GeneralSettings.cs
@@ -8,11 +8,6 @@ namespace OpenTelemetry.AutoInstrumentation.Configurations;
internal class GeneralSettings : Settings
{
- ///
- /// Gets the list of plugins represented by .
- ///
- public IList Plugins { get; } = [];
-
///
/// Gets a value indicating whether the event should trigger
/// the flushing of telemetry data.
@@ -32,15 +27,6 @@ internal class GeneralSettings : Settings
protected override void OnLoadEnvVar(Configuration configuration)
{
- var providerPlugins = configuration.GetString(ConfigurationKeys.ProviderPlugins);
- if (providerPlugins != null)
- {
- foreach (var pluginAssemblyQualifiedName in providerPlugins.Split(Constants.ConfigurationValues.DotNetQualifiedNameSeparator))
- {
- Plugins.Add(pluginAssemblyQualifiedName);
- }
- }
-
FlushOnUnhandledException = configuration.GetBool(ConfigurationKeys.FlushOnUnhandledException) ?? false;
SetupSdk = configuration.GetBool(ConfigurationKeys.SetupSdk) ?? true;
diff --git a/src/OpenTelemetry.AutoInstrumentation/Configurations/PluginsSettings.cs b/src/OpenTelemetry.AutoInstrumentation/Configurations/PluginsSettings.cs
new file mode 100644
index 0000000000..f9ce823e3f
--- /dev/null
+++ b/src/OpenTelemetry.AutoInstrumentation/Configurations/PluginsSettings.cs
@@ -0,0 +1,31 @@
+// Copyright The OpenTelemetry Authors
+// SPDX-License-Identifier: Apache-2.0
+
+using OpenTelemetry.AutoInstrumentation.Configurations.FileBasedConfiguration;
+
+namespace OpenTelemetry.AutoInstrumentation.Configurations;
+
+internal class PluginsSettings : Settings
+{
+ ///
+ /// Gets the list of plugins represented by .
+ ///
+ public IList Plugins { get; private set; } = [];
+
+ protected override void OnLoadEnvVar(Configuration configuration)
+ {
+ var providerPlugins = configuration.GetString(ConfigurationKeys.ProviderPlugins);
+ if (providerPlugins != null)
+ {
+ foreach (var pluginAssemblyQualifiedName in providerPlugins.Split(Constants.ConfigurationValues.DotNetQualifiedNameSeparator))
+ {
+ Plugins.Add(pluginAssemblyQualifiedName);
+ }
+ }
+ }
+
+ protected override void OnLoadFile(YamlConfiguration configuration)
+ {
+ Plugins = configuration.Plugins?.ParsePlugins() ?? [];
+ }
+}
diff --git a/src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs b/src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs
index d781ec406a..374a6c0e37 100644
--- a/src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs
+++ b/src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs
@@ -69,6 +69,8 @@ internal static LoggerProvider? LoggerProvider
internal static Lazy NoCodeSettings { get; } = new(() => Settings.FromDefaultSources(FailFastSettings.Value.FailFast));
+ internal static Lazy PluginsSettings { get; } = new(() => Settings.FromDefaultSources(FailFastSettings.Value.FailFast));
+
///
/// Initialize the OpenTelemetry SDK with a pre-defined set of exporters, shims, and
/// instrumentations.
@@ -102,7 +104,7 @@ public static void Initialize()
// Initialize SdkSelfDiagnosticsEventListener to create an EventListener for the OpenTelemetry SDK
_sdkEventListener = new(Logger);
- _pluginManager = new PluginManager(GeneralSettings.Value);
+ _pluginManager = new PluginManager(PluginsSettings.Value);
_pluginManager.Initializing();
// Register to shutdown events
diff --git a/src/OpenTelemetry.AutoInstrumentation/Plugins/PluginManager.cs b/src/OpenTelemetry.AutoInstrumentation/Plugins/PluginManager.cs
index 9327dccf75..0ce6304c3b 100644
--- a/src/OpenTelemetry.AutoInstrumentation/Plugins/PluginManager.cs
+++ b/src/OpenTelemetry.AutoInstrumentation/Plugins/PluginManager.cs
@@ -13,7 +13,7 @@ internal partial class PluginManager
{
private readonly IReadOnlyList<(Type Type, object Instance)> _plugins;
- public PluginManager(GeneralSettings settings)
+ public PluginManager(PluginsSettings settings)
{
var plugins = new List<(Type, object)>();
@@ -131,10 +131,7 @@ private void CallPlugins(string methodName)
foreach (var plugin in _plugins)
{
var mi = plugin.Type.GetMethod(methodName, Type.EmptyTypes);
- if (mi is not null)
- {
- mi.Invoke(plugin.Instance, null);
- }
+ mi?.Invoke(plugin.Instance, null);
}
}
@@ -142,11 +139,8 @@ private void CallPlugins(string methodName, (Type Type, object Value) arg)
{
foreach (var plugin in _plugins)
{
- var mi = plugin.Type.GetMethod(methodName, new[] { arg.Type });
- if (mi is not null)
- {
- mi.Invoke(plugin.Instance, new object[] { arg.Value });
- }
+ var mi = plugin.Type.GetMethod(methodName, [arg.Type]);
+ mi?.Invoke(plugin.Instance, [arg.Value]);
}
}
}
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedPluginsSettingsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedPluginsSettingsTests.cs
new file mode 100644
index 0000000000..b5a85c407b
--- /dev/null
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/FilebasedPluginsSettingsTests.cs
@@ -0,0 +1,70 @@
+// 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 FilebasedPluginsSettingsTests
+{
+ [Fact]
+ public void LoadFile_PluginsSettings()
+ {
+ var conf = new YamlConfiguration
+ {
+ Plugins = new PluginsConfiguration
+ {
+ Plugins = ["Test.Plugins.Plugin, Test.Plugins"]
+ }
+ };
+
+ var settings = new PluginsSettings();
+
+ settings.LoadFile(conf);
+
+ Assert.Single(settings.Plugins);
+ Assert.Contains("Test.Plugins.Plugin, Test.Plugins", settings.Plugins);
+ }
+
+ [Fact]
+ public void LoadFile_PluginsListSettings()
+ {
+ var conf = new YamlConfiguration
+ {
+ Plugins = new PluginsConfiguration
+ {
+ PluginsList = "Test.Plugins.Plugin, Test.Plugins"
+ }
+ };
+
+ var settings = new PluginsSettings();
+
+ settings.LoadFile(conf);
+ Assert.Single(settings.Plugins);
+ Assert.Contains("Test.Plugins.Plugin, Test.Plugins", settings.Plugins);
+ }
+
+ [Fact]
+ public void LoadFile_MergePluginsSettings()
+ {
+ var conf = new YamlConfiguration
+ {
+ Plugins = new PluginsConfiguration
+ {
+ Plugins = ["Test1.Plugins.Plugin, Test1.Plugins", "Test2.Plugins.Plugin, Test2.Plugins"],
+ PluginsList = "Test2.Plugins.Plugin, Test2.Plugins:Test3.Plugins.Plugin, Test3.Plugins"
+ }
+ };
+
+ var settings = new PluginsSettings();
+
+ settings.LoadFile(conf);
+
+ Assert.Equal(3, settings.Plugins.Count);
+ Assert.Contains("Test1.Plugins.Plugin, Test1.Plugins", settings.Plugins);
+ Assert.Contains("Test2.Plugins.Plugin, Test2.Plugins", settings.Plugins);
+ Assert.Contains("Test3.Plugins.Plugin, Test3.Plugins", settings.Plugins);
+ }
+}
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFile.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFile.yaml
new file mode 100644
index 0000000000..24cd86b41a
--- /dev/null
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFile.yaml
@@ -0,0 +1,5 @@
+file_format: "1.0-rc.1"
+plugins/development:
+ plugins:
+ - Test1.Plugins.Plugin, Test1.Plugins
+ - Test2.Plugins.Plugin, Test2.Plugins
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFileEnvVars.yaml b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFileEnvVars.yaml
new file mode 100644
index 0000000000..340b0be923
--- /dev/null
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Files/TestPluginsFileEnvVars.yaml
@@ -0,0 +1,4 @@
+file_format: "1.0-rc.1"
+plugins/development:
+ plugins_list: ${OTEL_DOTNET_AUTO_PLUGINS}
+
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPluginsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPluginsTests.cs
new file mode 100644
index 0000000000..72ca77e1a6
--- /dev/null
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/FileBased/Parser/ParserPluginsTests.cs
@@ -0,0 +1,42 @@
+// 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 ParserPluginsTests
+{
+ [Fact]
+ public void Parse_FullConfigYaml_ShouldPopulateModelCorrectly()
+ {
+ var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestPluginsFile.yaml");
+
+ Assert.NotNull(config);
+
+ Assert.NotNull(config.Plugins);
+ Assert.NotNull(config.Plugins.Plugins);
+ Assert.Null(config.Plugins.PluginsList);
+ Assert.Equal(2, config.Plugins.Plugins.Count);
+ Assert.Equal("Test1.Plugins.Plugin, Test1.Plugins", config.Plugins.Plugins[0]);
+ Assert.Equal("Test2.Plugins.Plugin, Test2.Plugins", config.Plugins.Plugins[1]);
+ }
+
+ [Fact]
+ public void Parse_EnvVarYaml_ShouldPopulateModelCompletely()
+ {
+ Environment.SetEnvironmentVariable("OTEL_DOTNET_AUTO_PLUGINS", "Test.Plugins.Plugin, Test.Plugins");
+
+ var config = YamlParser.ParseYaml("Configurations/FileBased/Files/TestPluginsFileEnvVars.yaml");
+
+ Assert.NotNull(config);
+
+ Assert.NotNull(config.Plugins);
+ Assert.Null(config.Plugins.Plugins);
+ Assert.NotNull(config.Plugins.PluginsList);
+
+ Assert.Equal("Test.Plugins.Plugin, Test.Plugins", config.Plugins.PluginsList);
+ }
+}
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/PluginManagerTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/PluginManagerTests.cs
index 2c1317b8c7..a9b7085898 100644
--- a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/PluginManagerTests.cs
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/PluginManagerTests.cs
@@ -150,14 +150,14 @@ public void ConfigureResourceSuccess()
Assert.Equal("value", resource.Attributes.First().Value);
}
- private static GeneralSettings GetSettings(string assemblyQualifiedName)
+ private static PluginsSettings GetSettings(string assemblyQualifiedName)
{
var config = new Configuration(false, new NameValueConfigurationSource(false, new NameValueCollection()
{
{ ConfigurationKeys.ProviderPlugins, assemblyQualifiedName }
}));
- var settings = new GeneralSettings();
+ var settings = new PluginsSettings();
settings.LoadEnvVar(config);
return settings;
}
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/SettingsTests.cs b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/SettingsTests.cs
index 1b5ebd8fab..41d65a0381 100644
--- a/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/SettingsTests.cs
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/Configurations/SettingsTests.cs
@@ -30,10 +30,17 @@ internal void GeneralSettings_DefaultValues()
{
var settings = Settings.FromDefaultSources(false);
- Assert.Empty(settings.Plugins);
Assert.False(settings.FlushOnUnhandledException);
}
+ [Fact]
+ internal void PluginsSettings_DefaultValues()
+ {
+ var settings = Settings.FromDefaultSources(false);
+
+ Assert.Empty(settings.Plugins);
+ }
+
[Fact]
internal void ResourceSettings_DefaultValues()
{
diff --git a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj
index e34a9eb301..da6639f509 100644
--- a/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj
+++ b/test/OpenTelemetry.AutoInstrumentation.Tests/OpenTelemetry.AutoInstrumentation.Tests.csproj
@@ -1,4 +1,4 @@
-
+
@@ -15,9 +15,15 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest