Skip to content

Commit

Permalink
[Metrics] Improve dependency injection support in meter provider buil…
Browse files Browse the repository at this point in the history
…d-up using SDK (#3646)

* Mirror TracerProviderBuilder dependency injection API onto MeterProviderBuilder.

* Nullable annotations.

* Warning cleanup.

* Warning cleanup.

* Public API updates.

* Warning cleanup.

* Public API updates.

* CHANGELOG updates.

* Warning cleanup.

* Fixes.

* Tests.
  • Loading branch information
CodeBlanch authored Sep 12, 2022
1 parent cea14d3 commit 6ff512c
Show file tree
Hide file tree
Showing 29 changed files with 1,268 additions and 582 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder> configure) -> 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 OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader<T>(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.IServiceProvider serviceProvider) -> OpenTelemetry.Metrics.MeterProvider
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Configure(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<System.IServiceProvider, OpenTelemetry.Metrics.MeterProviderBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.GetServices(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Configure(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
Expand Down
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Extensions.Hosting/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
`TracerProvider` has been moved into the SDK.
([#3533](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3533))

* Dependency injection support when configuring
`MeterProvider` has been moved into the SDK.
([#3646](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3646))

## 1.0.0-rc9.6

Released 2022-Aug-18
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,6 @@ namespace OpenTelemetry.Metrics
/// </summary>
public static class MeterProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(this MeterProviderBuilder meterProviderBuilder)
where T : class
{
if (meterProviderBuilder is MeterProviderBuilderHosting meterProviderBuilderHosting)
{
meterProviderBuilderHosting.Configure((sp, builder) => builder
.AddInstrumentation(() => sp.GetRequiredService<T>()));
}

return meterProviderBuilder;
}

/// <summary>
/// Adds a reader to the provider.
/// </summary>
/// <typeparam name="T">Reader type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddReader<T>(this MeterProviderBuilder meterProviderBuilder)
where T : MetricReader
{
if (meterProviderBuilder is MeterProviderBuilderHosting meterProviderBuilderHosting)
{
meterProviderBuilderHosting.Configure((sp, builder) => builder
.AddReader(sp.GetRequiredService<T>()));
}

return meterProviderBuilder;
}

/// <summary>
/// Register a callback action to configure the <see
/// cref="MeterProviderBuilder"/> once the application <see
Expand All @@ -68,14 +32,10 @@ public static MeterProviderBuilder AddReader<T>(this MeterProviderBuilder meterP
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
[Obsolete("Call ConfigureBuilder instead this method will be removed in a future version.")]
public static MeterProviderBuilder Configure(this MeterProviderBuilder meterProviderBuilder, Action<IServiceProvider, MeterProviderBuilder> configure)
{
if (meterProviderBuilder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder)
{
deferredMeterProviderBuilder.Configure(configure);
}

return meterProviderBuilder;
return meterProviderBuilder.ConfigureBuilder(configure);
}

/// <summary>
Expand All @@ -85,35 +45,12 @@ public static MeterProviderBuilder Configure(this MeterProviderBuilder meterProv
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <returns><see cref="IServiceCollection"/> or <see langword="null"/>
/// if services are unavailable.</returns>
[Obsolete("Call ConfigureServices instead this method will be removed in a future version.")]
public static IServiceCollection GetServices(this MeterProviderBuilder meterProviderBuilder)
{
if (meterProviderBuilder is MeterProviderBuilderHosting meterProviderBuilderHosting)
{
return meterProviderBuilderHosting.Services;
}

return null;
}

/// <summary>
/// Run the configured actions to initialize the <see cref="MeterProvider"/>.
/// </summary>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <returns><see cref="MeterProvider"/>.</returns>
public static MeterProvider Build(this MeterProviderBuilder meterProviderBuilder, IServiceProvider serviceProvider)
{
if (meterProviderBuilder is MeterProviderBuilderHosting meterProviderBuilderHosting)
{
return meterProviderBuilderHosting.Build(serviceProvider);
}

if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
return meterProviderBuilderBase.Build();
}

return null;
IServiceCollection services = null;
meterProviderBuilder.ConfigureServices(s => services = s);
return services;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@
// </copyright>

using System;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Extensions.Hosting.Implementation;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
Expand All @@ -27,7 +25,8 @@
namespace Microsoft.Extensions.DependencyInjection
{
/// <summary>
/// Extension methods for setting up OpenTelemetry services in an <see cref="IServiceCollection" />.
/// Extension methods for setting up OpenTelemetry services in an <see
/// cref="IServiceCollection" />.
/// </summary>
public static class OpenTelemetryServicesExtensions
{
Expand All @@ -37,24 +36,29 @@ public static class OpenTelemetryServicesExtensions
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Note: This is safe to be called multiple times and by library authors.
/// Only a single <see cref="TracerProvider"/> will be created for a given
/// <see cref="IServiceCollection"/>.
/// Note: This is safe to be called multiple times and by library
/// authors. Only a single <see cref="TracerProvider"/> will be created
/// for a given <see cref="IServiceCollection"/>.
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining calls.</returns>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services)
=> AddOpenTelemetryTracing(services, (b) => { });
=> AddOpenTelemetryTracing(services, b => { });

/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start tracing services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc cref="AddOpenTelemetryTracing(IServiceCollection)" path="/remarks"/></remarks>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryTracing(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining calls.</returns>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services, Action<TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Expand All @@ -67,54 +71,41 @@ public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection
}

/// <summary>
/// Adds OpenTelemetry MeterProvider to the specified <see cref="IServiceCollection" />.
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
/// <remarks>
/// Note: This is safe to be called multiple times and by library
/// authors. Only a single <see cref="MeterProvider"/> will be created
/// for a given <see cref="IServiceCollection"/>.
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services)
{
return services.AddOpenTelemetryMetrics(builder => { });
}
=> AddOpenTelemetryMetrics(services, b => { });

/// <summary>
/// Adds OpenTelemetry MeterProvider to the specified <see cref="IServiceCollection" />.
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="configure">Callback action to configure the <see cref="MeterProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryMetrics(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services, Action<MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);

var builder = new MeterProviderBuilderHosting(services);
configure(builder);
return services.AddOpenTelemetryMetrics(sp => builder.Build(sp));
}

/// <summary>
/// Adds OpenTelemetry MeterProvider to the specified <see cref="IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="createMeterProvider">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 AddOpenTelemetryMetrics(this IServiceCollection services, Func<IServiceProvider, MeterProvider> createMeterProvider)
{
Debug.Assert(services != null, $"{nameof(services)} must not be null");
Debug.Assert(createMeterProvider != null, $"{nameof(createMeterProvider)} must not be null");
Guard.ThrowIfNull(services);

// Accessing Sdk class is just to trigger its static ctor,
// which sets default Propagators and default Activity Id format
_ = Sdk.SuppressInstrumentation;
services.ConfigureOpenTelemetryMetrics(configure);

try
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
return services.AddSingleton(s => createMeterProvider(s));
}
catch (Exception ex)
{
HostingExtensionsEventSource.Log.FailedInitialize(ex);
}
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());

return services;
}
Expand Down
Loading

0 comments on commit 6ff512c

Please sign in to comment.