Dependency injection support (#1889)

This commit is contained in:
Mikel Blanchard 2021-03-26 11:36:18 -07:00 committed by GitHub
parent 5f1acbf8ed
commit 0208fd69f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 710 additions and 312 deletions

View File

@ -23,7 +23,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
@ -63,20 +63,17 @@ namespace Examples.AspNetCore
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue<string>("Jaeger:ServiceName")))
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddJaegerExporter(jaegerOptions =>
{
jaegerOptions.AgentHost = this.Configuration.GetValue<string>("Jaeger:Host");
jaegerOptions.AgentPort = this.Configuration.GetValue<int>("Jaeger:Port");
}));
.AddJaegerExporter());
services.Configure<JaegerExporterOptions>(this.Configuration.GetSection("Jaeger"));
break;
case "zipkin":
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddZipkinExporter(zipkinOptions =>
{
zipkinOptions.Endpoint = new Uri(this.Configuration.GetValue<string>("Zipkin:Endpoint"));
}));
.AddZipkinExporter());
services.Configure<ZipkinExporterOptions>(this.Configuration.GetSection("Zipkin"));
break;
case "otlp":
// Adding the OtlpExporter creates a GrpcChannel.

View File

@ -10,8 +10,8 @@
"UseExporter": "console",
"Jaeger": {
"ServiceName": "jaeger-test",
"Host": "localhost",
"Port": 6831
"AgentHost": "localhost",
"AgentPort": 6831
},
"Zipkin": {
"ServiceName": "zipkin-test",

View File

@ -0,0 +1 @@
OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void

View File

@ -0,0 +1 @@
OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void

View File

@ -22,12 +22,15 @@ namespace OpenTelemetry.Trace
/// </summary>
public abstract class TracerProviderBuilder
{
internal TracerProviderBuilder()
/// <summary>
/// Initializes a new instance of the <see cref="TracerProviderBuilder"/> class.
/// </summary>
protected TracerProviderBuilder()
{
}
/// <summary>
/// Adds an instrumentation to the provider.
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="TInstrumentation">Type of instrumentation class.</typeparam>
/// <param name="instrumentationFactory">Function that builds instrumentation.</param>

View File

@ -38,11 +38,24 @@ namespace OpenTelemetry.Trace
throw new ArgumentNullException(nameof(builder));
}
var exporterOptions = new JaegerExporterOptions();
configure?.Invoke(exporterOptions);
var jaegerExporter = new JaegerExporter(exporterOptions);
if (builder is IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
return deferredTracerProviderBuilder.Configure((sp, builder) =>
{
AddJaegerExporter(builder, sp.GetOptions<JaegerExporterOptions>(), configure);
});
}
if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple)
return AddJaegerExporter(builder, new JaegerExporterOptions(), configure);
}
private static TracerProviderBuilder AddJaegerExporter(TracerProviderBuilder builder, JaegerExporterOptions options, Action<JaegerExporterOptions> configure = null)
{
configure?.Invoke(options);
var jaegerExporter = new JaegerExporter(options);
if (options.ExportProcessorType == ExportProcessorType.Simple)
{
return builder.AddProcessor(new SimpleActivityExportProcessor(jaegerExporter));
}
@ -50,10 +63,10 @@ namespace OpenTelemetry.Trace
{
return builder.AddProcessor(new BatchActivityExportProcessor(
jaegerExporter,
exporterOptions.BatchExportProcessorOptions.MaxQueueSize,
exporterOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
exporterOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
exporterOptions.BatchExportProcessorOptions.MaxExportBatchSize));
options.BatchExportProcessorOptions.MaxQueueSize,
options.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
options.BatchExportProcessorOptions.MaxExportBatchSize));
}
}
}

View File

@ -22,6 +22,7 @@
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PooledList.cs" Link="Includes\PooledList.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PeerServiceResolver.cs" Link="Includes\PeerServiceResolver.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ResourceSemanticConventions.cs" Link="Includes\ResourceSemanticConventions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ServiceProviderExtensions.cs" Link="Includes\ServiceProviderExtensions.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -17,6 +17,7 @@
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PooledList.cs" Link="Includes\PooledList.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PeerServiceResolver.cs" Link="Includes\PeerServiceResolver.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ResourceSemanticConventions.cs" Link="Includes\ResourceSemanticConventions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ServiceProviderExtensions.cs" Link="Includes\ServiceProviderExtensions.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -38,11 +38,24 @@ namespace OpenTelemetry.Trace
throw new ArgumentNullException(nameof(builder));
}
var exporterOptions = new ZipkinExporterOptions();
configure?.Invoke(exporterOptions);
var zipkinExporter = new ZipkinExporter(exporterOptions);
if (builder is IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
return deferredTracerProviderBuilder.Configure((sp, builder) =>
{
AddZipkinExporter(builder, sp.GetOptions<ZipkinExporterOptions>(), configure);
});
}
if (exporterOptions.ExportProcessorType == ExportProcessorType.Simple)
return AddZipkinExporter(builder, new ZipkinExporterOptions(), configure);
}
private static TracerProviderBuilder AddZipkinExporter(TracerProviderBuilder builder, ZipkinExporterOptions options, Action<ZipkinExporterOptions> configure = null)
{
configure?.Invoke(options);
var zipkinExporter = new ZipkinExporter(options);
if (options.ExportProcessorType == ExportProcessorType.Simple)
{
return builder.AddProcessor(new SimpleActivityExportProcessor(zipkinExporter));
}
@ -50,10 +63,10 @@ namespace OpenTelemetry.Trace
{
return builder.AddProcessor(new BatchActivityExportProcessor(
zipkinExporter,
exporterOptions.BatchExportProcessorOptions.MaxQueueSize,
exporterOptions.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
exporterOptions.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
exporterOptions.BatchExportProcessorOptions.MaxExportBatchSize));
options.BatchExportProcessorOptions.MaxQueueSize,
options.BatchExportProcessorOptions.ScheduledDelayMilliseconds,
options.BatchExportProcessorOptions.ExporterTimeoutMilliseconds,
options.BatchExportProcessorOptions.MaxExportBatchSize));
}
}
}

View File

@ -1,4 +1,9 @@
Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions
OpenTelemetry.Trace.TracerProviderBuilderExtensions
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder> configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Build(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.IServiceProvider serviceProvider) -> OpenTelemetry.Trace.TracerProvider
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Configure(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder

View File

@ -2,6 +2,11 @@
## Unreleased
* Added `AddInstrumentation<T>`, `AddProcessor<T>`, `SetSampler<T>`, and
`Configure` extensions to support dependency injection through the
OpenTelemetry.Extensions.Hosting `TracerProviderBuilder`.
([#1889](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1889))
## 1.0.0-rc3
Released 2021-Mar-19

View File

@ -0,0 +1,126 @@
// <copyright file="TracerProviderBuilderHosting.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 System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
namespace OpenTelemetry.Trace
{
/// <summary>
/// A <see cref="TracerProviderBuilderBase"/> with support for deferred initialization using <see cref="IServiceProvider"/> for dependency injection.
/// </summary>
internal class TracerProviderBuilderHosting : TracerProviderBuilderBase, IDeferredTracerProviderBuilder
{
private readonly List<InstrumentationFactory> instrumentationFactories = new List<InstrumentationFactory>();
private readonly List<Type> processorTypes = new List<Type>();
private readonly List<Action<IServiceProvider, TracerProviderBuilder>> configurationActions = new List<Action<IServiceProvider, TracerProviderBuilder>>();
private Type samplerType;
public TracerProviderBuilderHosting(IServiceCollection services)
{
this.Services = services ?? throw new ArgumentNullException(nameof(services));
}
public IServiceCollection Services { get; }
public TracerProviderBuilder AddInstrumentation<TInstrumentation>(
Func<IServiceProvider, TInstrumentation> instrumentationFactory)
where TInstrumentation : class
{
if (instrumentationFactory == null)
{
throw new ArgumentNullException(nameof(instrumentationFactory));
}
this.instrumentationFactories.Add(
new InstrumentationFactory(
typeof(TInstrumentation).Name,
"semver:" + typeof(TInstrumentation).Assembly.GetName().Version,
typeof(TInstrumentation)));
return this;
}
public TracerProviderBuilder AddProcessor<T>()
where T : BaseProcessor<Activity>
{
this.processorTypes.Add(typeof(T));
return this;
}
public TracerProviderBuilder SetSampler<T>()
where T : Sampler
{
this.samplerType = typeof(T);
return this;
}
public TracerProviderBuilder Configure(Action<IServiceProvider, TracerProviderBuilder> configure)
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
this.configurationActions.Add(configure);
return this;
}
public TracerProvider Build(IServiceProvider serviceProvider)
{
foreach (InstrumentationFactory instrumentationFactory in this.instrumentationFactories)
{
this.AddInstrumentation(
instrumentationFactory.Name,
instrumentationFactory.Version,
() => serviceProvider.GetRequiredService(instrumentationFactory.Type));
}
foreach (Type processorType in this.processorTypes)
{
this.AddProcessor((BaseProcessor<Activity>)serviceProvider.GetRequiredService(processorType));
}
if (this.samplerType != null)
{
this.SetSampler((Sampler)serviceProvider.GetRequiredService(this.samplerType));
}
foreach (Action<IServiceProvider, TracerProviderBuilder> configureAction in this.configurationActions)
{
configureAction(serviceProvider, this);
}
return this.Build();
}
private readonly struct InstrumentationFactory
{
public readonly string Name;
public readonly string Version;
public readonly Type Type;
internal InstrumentationFactory(string name, string version, Type type)
{
this.Name = name;
this.Version = version;
this.Type = type;
}
}
}
}

View File

@ -17,7 +17,6 @@
using System;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Extensions.Hosting.Implementation;
using OpenTelemetry.Trace;
@ -35,8 +34,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services)
{
services.AddOpenTelemetryTracing(builder => { });
return services;
return services.AddOpenTelemetryTracing(builder => { });
}
/// <summary>
@ -52,63 +50,9 @@ namespace Microsoft.Extensions.DependencyInjection
throw new ArgumentNullException(nameof(configure));
}
var builder = Sdk.CreateTracerProviderBuilder();
var builder = new TracerProviderBuilderHosting(services);
configure(builder);
services.AddOpenTelemetryTracing(() => builder.Build());
return services;
}
/// <summary>
/// Adds OpenTelemetry TracerProvider to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="configure">The <see cref="TracerProviderBuilder"/> action to configure TracerProviderBuilder.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services, Action<IServiceProvider, TracerProviderBuilder> configure)
{
if (configure is null)
{
throw new ArgumentNullException(nameof(configure));
}
var builder = Sdk.CreateTracerProviderBuilder();
services.AddOpenTelemetryTracing((sp) =>
{
configure(sp, builder);
return builder.Build();
});
return services;
}
/// <summary>
/// Adds OpenTelemetry TracerProvider to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="createTracerProvider">A delegate that provides the tracer provider to be registered.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
private static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services, Func<TracerProvider> createTracerProvider)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}
if (createTracerProvider is null)
{
throw new ArgumentNullException(nameof(createTracerProvider));
}
try
{
services.AddSingleton(s => createTracerProvider());
AddOpenTelemetryTracingInternal(services);
}
catch (Exception ex)
{
HostingExtensionsEventSource.Log.FailedInitialize(ex);
}
return services;
return services.AddOpenTelemetryTracing(sp => builder.Build(sp));
}
/// <summary>
@ -131,8 +75,8 @@ namespace Microsoft.Extensions.DependencyInjection
try
{
services.AddSingleton(s => createTracerProvider(s));
AddOpenTelemetryTracingInternal(services);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
return services.AddSingleton(s => createTracerProvider(s));
}
catch (Exception ex)
{
@ -141,10 +85,5 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
private static void AddOpenTelemetryTracingInternal(IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
}
}
}

View File

@ -0,0 +1,115 @@
// <copyright file="TracerProviderBuilderExtensions.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.Diagnostics;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Contains extension methods for the <see cref="TracerProviderBuilder"/> class.
/// </summary>
public static class TracerProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : class
{
if (tracerProviderBuilder is TracerProviderBuilderHosting tracerProviderBuilderHosting)
{
tracerProviderBuilderHosting.AddInstrumentation<T>();
}
return tracerProviderBuilder;
}
/// <summary>
/// Adds a processor to the provider.
/// </summary>
/// <typeparam name="T">Processor type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddProcessor<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : BaseProcessor<Activity>
{
if (tracerProviderBuilder is TracerProviderBuilderHosting tracerProviderBuilderHosting)
{
tracerProviderBuilderHosting.AddProcessor<T>();
}
return tracerProviderBuilder;
}
/// <summary>
/// Sets the sampler on the provider.
/// </summary>
/// <typeparam name="T">Sampler type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetSampler<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : Sampler
{
if (tracerProviderBuilder is TracerProviderBuilderHosting tracerProviderBuilderHosting)
{
tracerProviderBuilderHosting.SetSampler<T>();
}
return tracerProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see cref="TracerProviderBuilder"/> during initialization.
/// </summary>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder Configure(this TracerProviderBuilder tracerProviderBuilder, Action<IServiceProvider, TracerProviderBuilder> configure)
{
if (tracerProviderBuilder is IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
deferredTracerProviderBuilder.Configure(configure);
}
return tracerProviderBuilder;
}
/// <summary>
/// Run the configured actions to initialize the <see cref="TracerProvider"/>.
/// </summary>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <returns><see cref="TracerProvider"/>.</returns>
public static TracerProvider Build(this TracerProviderBuilder tracerProviderBuilder, IServiceProvider serviceProvider)
{
if (tracerProviderBuilder is TracerProviderBuilderHosting tracerProviderBuilderHosting)
{
return tracerProviderBuilderHosting.Build(serviceProvider);
}
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
return tracerProviderBuilderBase.Build();
}
return null;
}
}
}

View File

@ -1,4 +1,12 @@
OpenTelemetry.Trace.IDeferredTracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void
OpenTelemetry.Trace.TracerProviderBuilderBase
OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func<object> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider
OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation<TInstrumentation>(System.Func<TInstrumentation> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddLegacySource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool

View File

@ -1,4 +1,12 @@
OpenTelemetry.Trace.IDeferredTracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void
OpenTelemetry.Trace.TracerProviderBuilderBase
OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func<object> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider
OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation<TInstrumentation>(System.Func<TInstrumentation> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddLegacySource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderExtensions.ForceFlush(this OpenTelemetry.Trace.TracerProvider provider, int timeoutMilliseconds = -1) -> bool

View File

@ -8,7 +8,16 @@ OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeScopes.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ParseStateValues.get -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ParseStateValues.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetResourceBuilder(OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
OpenTelemetry.Trace.IDeferredTracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection
OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void
OpenTelemetry.Trace.TracerProviderBuilderBase
OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func<object> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider
OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation<TInstrumentation>(System.Func<TInstrumentation> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Logs.OpenTelemetryLoggerProvider.Dispose(bool disposing) -> void
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddLegacySource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder

View File

@ -8,7 +8,16 @@ OpenTelemetry.Logs.OpenTelemetryLoggerOptions.IncludeScopes.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ParseStateValues.get -> bool
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.ParseStateValues.set -> void
OpenTelemetry.Logs.OpenTelemetryLoggerOptions.SetResourceBuilder(OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions
OpenTelemetry.Trace.IDeferredTracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Configure(System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.IDeferredTracerProviderBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection
OpenTelemetry.Trace.ParentBasedSampler.ParentBasedSampler(OpenTelemetry.Trace.Sampler rootSampler, OpenTelemetry.Trace.Sampler remoteParentSampled = null, OpenTelemetry.Trace.Sampler remoteParentNotSampled = null, OpenTelemetry.Trace.Sampler localParentSampled = null, OpenTelemetry.Trace.Sampler localParentNotSampled = null) -> void
OpenTelemetry.Trace.TracerProviderBuilderBase
OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation(string instrumentationName, string instrumentationVersion, System.Func<object> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
OpenTelemetry.Trace.TracerProviderBuilderBase.Build() -> OpenTelemetry.Trace.TracerProvider
OpenTelemetry.Trace.TracerProviderBuilderBase.TracerProviderBuilderBase() -> void
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddInstrumentation<TInstrumentation>(System.Func<TInstrumentation> instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Trace.TracerProviderBuilderBase.AddSource(params string[] names) -> OpenTelemetry.Trace.TracerProviderBuilder
override OpenTelemetry.Logs.OpenTelemetryLoggerProvider.Dispose(bool disposing) -> void
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddLegacySource(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, string operationName) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetErrorStatusOnException(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, bool enabled = true) -> OpenTelemetry.Trace.TracerProviderBuilder

View File

@ -61,6 +61,10 @@ Released 2021-Mar-19
* Added `SetResourceBuilder` support to `OpenTelemetryLoggerOptions`.
([#1913](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1913))
* Added `IDeferredTracerProviderBuilder` and `TracerProviderBuilderBase` to
support dependency injection through OpenTelemetry.Extensions.Hosting.
([#1889](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1889))
## 1.0.1
Released 2021-Feb-10

View File

@ -0,0 +1,47 @@
// <copyright file="ServiceProviderExtensions.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>
#if NET461 || NETSTANDARD2_0
using Microsoft.Extensions.Options;
#endif
namespace System
{
/// <summary>
/// Extension methods for OpenTelemetry dependency injection support.
/// </summary>
internal static class ServiceProviderExtensions
{
/// <summary>
/// Get options from the supplied <see cref="IServiceProvider"/>.
/// </summary>
/// <typeparam name="T">Options type.</typeparam>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <returns>Options instance.</returns>
public static T GetOptions<T>(this IServiceProvider serviceProvider)
where T : class, new()
{
#if NET461 || NETSTANDARD2_0
IOptions<T> options = (IOptions<T>)serviceProvider.GetService(typeof(IOptions<T>));
// Note: options could be null if user never invoked services.AddOptions().
return options?.Value ?? new T();
#else
return new T();
#endif
}
}
}

View File

@ -0,0 +1,42 @@
// <copyright file="IDeferredTracerProviderBuilder.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;
#if NET461_OR_GREATER || NETSTANDARD2_0
using Microsoft.Extensions.DependencyInjection;
#endif
namespace OpenTelemetry.Trace
{
/// <summary>
/// Describes a tracer provider builder that supports deferred
/// initialization using an <see cref="IServiceProvider"/> to perform
/// dependency injection.
/// </summary>
public interface IDeferredTracerProviderBuilder
{
#if NET461_OR_GREATER || NETSTANDARD2_0
IServiceCollection Services { get; }
#endif
/// <summary>
/// Register a callback action to configure the <see cref="TracerProviderBuilder"/> during initialization.
/// </summary>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
TracerProviderBuilder Configure(Action<IServiceProvider, TracerProviderBuilder> configure);
}
}

View File

@ -0,0 +1,230 @@
// <copyright file="TracerProviderBuilderBase.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 System.Diagnostics;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Build TracerProvider with Resource, Sampler, Processors and Instrumentation.
/// </summary>
public abstract class TracerProviderBuilderBase : TracerProviderBuilder
{
private readonly List<InstrumentationFactory> instrumentationFactories = new List<InstrumentationFactory>();
private readonly List<BaseProcessor<Activity>> processors = new List<BaseProcessor<Activity>>();
private readonly List<string> sources = new List<string>();
private readonly Dictionary<string, bool> legacyActivityOperationNames = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private ResourceBuilder resourceBuilder = ResourceBuilder.CreateDefault();
private Sampler sampler = new ParentBasedSampler(new AlwaysOnSampler());
protected TracerProviderBuilderBase()
{
}
/// <inheritdoc />
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(
Func<TInstrumentation> instrumentationFactory)
where TInstrumentation : class
{
if (instrumentationFactory == null)
{
throw new ArgumentNullException(nameof(instrumentationFactory));
}
this.instrumentationFactories.Add(
new InstrumentationFactory(
typeof(TInstrumentation).Name,
"semver:" + typeof(TInstrumentation).Assembly.GetName().Version,
instrumentationFactory));
return this;
}
/// <inheritdoc />
public override TracerProviderBuilder AddSource(params string[] names)
{
if (names == null)
{
throw new ArgumentNullException(nameof(names));
}
foreach (var name in names)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException($"{nameof(names)} contains null or whitespace string.");
}
// TODO: We need to fix the listening model.
// Today it ignores version.
this.sources.Add(name);
}
return this;
}
/// <summary>
/// Sets whether the status of <see cref="System.Diagnostics.Activity"/>
/// should be set to <c>Status.Error</c> when it ended abnormally due to an unhandled exception.
/// </summary>
/// <param name="enabled">Enabled or not.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetErrorStatusOnException(bool enabled)
{
ExceptionProcessor existingExceptionProcessor = null;
if (this.processors.Count > 0)
{
existingExceptionProcessor = this.processors[0] as ExceptionProcessor;
}
if (enabled)
{
if (existingExceptionProcessor == null)
{
try
{
this.processors.Insert(0, new ExceptionProcessor());
}
catch (Exception ex)
{
throw new NotSupportedException("SetErrorStatusOnException is not supported on this platform.", ex);
}
}
}
else
{
if (existingExceptionProcessor != null)
{
this.processors.RemoveAt(0);
existingExceptionProcessor.Dispose();
}
}
return this;
}
/// <summary>
/// Sets sampler.
/// </summary>
/// <param name="sampler">Sampler instance.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetSampler(Sampler sampler)
{
this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler));
return this;
}
/// <summary>
/// Sets the <see cref="ResourceBuilder"/> from which the Resource associated with
/// this provider is built from. Overwrites currently set ResourceBuilder.
/// </summary>
/// <param name="resourceBuilder"><see cref="ResourceBuilder"/> from which Resource will be built.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
this.resourceBuilder = resourceBuilder ?? throw new ArgumentNullException(nameof(resourceBuilder));
return this;
}
/// <summary>
/// Adds processor to the provider.
/// </summary>
/// <param name="processor">Activity processor to add.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder AddProcessor(BaseProcessor<Activity> processor)
{
if (processor == null)
{
throw new ArgumentNullException(nameof(processor));
}
this.processors.Add(processor);
return this;
}
/// <summary>
/// Adds a listener for <see cref="Activity"/> objects created with the given operation name to the <see cref="TracerProviderBuilder"/>.
/// </summary>
/// <remarks>
/// This is provided to capture legacy <see cref="Activity"/> objects created without using the <see cref="ActivitySource"/> API.
/// </remarks>
/// <param name="operationName">Operation name of the <see cref="Activity"/> objects to capture.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder AddLegacySource(string operationName)
{
if (string.IsNullOrWhiteSpace(operationName))
{
throw new ArgumentException($"{nameof(operationName)} contains null or whitespace string.");
}
this.legacyActivityOperationNames[operationName] = true;
return this;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <param name="instrumentationName">Instrumentation name.</param>
/// <param name="instrumentationVersion">Instrumentation version.</param>
/// <param name="instrumentationFactory">Function that builds instrumentation.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
protected TracerProviderBuilder AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
Func<object> instrumentationFactory)
{
this.instrumentationFactories.Add(
new InstrumentationFactory(instrumentationName, instrumentationVersion, instrumentationFactory));
return this;
}
/// <summary>
/// Run the configured actions to initialize the <see cref="TracerProvider"/>.
/// </summary>
/// <returns><see cref="TracerProvider"/>.</returns>
protected TracerProvider Build()
{
return new TracerProviderSdk(
this.resourceBuilder.Build(),
this.sources,
this.instrumentationFactories,
this.sampler,
this.processors,
this.legacyActivityOperationNames);
}
internal readonly struct InstrumentationFactory
{
public readonly string Name;
public readonly string Version;
public readonly Func<object> Factory;
internal InstrumentationFactory(string name, string version, Func<object> factory)
{
this.Name = name;
this.Version = version;
this.Factory = factory;
}
}
}
}

View File

@ -20,6 +20,9 @@ using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Contains extension methods for the <see cref="TracerProviderBuilder"/> class.
/// </summary>
public static class TracerProviderBuilderExtensions
{
/// <summary>
@ -31,9 +34,9 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetErrorStatusOnException(this TracerProviderBuilder tracerProviderBuilder, bool enabled = true)
{
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderSdk.SetErrorStatusOnException(enabled);
tracerProviderBuilderBase.SetErrorStatusOnException(enabled);
}
return tracerProviderBuilder;
@ -47,9 +50,9 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetSampler(this TracerProviderBuilder tracerProviderBuilder, Sampler sampler)
{
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderSdk.SetSampler(sampler);
tracerProviderBuilderBase.SetSampler(sampler);
}
return tracerProviderBuilder;
@ -64,9 +67,9 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetResourceBuilder(this TracerProviderBuilder tracerProviderBuilder, ResourceBuilder resourceBuilder)
{
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderSdk.SetResourceBuilder(resourceBuilder);
tracerProviderBuilderBase.SetResourceBuilder(resourceBuilder);
}
return tracerProviderBuilder;
@ -80,9 +83,9 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddProcessor(this TracerProviderBuilder tracerProviderBuilder, BaseProcessor<Activity> processor)
{
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderSdk.AddProcessor(processor);
tracerProviderBuilderBase.AddProcessor(processor);
}
return tracerProviderBuilder;
@ -99,19 +102,29 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddLegacySource(this TracerProviderBuilder tracerProviderBuilder, string operationName)
{
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderSdk.AddLegacySource(operationName);
tracerProviderBuilderBase.AddLegacySource(operationName);
}
return tracerProviderBuilder;
}
/// <summary>
/// Run the given actions to initialize the <see cref="TracerProvider"/>.
/// </summary>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns><see cref="TracerProvider"/>.</returns>
public static TracerProvider Build(this TracerProviderBuilder tracerProviderBuilder)
{
if (tracerProviderBuilder is IDeferredTracerProviderBuilder)
{
throw new NotSupportedException("DeferredTracerBuilder requires a ServiceProvider to build.");
}
if (tracerProviderBuilder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
return tracerProviderBuilderSdk.Build();
return tracerProviderBuilderSdk.BuildSdk();
}
return null;

View File

@ -14,204 +14,10 @@
// limitations under the License.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Build TracerProvider with Resource, Sampler, Processors and Instrumentation.
/// </summary>
internal class TracerProviderBuilderSdk : TracerProviderBuilder
internal class TracerProviderBuilderSdk : TracerProviderBuilderBase
{
private readonly List<InstrumentationFactory> instrumentationFactories = new List<InstrumentationFactory>();
private readonly List<BaseProcessor<Activity>> processors = new List<BaseProcessor<Activity>>();
private readonly List<string> sources = new List<string>();
private readonly Dictionary<string, bool> legacyActivityOperationNames = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private ResourceBuilder resourceBuilder = ResourceBuilder.CreateDefault();
private Sampler sampler = new ParentBasedSampler(new AlwaysOnSampler());
internal TracerProviderBuilderSdk()
{
}
/// <summary>
/// Adds an instrumentation to the provider.
/// </summary>
/// <typeparam name="TInstrumentation">Type of instrumentation class.</typeparam>
/// <param name="instrumentationFactory">Function that builds instrumentation.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(
Func<TInstrumentation> instrumentationFactory)
where TInstrumentation : class
{
if (instrumentationFactory == null)
{
throw new ArgumentNullException(nameof(instrumentationFactory));
}
this.instrumentationFactories.Add(
new InstrumentationFactory(
typeof(TInstrumentation).Name,
"semver:" + typeof(TInstrumentation).Assembly.GetName().Version,
instrumentationFactory));
return this;
}
/// <summary>
/// Adds given activitysource names to the list of subscribed sources.
/// </summary>
/// <param name="names">Activity source names.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public override TracerProviderBuilder AddSource(params string[] names)
{
if (names == null)
{
throw new ArgumentNullException(nameof(names));
}
foreach (var name in names)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException($"{nameof(names)} contains null or whitespace string.");
}
// TODO: We need to fix the listening model.
// Today it ignores version.
this.sources.Add(name);
}
return this;
}
/// <summary>
/// Sets whether the status of <see cref="System.Diagnostics.Activity"/>
/// should be set to <c>Status.Error</c> when it ended abnormally due to an unhandled exception.
/// </summary>
/// <param name="enabled">Enabled or not.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetErrorStatusOnException(bool enabled)
{
ExceptionProcessor existingExceptionProcessor = null;
if (this.processors.Count > 0)
{
existingExceptionProcessor = this.processors[0] as ExceptionProcessor;
}
if (enabled)
{
if (existingExceptionProcessor == null)
{
try
{
this.processors.Insert(0, new ExceptionProcessor());
}
catch (Exception ex)
{
throw new NotSupportedException("SetErrorStatusOnException is not supported on this platform.", ex);
}
}
}
else
{
if (existingExceptionProcessor != null)
{
this.processors.RemoveAt(0);
existingExceptionProcessor.Dispose();
}
}
return this;
}
/// <summary>
/// Sets sampler.
/// </summary>
/// <param name="sampler">Sampler instance.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetSampler(Sampler sampler)
{
this.sampler = sampler ?? throw new ArgumentNullException(nameof(sampler));
return this;
}
/// <summary>
/// Sets the <see cref="ResourceBuilder"/> from which the Resource associated with
/// this provider is built from. Overwrites currently set ResourceBuilder.
/// </summary>
/// <param name="resourceBuilder"><see cref="ResourceBuilder"/> from which Resource will be built.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
this.resourceBuilder = resourceBuilder ?? throw new ArgumentNullException(nameof(resourceBuilder));
return this;
}
/// <summary>
/// Adds processor to the provider.
/// </summary>
/// <param name="processor">Activity processor to add.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder AddProcessor(BaseProcessor<Activity> processor)
{
if (processor == null)
{
throw new ArgumentNullException(nameof(processor));
}
this.processors.Add(processor);
return this;
}
/// <summary>
/// Adds a listener for <see cref="Activity"/> objects created with the given operation name to the <see cref="TracerProviderBuilder"/>.
/// </summary>
/// <remarks>
/// This is provided to capture legacy <see cref="Activity"/> objects created without using the <see cref="ActivitySource"/> API.
/// </remarks>
/// <param name="operationName">Operation name of the <see cref="Activity"/> objects to capture.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
internal TracerProviderBuilder AddLegacySource(string operationName)
{
if (string.IsNullOrWhiteSpace(operationName))
{
throw new ArgumentException($"{nameof(operationName)} contains null or whitespace string.");
}
this.legacyActivityOperationNames[operationName] = true;
return this;
}
internal TracerProvider Build()
{
return new TracerProviderSdk(
this.resourceBuilder.Build(),
this.sources,
this.instrumentationFactories,
this.sampler,
this.processors,
this.legacyActivityOperationNames);
}
internal readonly struct InstrumentationFactory
{
public readonly string Name;
public readonly string Version;
public readonly Func<object> Factory;
internal InstrumentationFactory(string name, string version, Func<object> factory)
{
this.Name = name;
this.Version = version;
this.Factory = factory;
}
}
internal TracerProvider BuildSdk() => this.Build();
}
}

View File

@ -40,7 +40,7 @@ namespace OpenTelemetry.Trace
internal TracerProviderSdk(
Resource resource,
IEnumerable<string> sources,
IEnumerable<TracerProviderBuilderSdk.InstrumentationFactory> instrumentationFactories,
IEnumerable<TracerProviderBuilderBase.InstrumentationFactory> instrumentationFactories,
Sampler sampler,
List<BaseProcessor<Activity>> processors,
Dictionary<string, bool> legacyActivityOperationNames)

View File

@ -87,9 +87,10 @@ namespace OpenTelemetry.Extensions.Hosting
var services = new ServiceCollection();
services.AddSingleton(testInstrumentation);
services.AddOpenTelemetryTracing((provider, builder) =>
services.AddOpenTelemetryTracing(builder =>
{
builder.AddInstrumentation(() => provider.GetRequiredService<TestInstrumentation>());
builder.Configure(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
});
var serviceProvider = services.BuildServiceProvider();
@ -108,12 +109,13 @@ namespace OpenTelemetry.Extensions.Hosting
public void AddOpenTelemetryTracerProvider_BadArgs_NullServiceCollection()
{
ServiceCollection services = null;
Assert.Throws<ArgumentNullException>(() => services.AddOpenTelemetryTracing());
Assert.Throws<ArgumentNullException>(() => services.AddOpenTelemetryTracing(null));
Assert.Throws<ArgumentNullException>(() =>
services.AddOpenTelemetryTracing((provider, builder) =>
{
builder.AddInstrumentation(() => provider.GetRequiredService<TestInstrumentation>());
}));
services.AddOpenTelemetryTracing(builder =>
{
builder.Configure(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
}));
}
internal class TestInstrumentation : IDisposable