Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency injection support #1889

Merged
merged 19 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"));
CodeBlanch marked this conversation as resolved.
Show resolved Hide resolved
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
4 changes: 0 additions & 4 deletions src/OpenTelemetry.Api/Trace/TracerProviderBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ namespace OpenTelemetry.Trace
/// </summary>
public abstract class TracerProviderBuilder
{
internal TracerProviderBuilder()
{
}

/// <summary>
/// Adds an instrumentation to the provider.
/// </summary>
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,11 @@
Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions
OpenTelemetry.Trace.TracerProviderBuilderExtensions
OpenTelemetry.Trace.TracerProviderBuilderHosting
OpenTelemetry.Trace.TracerProviderBuilderHosting.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection
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
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -35,8 +34,7 @@ public static class OpenTelemetryServicesExtensions
/// <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>
Expand All @@ -52,63 +50,9 @@ public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection
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>
Expand All @@ -131,8 +75,8 @@ private static IServiceCollection AddOpenTelemetryTracing(this IServiceCollectio

try
{
services.AddSingleton(s => createTracerProvider(s));
AddOpenTelemetryTracingInternal(services);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
return services.AddSingleton(s => createTracerProvider(s));
}
catch (Exception ex)
{
Expand All @@ -141,10 +85,5 @@ private static IServiceCollection AddOpenTelemetryTracing(this IServiceCollectio

return services;
}

private static void AddOpenTelemetryTracingInternal(IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Loading