Support options change in plugins (#1542)
This commit is contained in:
parent
c587f56bc5
commit
79ff7dc750
|
@ -28,6 +28,8 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
|
|||
|
||||
- Error message on the native log if bytecode instrumentation type is missing all
|
||||
instrumentation methods [#1499](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/1499).
|
||||
- Plugins can overwrite OpenTelemetry dotnet SDK instrumentation and exporter options.
|
||||
See more at [plugins.md](docs/plugins.md).
|
||||
|
||||
## [0.4.0-beta.1](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/tag/v0.4.0-beta.1)
|
||||
|
||||
|
|
|
@ -186,36 +186,16 @@ Important environment variables include:
|
|||
|
||||
## Additional settings
|
||||
|
||||
| Environment variable | Description | Default value |
|
||||
|------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ENABLED` | Enables trace provider together with traces source instrumentations. | `true` |
|
||||
| `OTEL_DOTNET_AUTO_OPENTRACING_ENABLED` | Enables OpenTracing tracer. | `false` |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ENABLED` | Enables meter provider together with metrics source instrumentations. | `true` |
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.ActivitySource` names to be added to the tracer at the startup. Use it to capture manually instrumented spans. | |
|
||||
| `OTEL_DOTNET_AUTO_LEGACY_SOURCES` | Comma-separated list of additional legacy source names to be added to the tracer at the startup. Use it to capture `System.Diagnostics.Activity` objects created without using the `System.Diagnostics.ActivitySource` API. | |
|
||||
| `OTEL_DOTNET_AUTO_FLUSH_ON_UNHANDLEDEXCEPTION` | Controls whether the telemetry data is flushed when an [AppDomain.UnhandledException](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception) event is raised. Set to `true` when you suspect that you are experiencing a problem with missing telemetry data and also experiencing unhandled exceptions. | `false` |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.Metrics.Meter` names to be added to the meter at the startup. Use it to capture manually instrumented spans. | |
|
||||
| `OTEL_DOTNET_AUTO_PLUGINS` | Colon-separated list of OTel SDK instrumentation plugin types, specified with the [assembly-qualified name](https://docs.microsoft.com/en-us/dotnet/api/system.type.assemblyqualifiedname?view=net-6.0#system-type-assemblyqualifiedname). _Note: This list must be colon-separated because the type names may include commas._ | |
|
||||
|
||||
You can use `OTEL_DOTNET_AUTO_PLUGINS` environment variable to extend the
|
||||
configuration of the OpenTelemetry .NET SDK Tracer, Meter or Logs. A plugin
|
||||
must be a non-static, non-abstract class which has a default constructor
|
||||
and that implements at least one of the configuration methods below:
|
||||
|
||||
```csharp
|
||||
public OpenTelemetry.Trace.TracerProviderBuilder ConfigureTracerProvider(OpenTelemetry.Trace.TracerProviderBuilder builder)
|
||||
```
|
||||
|
||||
```csharp
|
||||
public OpenTelemetry.Metrics.MeterProviderBuilder ConfigureMeterProvider(OpenTelemetry.Metrics.MeterProviderBuilder builder)
|
||||
```
|
||||
|
||||
```csharp
|
||||
public OpenTelemetry.Logs.OpenTelemetryLoggerOptions ConfigureLoggerOptions(OpenTelemetry.Logs.OpenTelemetryLoggerOptions builder)
|
||||
```
|
||||
|
||||
The plugin must use the same version of the `OpenTelemetry` as the
|
||||
OpenTelemetry .NET Automatic Instrumentation.
|
||||
| Environment variable | Description | Default value |
|
||||
|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ENABLED` | Enables trace provider together with traces source instrumentations. | `true` |
|
||||
| `OTEL_DOTNET_AUTO_OPENTRACING_ENABLED` | Enables OpenTracing tracer. | `false` |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ENABLED` | Enables meter provider together with metrics source instrumentations. | `true` |
|
||||
| `OTEL_DOTNET_AUTO_TRACES_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.ActivitySource` names to be added to the tracer at the startup. Use it to capture manually instrumented spans. | |
|
||||
| `OTEL_DOTNET_AUTO_LEGACY_SOURCES` | Comma-separated list of additional legacy source names to be added to the tracer at the startup. Use it to capture `System.Diagnostics.Activity` objects created without using the `System.Diagnostics.ActivitySource` API. | |
|
||||
| `OTEL_DOTNET_AUTO_FLUSH_ON_UNHANDLEDEXCEPTION` | Controls whether the telemetry data is flushed when an [AppDomain.UnhandledException](https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception) event is raised. Set to `true` when you suspect that you are experiencing a problem with missing telemetry data and also experiencing unhandled exceptions. | `false` |
|
||||
| `OTEL_DOTNET_AUTO_METRICS_ADDITIONAL_SOURCES` | Comma-separated list of additional `System.Diagnostics.Metrics.Meter` names to be added to the meter at the startup. Use it to capture manually instrumented spans. | |
|
||||
| `OTEL_DOTNET_AUTO_PLUGINS` | Colon-separated list of OTel SDK instrumentation plugin types, specified with the [assembly-qualified name](https://docs.microsoft.com/en-us/dotnet/api/system.type.assemblyqualifiedname?view=net-6.0#system-type-assemblyqualifiedname). _Note: This list must be colon-separated because the type names may include commas._ See more info on how to write plugins at [plugins.md](plugins.md). | |
|
||||
|
||||
## .NET CLR Profiler
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
# Plugins
|
||||
|
||||
You can use `OTEL_DOTNET_AUTO_PLUGINS` environment variable to extend the
|
||||
configuration and overwrite options of the OpenTelemetry .NET SDK Tracer, Meter or
|
||||
Logs. A plugin must be a non-static, non-abstract class which has a default constructor
|
||||
and that implements at least one of the configuration methods below showed
|
||||
in an example plugin class:
|
||||
|
||||
```csharp
|
||||
|
||||
public class MyPlugin
|
||||
{
|
||||
// To configure tracing SDK
|
||||
public OpenTelemetry.Trace.TracerProviderBuilder ConfigureTracerProvider(OpenTelemetry.Trace.TracerProviderBuilder builder)
|
||||
{
|
||||
// My custom logic here
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
// To configure metrics SDK
|
||||
public OpenTelemetry.Metrics.MeterProviderBuilder ConfigureMeterProvider(OpenTelemetry.Metrics.MeterProviderBuilder builder)
|
||||
{
|
||||
// My custom logic here
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
// To configure logs SDK
|
||||
public void ConfigureOptions(OpenTelemetry.Logs.OpenTelemetryLoggerOptions options)
|
||||
{
|
||||
// My custom logic here
|
||||
}
|
||||
|
||||
// To configure any options used by OpenTelemetry .NET Automatic Instrumentation
|
||||
public void ConfigureOptions(OpenTelemetry.NameSpace.OptionType options)
|
||||
{
|
||||
// My custom logic here
|
||||
// Find supported options below
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Options
|
||||
|
||||
### Tracing
|
||||
|
||||
| Options type | NuGet package | NuGet version |
|
||||
|------------------------------------------------------------------------------|----------------------------------------------|---------------|
|
||||
| OpenTelemetry.Exporter.ConsoleExporterOptions | OpenTelemetry.Exporter.Console | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.ZipkinExporterOptions | OpenTelemetry.Exporter.Zipkin | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.JaegerExporterOptions | OpenTelemetry.Exporter.Jaeger | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.OtlpExporterOptions | OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.3.1 |
|
||||
| OpenTelemetry.Instrumentation.AspNet.AspNetInstrumentationOptions | OpenTelemetry.Instrumentation.AspNet | 1.0.0-rc9.6 |
|
||||
| OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions | OpenTelemetry.Instrumentation.AspNetCore | 1.0.0-rc9.4 |
|
||||
| OpenTelemetry.Instrumentation.GrpcNetClient.GrpcClientInstrumentationOptions | OpenTelemetry.Instrumentation.GrpcNetClient | 1.0.0-rc9.4 |
|
||||
| OpenTelemetry.Instrumentation.Http.HttpClientInstrumentationOptions | OpenTelemetry.Instrumentation.Http | 1.0.0-rc9.4 |
|
||||
| OpenTelemetry.Instrumentation.Http.HttpWebRequestInstrumentationOptions | OpenTelemetry.Instrumentation.Http | 1.0.0-rc9.4 |
|
||||
| OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentationOptions | OpenTelemetry.Instrumentation.SqlClient | 1.0.0-rc9.4 |
|
||||
| OpenTelemetry.Instrumentation.MySqlData.MySqlDataInstrumentationOptions | OpenTelemetry.Instrumentation.MySqlData | 1.0.0-beta.4 |
|
||||
| OpenTelemetry.Instrumentation.Wcf.WcfInstrumentationOptions | OpenTelemetry.Instrumentation.Wcf | 1.0.0-rc7 |
|
||||
|
||||
### Metrics
|
||||
|
||||
| Options type | NuGet package | NuGet version |
|
||||
|---------------------------------------------------------------------|----------------------------------------------|---------------|
|
||||
| OpenTelemetry.Metrics.MetricReaderOptions | OpenTelemetry | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.ConsoleExporterOptions | OpenTelemetry.Exporter.Console | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.PrometheusExporterOptions | OpenTelemetry.Exporter.Prometheus | 1.3.0-rc.2 |
|
||||
| OpenTelemetry.Exporter.OtlpExporterOptions | OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.OtlpExporterOptions | OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.3.1 |
|
||||
| OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions | OpenTelemetry.Instrumentation.Runtime | 1.0.0 |
|
||||
| OpenTelemetry.Instrumentation.Process.ProcessInstrumentationOptions | OpenTelemetry.Instrumentation.Process | 0.1.0-alpha.1 |
|
||||
|
||||
### Logs
|
||||
|
||||
| Options type | NuGet package | NuGet version |
|
||||
|-----------------------------------------------|----------------------------------------------|---------------|
|
||||
| OpenTelemetry.Logs.OpenTelemetryLoggerOptions | OpenTelemetry | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.ConsoleExporterOptions | OpenTelemetry.Exporter.Console | 1.3.1 |
|
||||
| OpenTelemetry.Exporter.OtlpExporterOptions | OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.3.1 |
|
||||
|
||||
## Requirements
|
||||
|
||||
* The plugin must use the same version of the `OpenTelemetry` as the
|
||||
OpenTelemetry .NET Automatic Instrumentation.
|
||||
* The plugin must use the same options versions as the
|
||||
OpenTelemetry .NET Automatic Instrumentation (found in the table above).
|
|
@ -35,7 +35,7 @@ internal class BootstrapperHostingStartup : IHostingStartup
|
|||
/// </summary>
|
||||
public BootstrapperHostingStartup()
|
||||
{
|
||||
_settings = LogSettings.FromDefaultSources();
|
||||
_settings = Instrumentation.LogSettings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -18,6 +18,7 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using OpenTelemetry.AutoInstrumentation.Logging;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Metrics;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
|
@ -26,10 +27,10 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
{
|
||||
private static readonly ILogger Logger = OtelLogging.GetLogger();
|
||||
|
||||
public static MeterProviderBuilder UseEnvironmentVariables(this MeterProviderBuilder builder, MetricSettings settings)
|
||||
public static MeterProviderBuilder UseEnvironmentVariables(this MeterProviderBuilder builder, MetricSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
builder
|
||||
.SetExporter(settings)
|
||||
.SetExporter(settings, pluginManager)
|
||||
.AddMeter(settings.Meters.ToArray());
|
||||
|
||||
foreach (var enabledMeter in settings.EnabledInstrumentations)
|
||||
|
@ -38,8 +39,8 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
{
|
||||
MetricInstrumentation.AspNet => Wrappers.AddSdkAspNetInstrumentation(builder),
|
||||
MetricInstrumentation.HttpClient => Wrappers.AddHttpClientInstrumentation(builder),
|
||||
MetricInstrumentation.NetRuntime => Wrappers.AddRuntimeInstrumentation(builder),
|
||||
MetricInstrumentation.Process => Wrappers.AddProcessInstrumentation(builder),
|
||||
MetricInstrumentation.NetRuntime => Wrappers.AddRuntimeInstrumentation(builder, pluginManager),
|
||||
MetricInstrumentation.Process => Wrappers.AddProcessInstrumentation(builder, pluginManager),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
@ -47,17 +48,17 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
return builder;
|
||||
}
|
||||
|
||||
private static MeterProviderBuilder SetExporter(this MeterProviderBuilder builder, MetricSettings settings)
|
||||
private static MeterProviderBuilder SetExporter(this MeterProviderBuilder builder, MetricSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
if (settings.ConsoleExporterEnabled)
|
||||
{
|
||||
Wrappers.AddConsoleExporter(builder, settings);
|
||||
Wrappers.AddConsoleExporter(builder, settings, pluginManager);
|
||||
}
|
||||
|
||||
return settings.MetricExporter switch
|
||||
{
|
||||
MetricsExporter.Prometheus => Wrappers.AddPrometheusExporter(builder),
|
||||
MetricsExporter.Otlp => Wrappers.AddOtlpExporter(builder, settings),
|
||||
MetricsExporter.Prometheus => Wrappers.AddPrometheusExporter(builder, pluginManager),
|
||||
MetricsExporter.Otlp => Wrappers.AddOtlpExporter(builder, settings, pluginManager),
|
||||
MetricsExporter.None => builder,
|
||||
_ => throw new ArgumentOutOfRangeException($"Metrics exporter '{settings.MetricExporter}' is incorrect")
|
||||
};
|
||||
|
@ -90,33 +91,36 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static MeterProviderBuilder AddRuntimeInstrumentation(MeterProviderBuilder builder)
|
||||
public static MeterProviderBuilder AddRuntimeInstrumentation(MeterProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddRuntimeInstrumentation();
|
||||
return builder.AddRuntimeInstrumentation(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static MeterProviderBuilder AddProcessInstrumentation(MeterProviderBuilder builder)
|
||||
public static MeterProviderBuilder AddProcessInstrumentation(MeterProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddProcessInstrumentation();
|
||||
return builder.AddProcessInstrumentation(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
// Exporters
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static MeterProviderBuilder AddConsoleExporter(MeterProviderBuilder builder, MetricSettings settings)
|
||||
public static MeterProviderBuilder AddConsoleExporter(MeterProviderBuilder builder, MetricSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddConsoleExporter((_, metricReaderOptions) =>
|
||||
return builder.AddConsoleExporter((consoleExporterOptions, metricReaderOptions) =>
|
||||
{
|
||||
if (settings.MetricExportInterval != null)
|
||||
{
|
||||
metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = settings.MetricExportInterval;
|
||||
}
|
||||
|
||||
pluginManager.ConfigureOptions(consoleExporterOptions);
|
||||
pluginManager.ConfigureOptions(metricReaderOptions);
|
||||
});
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder)
|
||||
public static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
Logger.Warning("Prometheus exporter is configured. It is intended for the inner dev loop. Do NOT use in production");
|
||||
|
||||
|
@ -124,11 +128,13 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
{
|
||||
options.StartHttpListener = true;
|
||||
options.ScrapeResponseCacheDurationMilliseconds = 300;
|
||||
|
||||
pluginManager.ConfigureOptions(options);
|
||||
});
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static MeterProviderBuilder AddOtlpExporter(MeterProviderBuilder builder, MetricSettings settings)
|
||||
public static MeterProviderBuilder AddOtlpExporter(MeterProviderBuilder builder, MetricSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
#if NETCOREAPP3_1
|
||||
if (settings.Http2UnencryptedSupportEnabled)
|
||||
|
@ -151,6 +157,9 @@ internal static class EnvironmentConfigurationMetricHelper
|
|||
{
|
||||
metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = settings.MetricExportInterval;
|
||||
}
|
||||
|
||||
pluginManager.ConfigureOptions(options);
|
||||
pluginManager.ConfigureOptions(metricReaderOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,26 +17,27 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
|
||||
internal static class EnvironmentConfigurationTracerHelper
|
||||
{
|
||||
public static TracerProviderBuilder UseEnvironmentVariables(this TracerProviderBuilder builder, TracerSettings settings)
|
||||
public static TracerProviderBuilder UseEnvironmentVariables(this TracerProviderBuilder builder, TracerSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
builder.SetExporter(settings);
|
||||
builder.SetExporter(settings, pluginManager);
|
||||
|
||||
foreach (var enabledInstrumentation in settings.EnabledInstrumentations)
|
||||
{
|
||||
_ = enabledInstrumentation switch
|
||||
{
|
||||
TracerInstrumentation.AspNet => Wrappers.AddSdkAspNetInstrumentation(builder),
|
||||
TracerInstrumentation.GrpcNetClient => Wrappers.AddGrpcClientInstrumentation(builder),
|
||||
TracerInstrumentation.HttpClient => Wrappers.AddHttpClientInstrumentation(builder),
|
||||
TracerInstrumentation.AspNet => Wrappers.AddSdkAspNetInstrumentation(builder, pluginManager),
|
||||
TracerInstrumentation.GrpcNetClient => Wrappers.AddGrpcClientInstrumentation(builder, pluginManager),
|
||||
TracerInstrumentation.HttpClient => Wrappers.AddHttpClientInstrumentation(builder, pluginManager),
|
||||
TracerInstrumentation.Npgsql => builder.AddSource("Npgsql"),
|
||||
TracerInstrumentation.SqlClient => Wrappers.AddSqlClientInstrumentation(builder),
|
||||
TracerInstrumentation.Wcf => Wrappers.AddWcfInstrumentation(builder),
|
||||
TracerInstrumentation.SqlClient => Wrappers.AddSqlClientInstrumentation(builder, pluginManager),
|
||||
TracerInstrumentation.Wcf => Wrappers.AddWcfInstrumentation(builder, pluginManager),
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
TracerInstrumentation.MassTransit => builder.AddSource("MassTransit"),
|
||||
TracerInstrumentation.MongoDB => builder.AddSource("MongoDB.Driver.Core.Extensions.DiagnosticSources"),
|
||||
|
@ -56,18 +57,18 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
return builder;
|
||||
}
|
||||
|
||||
private static TracerProviderBuilder SetExporter(this TracerProviderBuilder builder, TracerSettings settings)
|
||||
private static TracerProviderBuilder SetExporter(this TracerProviderBuilder builder, TracerSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
if (settings.ConsoleExporterEnabled)
|
||||
{
|
||||
Wrappers.AddConsoleExporter(builder);
|
||||
Wrappers.AddConsoleExporter(builder, pluginManager);
|
||||
}
|
||||
|
||||
return settings.TracesExporter switch
|
||||
{
|
||||
TracesExporter.Zipkin => Wrappers.AddZipkinExporter(builder),
|
||||
TracesExporter.Jaeger => Wrappers.AddJaegerExporter(builder),
|
||||
TracesExporter.Otlp => Wrappers.AddOtlpExporter(builder, settings),
|
||||
TracesExporter.Zipkin => Wrappers.AddZipkinExporter(builder, pluginManager),
|
||||
TracesExporter.Jaeger => Wrappers.AddJaegerExporter(builder, pluginManager),
|
||||
TracesExporter.Otlp => Wrappers.AddOtlpExporter(builder, settings, pluginManager),
|
||||
TracesExporter.None => builder,
|
||||
_ => throw new ArgumentOutOfRangeException($"Traces exporter '{settings.TracesExporter}' is incorrect")
|
||||
};
|
||||
|
@ -82,22 +83,22 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
// Instrumentations
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddWcfInstrumentation(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddWcfInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddWcfInstrumentation();
|
||||
return builder.AddWcfInstrumentation(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddHttpClientInstrumentation(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddHttpClientInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddHttpClientInstrumentation();
|
||||
return builder.AddHttpClientInstrumentation(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddSdkAspNetInstrumentation(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddSdkAspNetInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
#if NET462
|
||||
builder.AddAspNetInstrumentation();
|
||||
builder.AddAspNetInstrumentation(pluginManager.ConfigureOptions);
|
||||
#elif NETCOREAPP3_1_OR_GREATER
|
||||
builder.AddSource("OpenTelemetry.Instrumentation.AspNetCore");
|
||||
builder.AddLegacySource("Microsoft.AspNetCore.Hosting.HttpRequestIn");
|
||||
|
@ -107,40 +108,43 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddSqlClientInstrumentation(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddSqlClientInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddSqlClientInstrumentation();
|
||||
return builder.AddSqlClientInstrumentation(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddGrpcClientInstrumentation(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddGrpcClientInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddGrpcClientInstrumentation(options =>
|
||||
options.SuppressDownstreamInstrumentation = !Instrumentation.TracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.HttpClient));
|
||||
{
|
||||
options.SuppressDownstreamInstrumentation = !Instrumentation.TracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.HttpClient);
|
||||
pluginManager.ConfigureOptions(options);
|
||||
});
|
||||
}
|
||||
|
||||
// Exporters
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddConsoleExporter(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddConsoleExporter(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddConsoleExporter();
|
||||
return builder.AddConsoleExporter(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddZipkinExporter(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddZipkinExporter(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddZipkinExporter();
|
||||
return builder.AddZipkinExporter(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddJaegerExporter(TracerProviderBuilder builder)
|
||||
public static TracerProviderBuilder AddJaegerExporter(TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
return builder.AddJaegerExporter();
|
||||
return builder.AddJaegerExporter(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static TracerProviderBuilder AddOtlpExporter(TracerProviderBuilder builder, TracerSettings settings)
|
||||
public static TracerProviderBuilder AddOtlpExporter(TracerProviderBuilder builder, TracerSettings settings, PluginManager pluginManager)
|
||||
{
|
||||
#if NETCOREAPP3_1
|
||||
if (settings.Http2UnencryptedSupportEnabled)
|
||||
|
@ -156,6 +160,7 @@ internal static class EnvironmentConfigurationTracerHelper
|
|||
if (settings.OtlpExportProtocol.HasValue)
|
||||
{
|
||||
options.Protocol = settings.OtlpExportProtocol.Value;
|
||||
pluginManager.ConfigureOptions(options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// <copyright file="GeneralSettings.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
|
||||
internal class GeneralSettings : Settings
|
||||
{
|
||||
public GeneralSettings(IConfigurationSource source)
|
||||
: base(source)
|
||||
{
|
||||
var providerPlugins = source.GetString(ConfigurationKeys.ProviderPlugins);
|
||||
if (providerPlugins != null)
|
||||
{
|
||||
foreach (var pluginAssemblyQualifiedName in providerPlugins.Split(Constants.ConfigurationValues.DotNetQualifiedNameSeparator))
|
||||
{
|
||||
Plugins.Add(pluginAssemblyQualifiedName);
|
||||
}
|
||||
}
|
||||
|
||||
FlushOnUnhandledException = source.GetBool(ConfigurationKeys.FlushOnUnhandledException) ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of plugins represented by <see cref="Type.AssemblyQualifiedName"/>.
|
||||
/// </summary>
|
||||
public IList<string> Plugins { get; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="AppDomain.UnhandledException"/> event should trigger
|
||||
/// the flushing of telemetry data.
|
||||
/// Default is <c>false</c>.
|
||||
/// </summary>
|
||||
public bool FlushOnUnhandledException { get; }
|
||||
}
|
|
@ -30,7 +30,7 @@ internal class LogSettings : Settings
|
|||
/// using the specified <see cref="IConfigurationSource"/> to initialize values.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
|
||||
private LogSettings(IConfigurationSource source)
|
||||
public LogSettings(IConfigurationSource source)
|
||||
: base(source)
|
||||
{
|
||||
LogExporter = ParseLogExporter(source);
|
||||
|
@ -63,21 +63,6 @@ internal class LogSettings : Settings
|
|||
/// </summary>
|
||||
public IList<LogInstrumentation> EnabledInstrumentations { get; }
|
||||
|
||||
internal static LogSettings FromDefaultSources()
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
{
|
||||
new EnvironmentConfigurationSource(),
|
||||
|
||||
#if NETFRAMEWORK
|
||||
// on .NET Framework only, also read from app.config/web.config
|
||||
new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings)
|
||||
#endif
|
||||
};
|
||||
|
||||
return new LogSettings(configurationSource);
|
||||
}
|
||||
|
||||
private static LogExporter ParseLogExporter(IConfigurationSource source)
|
||||
{
|
||||
var logExporterEnvVar = source.GetString(ConfigurationKeys.Logs.Exporter)
|
||||
|
|
|
@ -30,7 +30,7 @@ internal class MetricSettings : Settings
|
|||
/// using the specified <see cref="IConfigurationSource"/> to initialize values.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
|
||||
private MetricSettings(IConfigurationSource source)
|
||||
public MetricSettings(IConfigurationSource source)
|
||||
: base(source)
|
||||
{
|
||||
MetricExporter = ParseMetricExporter(source);
|
||||
|
@ -84,21 +84,6 @@ internal class MetricSettings : Settings
|
|||
/// </summary>
|
||||
public IList<string> Meters { get; } = new List<string>();
|
||||
|
||||
internal static MetricSettings FromDefaultSources()
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
{
|
||||
new EnvironmentConfigurationSource(),
|
||||
|
||||
#if NETFRAMEWORK
|
||||
// on .NET Framework only, also read from app.config/web.config
|
||||
new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings)
|
||||
#endif
|
||||
};
|
||||
|
||||
return new MetricSettings(configurationSource);
|
||||
}
|
||||
|
||||
private static MetricsExporter ParseMetricExporter(IConfigurationSource source)
|
||||
{
|
||||
var metricsExporterEnvVar = source.GetString(ConfigurationKeys.Metrics.Exporter)
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTelemetry.AutoInstrumentation.Logging;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
|
@ -25,92 +22,13 @@ namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
|||
|
||||
internal static class PluginsConfigurationHelper
|
||||
{
|
||||
private static readonly ILogger Logger = OtelLogging.GetLogger();
|
||||
|
||||
public static TracerProviderBuilder InvokePlugins(this TracerProviderBuilder builder, IEnumerable<string> pluginsAssemblyQualifiedNames)
|
||||
public static TracerProviderBuilder InvokePlugins(this TracerProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
foreach (var assemblyQualifiedName in pluginsAssemblyQualifiedNames)
|
||||
{
|
||||
builder = builder.InvokePlugin(assemblyQualifiedName);
|
||||
}
|
||||
|
||||
return builder;
|
||||
return pluginManager.ConfigureTracerProviderBuilder(builder);
|
||||
}
|
||||
|
||||
public static MeterProviderBuilder InvokePlugins(this MeterProviderBuilder builder, IEnumerable<string> pluginsAssemblyQualifiedNames)
|
||||
public static MeterProviderBuilder InvokePlugins(this MeterProviderBuilder builder, PluginManager pluginManager)
|
||||
{
|
||||
foreach (var assemblyQualifiedName in pluginsAssemblyQualifiedNames)
|
||||
{
|
||||
builder = builder.InvokePlugin(assemblyQualifiedName);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static OpenTelemetryLoggerOptions InvokePlugins(this OpenTelemetryLoggerOptions options, IEnumerable<string> pluginsAssemblyQualifiedNames)
|
||||
{
|
||||
foreach (var assemblyQualifiedName in pluginsAssemblyQualifiedNames)
|
||||
{
|
||||
options = options.InvokePlugin(assemblyQualifiedName);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static TracerProviderBuilder InvokePlugin(this TracerProviderBuilder builder, string pluginAssemblyQualifiedName)
|
||||
{
|
||||
const string configureTracerProviderMethodName = "ConfigureTracerProvider";
|
||||
|
||||
// get the type and method
|
||||
var t = Type.GetType(pluginAssemblyQualifiedName, throwOnError: true);
|
||||
var mi = t.GetMethod(configureTracerProviderMethodName, new Type[] { typeof(TracerProviderBuilder) });
|
||||
if (mi is null)
|
||||
{
|
||||
Logger.Information(new MissingMethodException(t.Name, configureTracerProviderMethodName), $"{configureTracerProviderMethodName} is missing in {pluginAssemblyQualifiedName}");
|
||||
return builder;
|
||||
}
|
||||
|
||||
// execute
|
||||
var obj = Activator.CreateInstance(t);
|
||||
var result = mi.Invoke(obj, new object[] { builder });
|
||||
return (TracerProviderBuilder)result;
|
||||
}
|
||||
|
||||
private static MeterProviderBuilder InvokePlugin(this MeterProviderBuilder builder, string pluginAssemblyQualifiedName)
|
||||
{
|
||||
const string configureMeterProviderMethodName = "ConfigureMeterProvider";
|
||||
|
||||
// get the type and method
|
||||
var t = Type.GetType(pluginAssemblyQualifiedName, throwOnError: true);
|
||||
var mi = t.GetMethod(configureMeterProviderMethodName, new Type[] { typeof(MeterProviderBuilder) });
|
||||
if (mi is null)
|
||||
{
|
||||
Logger.Information(new MissingMethodException(t.Name, configureMeterProviderMethodName), $"{configureMeterProviderMethodName} is missing in {pluginAssemblyQualifiedName}");
|
||||
return builder;
|
||||
}
|
||||
|
||||
// execute
|
||||
var obj = Activator.CreateInstance(t);
|
||||
var result = mi.Invoke(obj, new object[] { builder });
|
||||
return (MeterProviderBuilder)result;
|
||||
}
|
||||
|
||||
private static OpenTelemetryLoggerOptions InvokePlugin(this OpenTelemetryLoggerOptions options, string pluginAssemblyQualifiedName)
|
||||
{
|
||||
const string configureLoggerOptionsMethodName = "ConfigureLoggerOptions";
|
||||
|
||||
// get the type and method
|
||||
var t = Type.GetType(pluginAssemblyQualifiedName, throwOnError: true);
|
||||
var mi = t.GetMethod(configureLoggerOptionsMethodName, new Type[] { typeof(OpenTelemetryLoggerOptions) });
|
||||
if (mi is null)
|
||||
{
|
||||
Logger.Information(new MissingMethodException(t.Name, configureLoggerOptionsMethodName), $"{configureLoggerOptionsMethodName} is missing in {pluginAssemblyQualifiedName}");
|
||||
return options;
|
||||
}
|
||||
|
||||
// execute
|
||||
var obj = Activator.CreateInstance(t);
|
||||
var result = mi.Invoke(obj, new object[] { options });
|
||||
return (OpenTelemetryLoggerOptions)result;
|
||||
return pluginManager.ConfigureMeterProviderBuilder(builder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@ namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
|||
/// <summary>
|
||||
/// Propagator Settings
|
||||
/// </summary>
|
||||
internal class SdkSettings
|
||||
internal class SdkSettings : Settings
|
||||
{
|
||||
private SdkSettings(CompositeConfigurationSource source)
|
||||
public SdkSettings(IConfigurationSource source)
|
||||
: base(source)
|
||||
{
|
||||
var propagators = source.GetString(ConfigurationKeys.Sdk.Propagators);
|
||||
|
||||
|
@ -42,21 +43,6 @@ internal class SdkSettings
|
|||
/// </summary>
|
||||
public IList<Propagator> Propagators { get; } = new List<Propagator>();
|
||||
|
||||
internal static SdkSettings FromDefaultSources()
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
{
|
||||
new EnvironmentConfigurationSource(),
|
||||
|
||||
#if NETFRAMEWORK
|
||||
// on .NET Framework only, also read from app.config/web.config
|
||||
new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings)
|
||||
#endif
|
||||
};
|
||||
|
||||
return new SdkSettings(configurationSource);
|
||||
}
|
||||
|
||||
private static Propagator ParsePropagator(string propagator)
|
||||
{
|
||||
switch (propagator)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using OpenTelemetry.Exporter;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
|
@ -39,16 +39,6 @@ internal abstract class Settings
|
|||
|
||||
OtlpExportProtocol = GetExporterOtlpProtocol(source);
|
||||
Http2UnencryptedSupportEnabled = source.GetBool(ConfigurationKeys.Http2UnencryptedSupportEnabled) ?? false;
|
||||
FlushOnUnhandledException = source.GetBool(ConfigurationKeys.FlushOnUnhandledException) ?? false;
|
||||
|
||||
var providerPlugins = source.GetString(ConfigurationKeys.ProviderPlugins);
|
||||
if (providerPlugins != null)
|
||||
{
|
||||
foreach (var pluginAssemblyQualifiedName in providerPlugins.Split(Constants.ConfigurationValues.DotNetQualifiedNameSeparator))
|
||||
{
|
||||
Plugins.Add(pluginAssemblyQualifiedName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -64,17 +54,31 @@ internal abstract class Settings
|
|||
/// </summary>
|
||||
public bool Http2UnencryptedSupportEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="AppDomain.UnhandledException"/> event should trigger
|
||||
/// the flushing of telemetry data.
|
||||
/// Default is <c>false</c>.
|
||||
/// </summary>
|
||||
public bool FlushOnUnhandledException { get; }
|
||||
public static T FromDefaultSources<T>()
|
||||
where T : Settings
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
{
|
||||
new EnvironmentConfigurationSource(),
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of plugins represented by <see cref="Type.AssemblyQualifiedName"/>.
|
||||
/// </summary>
|
||||
public IList<string> Plugins { get; } = new List<string>();
|
||||
#if NETFRAMEWORK
|
||||
// on .NET Framework only, also read from app.config/web.config
|
||||
new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings)
|
||||
#endif
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
return (T)typeof(T)
|
||||
.GetConstructor(new[] { typeof(IConfigurationSource) })
|
||||
.Invoke(new object[] { configurationSource });
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
// Unwrap the more informative internal exception
|
||||
throw ex.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
private static OtlpExportProtocol? GetExporterOtlpProtocol(IConfigurationSource source)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@ internal class TracerSettings : Settings
|
|||
/// using the specified <see cref="IConfigurationSource"/> to initialize values.
|
||||
/// </summary>
|
||||
/// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param>
|
||||
private TracerSettings(IConfigurationSource source)
|
||||
public TracerSettings(IConfigurationSource source)
|
||||
: base(source)
|
||||
{
|
||||
TracesExporter = ParseTracesExporter(source);
|
||||
|
@ -106,21 +106,6 @@ internal class TracerSettings : Settings
|
|||
/// </summary>
|
||||
public InstrumentationOptions InstrumentationOptions { get; private set; }
|
||||
|
||||
internal static TracerSettings FromDefaultSources()
|
||||
{
|
||||
var configurationSource = new CompositeConfigurationSource
|
||||
{
|
||||
new EnvironmentConfigurationSource(),
|
||||
|
||||
#if NETFRAMEWORK
|
||||
// on .NET Framework only, also read from app.config/web.config
|
||||
new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings)
|
||||
#endif
|
||||
};
|
||||
|
||||
return new TracerSettings(configurationSource);
|
||||
}
|
||||
|
||||
private static TracesExporter ParseTracesExporter(IConfigurationSource source)
|
||||
{
|
||||
var tracesExporterEnvVar = source.GetString(ConfigurationKeys.Traces.Exporter)
|
||||
|
|
|
@ -23,6 +23,7 @@ using OpenTelemetry.AutoInstrumentation.Diagnostics;
|
|||
using OpenTelemetry.AutoInstrumentation.Loading;
|
||||
#endif
|
||||
using OpenTelemetry.AutoInstrumentation.Logging;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Context.Propagation;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Shims.OpenTracing;
|
||||
|
@ -47,6 +48,7 @@ internal static class Instrumentation
|
|||
|
||||
private static TracerProvider _tracerProvider;
|
||||
private static MeterProvider _meterProvider;
|
||||
private static PluginManager _pluginManager;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether OpenTelemetry's profiler is attached to the current process.
|
||||
|
@ -69,15 +71,21 @@ internal static class Instrumentation
|
|||
}
|
||||
}
|
||||
|
||||
internal static PluginManager PluginManager => _pluginManager;
|
||||
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
internal static ILifespanManager LifespanManager => LazyInstrumentationLoader.LifespanManager;
|
||||
#endif
|
||||
|
||||
internal static TracerSettings TracerSettings { get; } = TracerSettings.FromDefaultSources();
|
||||
internal static GeneralSettings GeneralSettings { get; } = Settings.FromDefaultSources<GeneralSettings>();
|
||||
|
||||
internal static MetricSettings MetricSettings { get; } = MetricSettings.FromDefaultSources();
|
||||
internal static TracerSettings TracerSettings { get; } = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
internal static SdkSettings SdkSettings { get; } = SdkSettings.FromDefaultSources();
|
||||
internal static MetricSettings MetricSettings { get; } = Settings.FromDefaultSources<MetricSettings>();
|
||||
|
||||
internal static LogSettings LogSettings { get; } = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
internal static SdkSettings SdkSettings { get; } = Settings.FromDefaultSources<SdkSettings>();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the OpenTelemetry SDK with a pre-defined set of exporters, shims, and
|
||||
|
@ -93,6 +101,8 @@ internal static class Instrumentation
|
|||
|
||||
try
|
||||
{
|
||||
_pluginManager = new PluginManager(GeneralSettings);
|
||||
|
||||
if (TracerSettings.TracesEnabled || MetricSettings.MetricsEnabled)
|
||||
{
|
||||
// Initialize SdkSelfDiagnosticsEventListener to create an EventListener for the OpenTelemetry SDK
|
||||
|
@ -102,7 +112,7 @@ internal static class Instrumentation
|
|||
AppDomain.CurrentDomain.ProcessExit += OnExit;
|
||||
AppDomain.CurrentDomain.DomainUnload += OnExit;
|
||||
|
||||
if (TracerSettings.FlushOnUnhandledException || MetricSettings.FlushOnUnhandledException)
|
||||
if (GeneralSettings.FlushOnUnhandledException)
|
||||
{
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
}
|
||||
|
@ -120,20 +130,20 @@ internal static class Instrumentation
|
|||
|
||||
if (TracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.AspNet))
|
||||
{
|
||||
LazyInstrumentationLoader.Add(new AspNetCoreInitializer());
|
||||
LazyInstrumentationLoader.Add(new AspNetCoreInitializer(_pluginManager));
|
||||
}
|
||||
|
||||
if (TracerSettings.EnabledInstrumentations.Contains(TracerInstrumentation.MySqlData))
|
||||
{
|
||||
LazyInstrumentationLoader.Add(new MySqlDataInitializer());
|
||||
LazyInstrumentationLoader.Add(new MySqlDataInitializer(_pluginManager));
|
||||
}
|
||||
#endif
|
||||
|
||||
var builder = Sdk
|
||||
.CreateTracerProviderBuilder()
|
||||
.SetResourceBuilder(ResourceFactory.Create())
|
||||
.UseEnvironmentVariables(TracerSettings)
|
||||
.InvokePlugins(TracerSettings.Plugins);
|
||||
.UseEnvironmentVariables(TracerSettings, _pluginManager)
|
||||
.InvokePlugins(_pluginManager);
|
||||
|
||||
_tracerProvider = builder.Build();
|
||||
Logger.Information("OpenTelemetry tracer initialized.");
|
||||
|
@ -152,8 +162,8 @@ internal static class Instrumentation
|
|||
var builder = Sdk
|
||||
.CreateMeterProviderBuilder()
|
||||
.SetResourceBuilder(ResourceFactory.Create())
|
||||
.UseEnvironmentVariables(MetricSettings)
|
||||
.InvokePlugins(MetricSettings.Plugins);
|
||||
.UseEnvironmentVariables(MetricSettings, _pluginManager)
|
||||
.InvokePlugins(_pluginManager);
|
||||
|
||||
_meterProvider = builder.Build();
|
||||
Logger.Information("OpenTelemetry meter initialized.");
|
||||
|
|
|
@ -16,14 +16,18 @@
|
|||
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
using System;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Loading;
|
||||
|
||||
internal class AspNetCoreInitializer : InstrumentationInitializer
|
||||
{
|
||||
public AspNetCoreInitializer()
|
||||
private readonly PluginManager _pluginManager;
|
||||
|
||||
public AspNetCoreInitializer(PluginManager pluginManager)
|
||||
: base("Microsoft.AspNetCore.Http")
|
||||
{
|
||||
_pluginManager = pluginManager;
|
||||
}
|
||||
|
||||
public override void Initialize(ILifespanManager lifespanManager)
|
||||
|
@ -31,7 +35,10 @@ internal class AspNetCoreInitializer : InstrumentationInitializer
|
|||
var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentation, OpenTelemetry.Instrumentation.AspNetCore");
|
||||
var httpInListenerType = Type.GetType("OpenTelemetry.Instrumentation.AspNetCore.Implementation.HttpInListener, OpenTelemetry.Instrumentation.AspNetCore");
|
||||
|
||||
var httpInListener = Activator.CreateInstance(httpInListenerType, args: new OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions());
|
||||
var options = new OpenTelemetry.Instrumentation.AspNetCore.AspNetCoreInstrumentationOptions();
|
||||
_pluginManager.ConfigureOptions(options);
|
||||
|
||||
var httpInListener = Activator.CreateInstance(httpInListenerType, args: options);
|
||||
var instrumentation = Activator.CreateInstance(instrumentationType, args: httpInListener);
|
||||
|
||||
lifespanManager.Track(instrumentation);
|
||||
|
|
|
@ -17,22 +17,27 @@
|
|||
#if NETCOREAPP3_1_OR_GREATER
|
||||
|
||||
using System;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Loading;
|
||||
|
||||
internal class MySqlDataInitializer : InstrumentationInitializer
|
||||
{
|
||||
public MySqlDataInitializer()
|
||||
private readonly PluginManager _pluginManager;
|
||||
|
||||
public MySqlDataInitializer(PluginManager pluginManager)
|
||||
: base("MySql.Data")
|
||||
{
|
||||
_pluginManager = pluginManager;
|
||||
}
|
||||
|
||||
public override void Initialize(ILifespanManager lifespanManager)
|
||||
{
|
||||
var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.MySqlData.MySqlDataInstrumentation, OpenTelemetry.Instrumentation.MySqlData");
|
||||
var optionsInstrumentationType = Type.GetType("OpenTelemetry.Instrumentation.MySqlData.MySqlDataInstrumentationOptions, OpenTelemetry.Instrumentation.MySqlData");
|
||||
|
||||
var options = Activator.CreateInstance(optionsInstrumentationType);
|
||||
var options = new OpenTelemetry.Instrumentation.MySqlData.MySqlDataInstrumentationOptions();
|
||||
_pluginManager.ConfigureOptions(options);
|
||||
|
||||
var instrumentation = Activator.CreateInstance(instrumentationType, options);
|
||||
|
||||
lifespanManager.Track(instrumentation);
|
||||
|
|
|
@ -43,21 +43,20 @@ internal static class LogBuilderExtensions
|
|||
return builder;
|
||||
}
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Instrumentation.LogSettings;
|
||||
var pluginManager = Instrumentation.PluginManager;
|
||||
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.SetResourceBuilder(ResourceFactory.Create());
|
||||
|
||||
options.IncludeFormattedMessage = settings.IncludeFormattedMessage;
|
||||
|
||||
if (settings.Plugins.Count > 0)
|
||||
{
|
||||
options.InvokePlugins(settings.Plugins);
|
||||
}
|
||||
pluginManager.ConfigureOptions(options);
|
||||
|
||||
if (settings.ConsoleExporterEnabled)
|
||||
{
|
||||
options.AddConsoleExporter();
|
||||
options.AddConsoleExporter(pluginManager.ConfigureOptions);
|
||||
}
|
||||
|
||||
switch (settings.LogExporter)
|
||||
|
@ -72,12 +71,14 @@ internal static class LogBuilderExtensions
|
|||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||
}
|
||||
#endif
|
||||
options.AddOtlpExporter(options =>
|
||||
options.AddOtlpExporter(otlpOptions =>
|
||||
{
|
||||
if (settings.OtlpExportProtocol.HasValue)
|
||||
{
|
||||
options.Protocol = settings.OtlpExportProtocol.Value;
|
||||
otlpOptions.Protocol = settings.OtlpExportProtocol.Value;
|
||||
}
|
||||
|
||||
pluginManager.ConfigureOptions(otlpOptions);
|
||||
});
|
||||
break;
|
||||
case LogExporter.None:
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// <copyright file="PluginManager.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
|
||||
internal class PluginManager
|
||||
{
|
||||
private readonly IReadOnlyList<(Type Type, object Instance)> _plugins;
|
||||
|
||||
public PluginManager(GeneralSettings settings)
|
||||
{
|
||||
var plugins = new List<(Type, object)>();
|
||||
|
||||
foreach (var assemblyQualifiedName in settings.Plugins)
|
||||
{
|
||||
var type = Type.GetType(assemblyQualifiedName, throwOnError: true);
|
||||
var instance = Activator.CreateInstance(type);
|
||||
|
||||
plugins.Add((type, instance));
|
||||
}
|
||||
|
||||
_plugins = plugins;
|
||||
}
|
||||
|
||||
public TracerProviderBuilder ConfigureTracerProviderBuilder(TracerProviderBuilder builder)
|
||||
{
|
||||
return ConfigureBuilder(builder, "ConfigureTracerProvider");
|
||||
}
|
||||
|
||||
public MeterProviderBuilder ConfigureMeterProviderBuilder(MeterProviderBuilder builder)
|
||||
{
|
||||
return ConfigureBuilder(builder, "ConfigureMeterProvider");
|
||||
}
|
||||
|
||||
public void ConfigureOptions<T>(T options)
|
||||
{
|
||||
foreach (var plugin in _plugins)
|
||||
{
|
||||
var mi = plugin.Type.GetMethod("ConfigureOptions", new Type[] { typeof(T) });
|
||||
if (mi is not null)
|
||||
{
|
||||
mi.Invoke(plugin.Instance, new object[] { options });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private T ConfigureBuilder<T>(T builder, string methodName)
|
||||
{
|
||||
foreach (var plugin in _plugins)
|
||||
{
|
||||
var mi = plugin.Type.GetMethod(methodName, new Type[] { typeof(T) });
|
||||
if (mi is not null)
|
||||
{
|
||||
builder = (T)mi.Invoke(plugin.Instance, new object[] { builder });
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using IntegrationTests.Helpers;
|
||||
using Xunit;
|
||||
|
@ -35,6 +36,11 @@ public class PluginsTests : TestHelper
|
|||
using var collector = await MockSpansCollector.Start(Output);
|
||||
SetExporter(collector);
|
||||
collector.Expect("MyCompany.MyProduct.MyLibrary");
|
||||
#if NETFRAMEWORK
|
||||
collector.Expect("OpenTelemetry.HttpWebRequest", span => span.Attributes.Any(att => att.Key == "example.plugin"));
|
||||
#else
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Http", span => span.Attributes.Any(att => att.Key == "example.plugin"));
|
||||
#endif
|
||||
|
||||
SetEnvironmentVariable("OTEL_DOTNET_AUTO_PLUGINS", "TestApplication.Plugins.Plugin, TestApplication.Plugins, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
|
||||
RunTestApplication();
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
// <copyright file="PluginManagerTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using FluentAssertions.Execution;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
using OpenTelemetry.AutoInstrumentation.Plugins;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Tests.Configuration;
|
||||
|
||||
public class PluginManagerTests
|
||||
{
|
||||
[Fact]
|
||||
public void MissingAssembly()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = "Missing.Assembly.PluginType, Missing.Assembly";
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var createAction = () => new PluginManager(settings);
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
createAction.Should().Throw<FileNotFoundException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingPluginTypeFromAssembly()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = "Missing.PluginType";
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var createAction = () => new PluginManager(settings);
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
createAction.Should().Throw<TypeLoadException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PluginTypeMissingMethodDoesNotThrow()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = GetType().AssemblyQualifiedName;
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var pluginManager = new PluginManager(settings);
|
||||
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(pluginManager);
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(pluginManager);
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().NotThrow();
|
||||
meterAction.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PluginTypeMissingDefaultConstructor()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = typeof(MockPluginMissingDefaultConstructor).AssemblyQualifiedName;
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var createAction = () => new PluginManager(settings);
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
createAction.Should().Throw<MissingMethodException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvokeProviderPluginSuccess()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = typeof(MockPlugin).AssemblyQualifiedName;
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var pluginManager = new PluginManager(settings);
|
||||
|
||||
var traceProviderBuilderMock = new Mock<TracerProviderBuilder>();
|
||||
traceProviderBuilderMock.Setup(x => x.AddSource(It.Is<string>(x => x == "My.Custom.Source"))).Verifiable();
|
||||
|
||||
var meterProviderBuilderMock = new Mock<MeterProviderBuilder>();
|
||||
meterProviderBuilderMock.Setup(x => x.AddMeter(It.Is<string>(x => x == "My.Custom.Meter"))).Verifiable();
|
||||
|
||||
var tracerAction = () => traceProviderBuilderMock.Object.InvokePlugins(pluginManager);
|
||||
var meterAction = () => meterProviderBuilderMock.Object.InvokePlugins(pluginManager);
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().NotThrow();
|
||||
meterAction.Should().NotThrow();
|
||||
|
||||
traceProviderBuilderMock.Verify();
|
||||
meterProviderBuilderMock.Verify();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigureOptionsSuccess()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = typeof(MockPlugin).AssemblyQualifiedName;
|
||||
var settings = GetSettings(pluginAssemblyQualifiedName);
|
||||
var pluginManager = new PluginManager(settings);
|
||||
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.IncludeFormattedMessage = false;
|
||||
pluginManager.ConfigureOptions(options);
|
||||
|
||||
// Verify that plugin changes the state
|
||||
options.IncludeFormattedMessage.Should().BeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
logsAction.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
|
||||
private static GeneralSettings GetSettings(string assemblyQualifiedName)
|
||||
{
|
||||
var config = new NameValueConfigurationSource(new NameValueCollection()
|
||||
{
|
||||
{ ConfigurationKeys.ProviderPlugins, assemblyQualifiedName }
|
||||
});
|
||||
|
||||
return new GeneralSettings(config);
|
||||
}
|
||||
|
||||
public class MockPlugin
|
||||
{
|
||||
public TracerProviderBuilder ConfigureTracerProvider(TracerProviderBuilder builder)
|
||||
{
|
||||
builder.AddSource("My.Custom.Source");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MeterProviderBuilder ConfigureMeterProvider(MeterProviderBuilder builder)
|
||||
{
|
||||
builder.AddMeter("My.Custom.Meter");
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public OpenTelemetryLoggerOptions ConfigureOptions(OpenTelemetryLoggerOptions options)
|
||||
{
|
||||
// Dummy overwritten setting
|
||||
options.IncludeFormattedMessage = true;
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
public class MockPluginMissingDefaultConstructor : MockPlugin
|
||||
{
|
||||
public MockPluginMissingDefaultConstructor(string ignored)
|
||||
{
|
||||
throw new InvalidOperationException("this plugin is not expected to be successfully constructed");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
// <copyright file="PluginsConfigurationHelperTests.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using FluentAssertions.Execution;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenTelemetry.AutoInstrumentation.Configuration;
|
||||
using OpenTelemetry.Logs;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
using Xunit;
|
||||
|
||||
namespace OpenTelemetry.AutoInstrumentation.Tests.Configuration;
|
||||
|
||||
public class PluginsConfigurationHelperTests
|
||||
{
|
||||
[Fact]
|
||||
public void MissingAssembly()
|
||||
{
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(new[] { "Missing.Assembly.PluginType, Missing.Assembly" });
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(new[] { "Missing.Assembly.PluginType, Missing.Assembly" });
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.InvokePlugins(new[] { "Missing.Assembly.PluginType, Missing.Assembly" });
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().Throw<FileNotFoundException>();
|
||||
meterAction.Should().Throw<FileNotFoundException>();
|
||||
logsAction.Should().Throw<FileNotFoundException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MissingPluginTypeFromAssembly()
|
||||
{
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(new[] { "Missing.PluginType" });
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(new[] { "Missing.PluginType" });
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.InvokePlugins(new[] { "Missing.PluginType" });
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().Throw<TypeLoadException>();
|
||||
meterAction.Should().Throw<TypeLoadException>();
|
||||
logsAction.Should().Throw<TypeLoadException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PluginTypeMissingMethodDoesNotThrow()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = GetType().AssemblyQualifiedName;
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().NotThrow();
|
||||
meterAction.Should().NotThrow();
|
||||
logsAction.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PluginTypeMissingDefaultConstructor()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = typeof(MockPluginMissingDefaultConstructor).AssemblyQualifiedName;
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().Throw<MissingMethodException>();
|
||||
meterAction.Should().Throw<MissingMethodException>();
|
||||
logsAction.Should().Throw<MissingMethodException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvokePluginSuccess()
|
||||
{
|
||||
var pluginAssemblyQualifiedName = typeof(MockPlugin).AssemblyQualifiedName;
|
||||
var tracerAction = () => Sdk.CreateTracerProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var meterAction = () => Sdk.CreateMeterProviderBuilder().InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
var logsAction = () => LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddOpenTelemetry(options =>
|
||||
{
|
||||
options.InvokePlugins(new[] { pluginAssemblyQualifiedName });
|
||||
});
|
||||
});
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
tracerAction.Should().NotThrow();
|
||||
meterAction.Should().NotThrow();
|
||||
logsAction.Should().NotThrow();
|
||||
}
|
||||
}
|
||||
|
||||
public class MockPlugin
|
||||
{
|
||||
public TracerProviderBuilder ConfigureTracerProvider(TracerProviderBuilder builder)
|
||||
{
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MeterProviderBuilder ConfigureMeterProvider(MeterProviderBuilder builder)
|
||||
{
|
||||
return builder;
|
||||
}
|
||||
|
||||
public OpenTelemetryLoggerOptions ConfigureLoggerOptions(OpenTelemetryLoggerOptions options)
|
||||
{
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
public class MockPluginMissingDefaultConstructor : MockPlugin
|
||||
{
|
||||
public MockPluginMissingDefaultConstructor(string ignored)
|
||||
{
|
||||
throw new InvalidOperationException("this plugin is not expected to be successfully constructed");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,12 +33,12 @@ public class SettingsTests : IDisposable
|
|||
|
||||
public static IEnumerable<object[]> ExporterEnvVarAndLoadSettingsAction()
|
||||
{
|
||||
yield return new object[] { ConfigurationKeys.Traces.Exporter, new Action(() => TracerSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Traces.Instrumentations, new Action(() => TracerSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Metrics.Exporter, new Action(() => MetricSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Metrics.Instrumentations, new Action(() => MetricSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Logs.Exporter, new Action(() => LogSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Sdk.Propagators, new Action(() => SdkSettings.FromDefaultSources()) };
|
||||
yield return new object[] { ConfigurationKeys.Traces.Exporter, new Action(() => Settings.FromDefaultSources<TracerSettings>()) };
|
||||
yield return new object[] { ConfigurationKeys.Traces.Instrumentations, new Action(() => Settings.FromDefaultSources<TracerSettings>()) };
|
||||
yield return new object[] { ConfigurationKeys.Metrics.Exporter, new Action(() => Settings.FromDefaultSources<MetricSettings>()) };
|
||||
yield return new object[] { ConfigurationKeys.Metrics.Instrumentations, new Action(() => Settings.FromDefaultSources<MetricSettings>()) };
|
||||
yield return new object[] { ConfigurationKeys.Logs.Exporter, new Action(() => Settings.FromDefaultSources<LogSettings>()) };
|
||||
yield return new object[] { ConfigurationKeys.Sdk.Propagators, new Action(() => Settings.FromDefaultSources<SdkSettings>()) };
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -46,10 +46,24 @@ public class SettingsTests : IDisposable
|
|||
ClearEnvVars();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
internal void GeneralSettings_DefaultValues()
|
||||
{
|
||||
var settings = Settings.FromDefaultSources<GeneralSettings>();
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
settings.Plugins.Should().BeEmpty();
|
||||
settings.FlushOnUnhandledException.Should().BeFalse();
|
||||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
internal void TracerSettings_DefaultValues()
|
||||
{
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
|
@ -58,11 +72,9 @@ public class SettingsTests : IDisposable
|
|||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||
settings.ConsoleExporterEnabled.Should().BeFalse();
|
||||
settings.EnabledInstrumentations.Should().NotBeEmpty();
|
||||
settings.Plugins.Should().BeEmpty();
|
||||
settings.ActivitySources.Should().BeEquivalentTo(new List<string> { "OpenTelemetry.AutoInstrumentation.*" });
|
||||
settings.LegacySources.Should().BeEmpty();
|
||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||
settings.FlushOnUnhandledException.Should().BeFalse();
|
||||
|
||||
// Instrumentation options tests
|
||||
settings.InstrumentationOptions.GraphQLSetDocument.Should().BeFalse();
|
||||
|
@ -72,7 +84,7 @@ public class SettingsTests : IDisposable
|
|||
[Fact]
|
||||
internal void MeterSettings_DefaultValues()
|
||||
{
|
||||
var settings = MetricSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<MetricSettings>();
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
|
@ -81,17 +93,15 @@ public class SettingsTests : IDisposable
|
|||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||
settings.ConsoleExporterEnabled.Should().BeFalse();
|
||||
settings.EnabledInstrumentations.Should().NotBeEmpty();
|
||||
settings.Plugins.Should().BeEmpty();
|
||||
settings.Meters.Should().BeEmpty();
|
||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||
settings.FlushOnUnhandledException.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
internal void LogSettings_DefaultValues()
|
||||
{
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
|
@ -99,17 +109,15 @@ public class SettingsTests : IDisposable
|
|||
settings.OtlpExportProtocol.Should().Be(OtlpExportProtocol.HttpProtobuf);
|
||||
settings.ConsoleExporterEnabled.Should().BeFalse();
|
||||
settings.EnabledInstrumentations.Should().NotBeEmpty();
|
||||
settings.Plugins.Should().BeEmpty();
|
||||
settings.IncludeFormattedMessage.Should().BeFalse();
|
||||
settings.Http2UnencryptedSupportEnabled.Should().BeFalse();
|
||||
settings.FlushOnUnhandledException.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
internal void SdkSettings_DefaultValues()
|
||||
{
|
||||
var settings = SdkSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<SdkSettings>();
|
||||
|
||||
using (new AssertionScope())
|
||||
{
|
||||
|
@ -126,7 +134,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Traces.Exporter, tracesExporter);
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
settings.TracesExporter.Should().Be(expectedTracesExporter);
|
||||
}
|
||||
|
@ -139,7 +147,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Exporter, metricExporter);
|
||||
|
||||
var settings = MetricSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<MetricSettings>();
|
||||
|
||||
settings.MetricExporter.Should().Be(expectedMetricsExporter);
|
||||
}
|
||||
|
@ -151,7 +159,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.Exporter, logExporter);
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
settings.LogExporter.Should().Be(expectedLogExporter);
|
||||
}
|
||||
|
@ -167,7 +175,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Sdk.Propagators, propagators);
|
||||
|
||||
var settings = SdkSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<SdkSettings>();
|
||||
|
||||
settings.Propagators.Should().BeEquivalentTo(expectedPropagators);
|
||||
}
|
||||
|
@ -191,7 +199,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Traces.Instrumentations, tracerInstrumentation);
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<TracerInstrumentation> { expectedTracerInstrumentation });
|
||||
}
|
||||
|
@ -202,7 +210,7 @@ public class SettingsTests : IDisposable
|
|||
Environment.SetEnvironmentVariable(ConfigurationKeys.Traces.Instrumentations, $"{nameof(TracerInstrumentation.AspNet)},{nameof(TracerInstrumentation.GraphQL)}");
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Traces.DisabledInstrumentations, nameof(TracerInstrumentation.GraphQL));
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<TracerInstrumentation> { TracerInstrumentation.AspNet });
|
||||
}
|
||||
|
@ -216,7 +224,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, meterInstrumentation);
|
||||
|
||||
var settings = MetricSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<MetricSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<MetricInstrumentation> { expectedMetricInstrumentation });
|
||||
}
|
||||
|
@ -227,7 +235,7 @@ public class SettingsTests : IDisposable
|
|||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, $"{nameof(MetricInstrumentation.NetRuntime)},{nameof(MetricInstrumentation.AspNet)}");
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.DisabledInstrumentations, nameof(MetricInstrumentation.AspNet));
|
||||
|
||||
var settings = MetricSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<MetricSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<MetricInstrumentation> { MetricInstrumentation.NetRuntime });
|
||||
}
|
||||
|
@ -238,7 +246,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Metrics.Instrumentations, logInstrumentation);
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEquivalentTo(new List<LogInstrumentation> { expectedLogInstrumentation });
|
||||
}
|
||||
|
@ -248,7 +256,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.DisabledInstrumentations, nameof(LogInstrumentation.ILogger));
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
settings.EnabledInstrumentations.Should().BeEmpty();
|
||||
}
|
||||
|
@ -260,7 +268,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Logs.IncludeFormattedMessage, includeFormattedMessage);
|
||||
|
||||
var settings = LogSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<LogSettings>();
|
||||
|
||||
settings.IncludeFormattedMessage.Should().Be(expectedValue);
|
||||
}
|
||||
|
@ -283,7 +291,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.ExporterOtlpProtocol, otlpProtocol);
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
// null values for expected data will be handled by OTel .NET SDK
|
||||
settings.OtlpExportProtocol.Should().Be(expectedOtlpExportProtocol);
|
||||
|
@ -297,7 +305,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.Http2UnencryptedSupportEnabled, http2UnencryptedSupportEnabled);
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<TracerSettings>();
|
||||
|
||||
settings.Http2UnencryptedSupportEnabled.Should().Be(expectedValue);
|
||||
}
|
||||
|
@ -310,7 +318,7 @@ public class SettingsTests : IDisposable
|
|||
{
|
||||
Environment.SetEnvironmentVariable(ConfigurationKeys.FlushOnUnhandledException, flushOnUnhandledException);
|
||||
|
||||
var settings = TracerSettings.FromDefaultSources();
|
||||
var settings = Settings.FromDefaultSources<GeneralSettings>();
|
||||
|
||||
settings.FlushOnUnhandledException.Should().Be(expectedValue);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// limitations under the License.
|
||||
// </copyright>
|
||||
|
||||
using OpenTelemetry.Instrumentation.Http;
|
||||
using OpenTelemetry.Metrics;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
|
@ -30,4 +31,28 @@ public class Plugin
|
|||
{
|
||||
return builder.AddMeter(TestApplication.Smoke.Program.SourceName);
|
||||
}
|
||||
|
||||
public void ConfigureOptions(HttpClientInstrumentationOptions options)
|
||||
{
|
||||
options.Enrich = (activity, eventName, rawObject) =>
|
||||
{
|
||||
if (eventName.Equals("OnStartActivity"))
|
||||
{
|
||||
activity.SetTag("example.plugin", "MyExamplePlugin");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if NETFRAMEWORK
|
||||
public void ConfigureOptions(HttpWebRequestInstrumentationOptions options)
|
||||
{
|
||||
options.Enrich = (activity, eventName, rawObject) =>
|
||||
{
|
||||
if (eventName.Equals("OnStartActivity"))
|
||||
{
|
||||
activity.SetTag("example.plugin", "MyExamplePlugin");
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry" Version="1.3.1" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.4" />
|
||||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Loading…
Reference in New Issue