Skip to content

Commit

Permalink
Dependency injection support (#1889)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeBlanch authored Mar 26, 2021
1 parent 5f1acbf commit 0208fd6
Show file tree
Hide file tree
Showing 26 changed files with 710 additions and 312 deletions.
17 changes: 7 additions & 10 deletions examples/AspNetCore/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

Expand Down Expand Up @@ -63,20 +63,17 @@ public void ConfigureServices(IServiceCollection services)
.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.
Expand Down
4 changes: 2 additions & 2 deletions examples/AspNetCore/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"UseExporter": "console",
"Jaeger": {
"ServiceName": "jaeger-test",
"Host": "localhost",
"Port": 6831
"AgentHost": "localhost",
"AgentPort": 6831
},
"Zipkin": {
"ServiceName": "zipkin-test",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OpenTelemetry.Trace.TracerProviderBuilder.TracerProviderBuilder() -> void
7 changes: 5 additions & 2 deletions src/OpenTelemetry.Api/Trace/TracerProviderBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,35 @@ public static TracerProviderBuilder AddJaegerExporter(this TracerProviderBuilder
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);
});
}

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 (exporterOptions.ExportProcessorType == ExportProcessorType.Simple)
if (options.ExportProcessorType == ExportProcessorType.Simple)
{
return builder.AddProcessor(new SimpleActivityExportProcessor(jaegerExporter));
}
else
{
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));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,35 @@ public static TracerProviderBuilder AddZipkinExporter(this TracerProviderBuilder
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);
});
}

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 (exporterOptions.ExportProcessorType == ExportProcessorType.Simple)
if (options.ExportProcessorType == ExportProcessorType.Simple)
{
return builder.AddProcessor(new SimpleActivityExportProcessor(zipkinExporter));
}
else
{
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));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
Loading

0 comments on commit 0208fd6

Please sign in to comment.