diff --git a/src/OpenTelemetry.Api/Metrics/MeterProvider.cs b/src/OpenTelemetry.Api/Metrics/MeterProvider.cs index 80859e56cb5..bff2d0a271c 100644 --- a/src/OpenTelemetry.Api/Metrics/MeterProvider.cs +++ b/src/OpenTelemetry.Api/Metrics/MeterProvider.cs @@ -27,5 +27,10 @@ public class MeterProvider : BaseProvider protected MeterProvider() { } + + /// + /// Gets the default . + /// + internal static MeterProvider Default { get; } = new MeterProvider(); } } diff --git a/src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs b/src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs index aa5a5ace8e5..39f563bc8a0 100644 --- a/src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs +++ b/src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs @@ -32,6 +32,10 @@ public abstract class MeterProviderBuilderBase : MeterProviderBuilder { internal const int MaxMetricsDefault = 1000; internal const int MaxMetricPointsPerMetricDefault = 2000; + + // Builds noop MeterProvider when this flag is set. + // This flag is controlled through reflection. + private static bool disableMeterProviderBuilder = false; private readonly List instrumentationFactories = new(); private readonly List meterSources = new(); private readonly List> viewConfigs = new(); @@ -142,7 +146,9 @@ internal MeterProviderBuilder SetMaxMetricPointsPerMetricStream(int maxMetricPoi /// . protected MeterProvider Build() { - return new MeterProviderSdk( + if (!disableMeterProviderBuilder) + { + return new MeterProviderSdk( this.resourceBuilder.Build(), this.meterSources, this.instrumentationFactories, @@ -150,6 +156,11 @@ protected MeterProvider Build() this.maxMetricStreams, this.maxMetricPointsPerMetricStream, this.MetricReaders.ToArray()); + } + else + { + return MeterProvider.Default; + } } internal readonly struct InstrumentationFactory diff --git a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs index 0fd85d2a37d..f9a8e21f39e 100644 --- a/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs +++ b/src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs @@ -33,6 +33,10 @@ public abstract class TracerProviderBuilderBase : TracerProviderBuilder, IDeferr { internal readonly TracerProviderBuilderState? State; + // Builds noop TracerProvider when this flag is set. + // This flag is controlled through reflection. + private static bool disableTracerProviderBuilder = false; + private readonly bool ownsServices; private IServiceCollection? services; @@ -264,7 +268,14 @@ protected TracerProvider Build() var serviceProvider = services.BuildServiceProvider(); - return new TracerProviderSdk(serviceProvider, ownsServiceProvider: true); + if (!disableTracerProviderBuilder) + { + return new TracerProviderSdk(serviceProvider, ownsServiceProvider: true); + } + else + { + return TracerProvider.Default; + } } private static BaseProcessor BuildExportProcessor( diff --git a/test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs b/test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs index aa034bdd406..4faee30fcc3 100644 --- a/test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs @@ -15,6 +15,7 @@ // using System.Collections.Generic; +using System.Reflection; using OpenTelemetry.Exporter; using Xunit; @@ -34,6 +35,21 @@ public void MeterProviderFindExporterTest() Assert.False(meterProvider.TryFindExporter(out MyExporter myExporter)); } + [Fact] + public void NoopMeterProviderWithDisabledMeterProviderBuilderFlag() + { + var buildMeterProviderBuilderField = typeof(MeterProviderBuilderBase).GetField("disableMeterProviderBuilder", BindingFlags.Static | BindingFlags.NonPublic); + buildMeterProviderBuilderField.SetValue(null, true); + + var exportedItems = new List(); + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddInMemoryExporter(exportedItems) + .Build(); + + Assert.Same(meterProvider, MeterProvider.Default); + buildMeterProviderBuilderField.SetValue(null, false); + } + private class MyExporter : BaseExporter { public override ExportResult Export(in Batch batch) diff --git a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs index 73773b44e63..98abf734b55 100644 --- a/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs +++ b/test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs @@ -18,6 +18,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection; using OpenTelemetry.Instrumentation; using OpenTelemetry.Resources; using OpenTelemetry.Tests; @@ -1209,6 +1210,21 @@ public void SdkSamplesAndProcessesLegacySourceWhenAddLegacySourceIsCalledWithWil Assert.Contains(nonLegacyActivity.OperationName, onStopProcessedActivities); // Processor.OnEnd is called since we added a legacy OperationName } + [Fact] + public void NoopTracerProviderWithDisabledTracerProviderBuilderFlag() + { + var buildTracerProviderBuilderField = typeof(TracerProviderBuilderBase).GetField("disableTracerProviderBuilder", BindingFlags.Static | BindingFlags.NonPublic); + buildTracerProviderBuilderField.SetValue(null, true); + + using var source1 = new ActivitySource($"{Utils.GetCurrentMethodName()}.1"); + var builder = Sdk.CreateTracerProviderBuilder(); + builder.AddSource(source1.Name); + using var provider = builder.Build(); + + Assert.Same(provider, TracerProvider.Default); + buildTracerProviderBuilderField.SetValue(null, false); + } + public void Dispose() { GC.SuppressFinalize(this);