Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="MeterProviderBuilderServiceCollectionHelper.cs" company="OpenTelemetry Authors">
// <copyright file="ProviderBuilderServiceCollectionCallbackHelper.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -20,13 +20,14 @@
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;

namespace OpenTelemetry.Metrics;
namespace OpenTelemetry;

internal static class MeterProviderBuilderServiceCollectionHelper
internal static class ProviderBuilderServiceCollectionCallbackHelper<TBuilder, TProvider, TState>
where TState : ProviderBuilderState<TBuilder, TProvider>
{
internal static IServiceCollection RegisterConfigureBuilderCallback(
public static IServiceCollection RegisterConfigureBuilderCallback(
IServiceCollection services,
Action<IServiceProvider, MeterProviderBuilder> configure)
Action<IServiceProvider, TBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");

Expand All @@ -35,42 +36,43 @@ internal static IServiceCollection RegisterConfigureBuilderCallback(
(sp, state) => configure!(sp, state.Builder));
}

internal static IServiceCollection RegisterConfigureStateCallback(
public static IServiceCollection RegisterConfigureStateCallback(
IServiceCollection services,
Action<IServiceProvider, MeterProviderBuilderState> configure)
Action<IServiceProvider, TState> configure)
{
Debug.Assert(services != null, "services was null");
Debug.Assert(configure != null, "configure was null");

return services!.AddSingleton(new ConfigureMeterProviderBuilderStateCallbackRegistration(configure!));
return services!.AddSingleton(
new ConfigureProviderBuilderStateCallbackRegistration(configure!));
}

internal static void InvokeRegisteredConfigureStateCallbacks(
public static void InvokeRegisteredConfigureStateCallbacks(
IServiceProvider serviceProvider,
MeterProviderBuilderState state)
TState state)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
Debug.Assert(state != null, "state was null");

var callbackRegistrations = serviceProvider!.GetServices<ConfigureMeterProviderBuilderStateCallbackRegistration>();
var callbackRegistrations = serviceProvider!.GetServices<ConfigureProviderBuilderStateCallbackRegistration>();

foreach (var callbackRegistration in callbackRegistrations)
{
callbackRegistration.Configure(serviceProvider!, state!);
}
}

private sealed class ConfigureMeterProviderBuilderStateCallbackRegistration
private sealed class ConfigureProviderBuilderStateCallbackRegistration
{
private readonly Action<IServiceProvider, MeterProviderBuilderState> configure;
private readonly Action<IServiceProvider, TState> configure;

public ConfigureMeterProviderBuilderStateCallbackRegistration(
Action<IServiceProvider, MeterProviderBuilderState> configure)
public ConfigureProviderBuilderStateCallbackRegistration(
Action<IServiceProvider, TState> configure)
{
this.configure = configure;
}

public void Configure(IServiceProvider serviceProvider, MeterProviderBuilderState state)
public void Configure(IServiceProvider serviceProvider, TState state)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
Debug.Assert(state != null, "state was null");
Expand Down
107 changes: 107 additions & 0 deletions src/OpenTelemetry/Internal/Builder/ProviderBuilderState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// <copyright file="ProviderBuilderState.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>

#nullable enable

using System;
using System.Collections.Generic;
using System.Diagnostics;
using OpenTelemetry.Resources;

namespace OpenTelemetry;

internal abstract class ProviderBuilderState<TBuilder, TProvider>
{
private TProvider? provider;

protected ProviderBuilderState(IServiceProvider serviceProvider)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");

this.ServiceProvider = serviceProvider!;
}

public IServiceProvider ServiceProvider { get; }

public abstract TBuilder Builder { get; }

public TProvider Provider
{
get => this.provider ?? throw new InvalidOperationException("Provider has not been set on state.");
}

public List<InstrumentationRegistration> Instrumentation { get; } = new();

public ResourceBuilder? ResourceBuilder { get; protected set; }

public void RegisterProvider(string providerTypeName, TProvider provider)
{
Debug.Assert(provider != null, "provider was null");

if (this.provider != null)
{
throw new NotSupportedException($"{providerTypeName} cannot be accessed while build is executing.");
}

this.provider = provider;
}

public void AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
object instrumentation)
{
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace");
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace");
Debug.Assert(instrumentation != null, "instrumentation was null");

this.Instrumentation.Add(
new InstrumentationRegistration(
instrumentationName,
instrumentationVersion,
instrumentation!));
}

public void ConfigureResource(Action<ResourceBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");

var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault();

configure!(resourceBuilder);
}

public void SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Debug.Assert(resourceBuilder != null, "resourceBuilder was null");

this.ResourceBuilder = resourceBuilder;
}

internal readonly struct InstrumentationRegistration
{
public readonly string Name;
public readonly string Version;
public readonly object Instance;

internal InstrumentationRegistration(string name, string version, object instance)
{
this.Name = name;
this.Version = version;
this.Instance = instance;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Metrics.MeterProviderBuilderSdk,
OpenTelemetry.Metrics.MeterProviderSdk,
OpenTelemetry.Metrics.MeterProviderBuilderState>;

namespace OpenTelemetry.Metrics
{
/// <summary>
Expand Down Expand Up @@ -103,7 +108,7 @@ MeterProviderBuilder IDeferredMeterProviderBuilder.Configure(
else
{
this.ConfigureServices(services
=> MeterProviderBuilderServiceCollectionHelper.RegisterConfigureBuilderCallback(services, configure));
=> CallbackHelper.RegisterConfigureBuilderCallback(services, configure));
}

return this;
Expand Down Expand Up @@ -292,7 +297,7 @@ private MeterProviderBuilder ConfigureState(Action<IServiceProvider, MeterProvid
}
else
{
this.ConfigureServices(services => MeterProviderBuilderServiceCollectionHelper.RegisterConfigureStateCallback(services, configure!));
this.ConfigureServices(services => CallbackHelper.RegisterConfigureStateCallback(services, configure!));
}

return this;
Expand Down
85 changes: 14 additions & 71 deletions src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,63 +21,36 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

namespace OpenTelemetry.Metrics
{
/// <summary>
/// Stores state used to build a <see cref="MeterProvider"/>.
/// </summary>
internal sealed class MeterProviderBuilderState
internal sealed class MeterProviderBuilderState : ProviderBuilderState<MeterProviderBuilderSdk, MeterProviderSdk>
{
internal const int MaxMetricsDefault = 1000;
internal const int MaxMetricPointsPerMetricDefault = 2000;
internal readonly IServiceProvider ServiceProvider;
internal readonly List<InstrumentationRegistration> Instrumentation = new();
internal readonly List<MetricReader> Readers = new();
internal readonly List<string> MeterSources = new();
internal readonly List<Func<Instrument, MetricStreamConfiguration?>> ViewConfigs = new();
internal ResourceBuilder? ResourceBuilder;
internal int MaxMetricStreams = MaxMetricsDefault;
internal int MaxMetricPointsPerMetricStream = MaxMetricPointsPerMetricDefault;

private bool hasEnteredBuildPhase;
public const int MaxMetricsDefault = 1000;
public const int MaxMetricPointsPerMetricDefault = 2000;

private MeterProviderBuilderSdk? builder;

public MeterProviderBuilderState(IServiceProvider serviceProvider)
: base(serviceProvider)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");

this.ServiceProvider = serviceProvider!;
}

public MeterProviderBuilderSdk Builder => this.builder ??= new MeterProviderBuilderSdk(this);
public override MeterProviderBuilderSdk Builder
=> this.builder ??= new MeterProviderBuilderSdk(this);

public void CheckForCircularBuild()
{
if (this.hasEnteredBuildPhase)
{
throw new NotSupportedException("MeterProvider cannot be accessed while build is executing.");
}
public List<MetricReader> Readers { get; } = new();

this.hasEnteredBuildPhase = true;
}
public List<string> MeterSources { get; } = new();

public void AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
object instrumentation)
{
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace");
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace");
Debug.Assert(instrumentation != null, "instrumentation was null");

this.Instrumentation.Add(
new InstrumentationRegistration(
instrumentationName,
instrumentationVersion,
instrumentation!));
}
public List<Func<Instrument, MetricStreamConfiguration?>> ViewConfigs { get; } = new();

public int MaxMetricStreams { get; set; } = MaxMetricsDefault;

public int MaxMetricPointsPerMetricStream { get; set; } = MaxMetricPointsPerMetricDefault;

public void AddMeter(params string[] names)
{
Expand All @@ -104,35 +77,5 @@ public void AddView(Func<Instrument, MetricStreamConfiguration?> viewConfig)

this.ViewConfigs.Add(viewConfig!);
}

public void ConfigureResource(Action<ResourceBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");

var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault();

configure!(resourceBuilder);
}

public void SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Debug.Assert(resourceBuilder != null, "resourceBuilder was null");

this.ResourceBuilder = resourceBuilder;
}

internal readonly struct InstrumentationRegistration
{
public readonly string Name;
public readonly string Version;
public readonly object Instance;

internal InstrumentationRegistration(string name, string version, object instance)
{
this.Name = name;
this.Version = version;
this.Instance = instance;
}
}
}
}
9 changes: 7 additions & 2 deletions src/OpenTelemetry/Metrics/MeterProviderSdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Metrics.MeterProviderBuilderSdk,
OpenTelemetry.Metrics.MeterProviderSdk,
OpenTelemetry.Metrics.MeterProviderBuilderState>;

namespace OpenTelemetry.Metrics
{
internal sealed class MeterProviderSdk : MeterProvider
Expand All @@ -49,7 +54,7 @@ internal MeterProviderSdk(
Debug.Assert(serviceProvider != null, "serviceProvider was null");

var state = serviceProvider!.GetRequiredService<MeterProviderBuilderState>();
state.CheckForCircularBuild();
state.RegisterProvider(nameof(MeterProvider), this);

this.ServiceProvider = serviceProvider!;

Expand All @@ -61,7 +66,7 @@ internal MeterProviderSdk(

OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent("Building MeterProvider.");

MeterProviderBuilderServiceCollectionHelper.InvokeRegisteredConfigureStateCallbacks(
CallbackHelper.InvokeRegisteredConfigureStateCallbacks(
serviceProvider!,
state);

Expand Down
10 changes: 8 additions & 2 deletions src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;

using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Trace.TracerProviderBuilderSdk,
OpenTelemetry.Trace.TracerProviderSdk,
OpenTelemetry.Trace.TracerProviderBuilderState>;

namespace OpenTelemetry.Trace
{
/// <summary>
Expand Down Expand Up @@ -112,7 +117,7 @@ TracerProviderBuilder IDeferredTracerProviderBuilder.Configure(
else
{
this.ConfigureServices(services
=> TracerProviderBuilderServiceCollectionHelper.RegisterConfigureBuilderCallback(services, configure));
=> CallbackHelper.RegisterConfigureBuilderCallback(services, configure));
}

return this;
Expand Down Expand Up @@ -327,7 +332,8 @@ private TracerProviderBuilder ConfigureState(Action<IServiceProvider, TracerProv
}
else
{
this.ConfigureServices(services => TracerProviderBuilderServiceCollectionHelper.RegisterConfigureStateCallback(services, configure!));
this.ConfigureServices(services =>
CallbackHelper.RegisterConfigureStateCallback(services, configure!));
}

return this;
Expand Down
Loading