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

Disable flag for TracerProvider / MeterProvider #3583

Closed
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions src/OpenTelemetry.Api/Metrics/MeterProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@ public class MeterProvider : BaseProvider
protected MeterProvider()
{
}

/// <summary>
/// Gets the default <see cref="MeterProvider"/>.
/// </summary>
internal static MeterProvider Default { get; } = new MeterProvider();
}
}
13 changes: 12 additions & 1 deletion src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a scenario where metrics/traces need to be disabled independently?
What is the contract and how to maintain the contract?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe consider something similar to

// An integer value which controls whether instrumentation should be suppressed (disabled).
// * 0: instrumentation is not suppressed
// * [int.MinValue, -1]: instrumentation is always suppressed
// * [1, int.MaxValue]: instrumentation is suppressed in a reference-counting mode
private static readonly RuntimeContextSlot<int> Slot = RuntimeContext.RegisterSlot<int>("otel.suppress_instrumentation");
.

private readonly List<InstrumentationFactory> instrumentationFactories = new();
private readonly List<string> meterSources = new();
private readonly List<Func<Instrument, MetricStreamConfiguration>> viewConfigs = new();
Expand Down Expand Up @@ -142,14 +146,21 @@ internal MeterProviderBuilder SetMaxMetricPointsPerMetricStream(int maxMetricPoi
/// <returns><see cref="MeterProvider"/>.</returns>
protected MeterProvider Build()
{
return new MeterProviderSdk(
if (!disableMeterProviderBuilder)
{
return new MeterProviderSdk(
this.resourceBuilder.Build(),
this.meterSources,
this.instrumentationFactories,
this.viewConfigs,
this.maxMetricStreams,
this.maxMetricPointsPerMetricStream,
this.MetricReaders.ToArray());
}
else
{
return MeterProvider.Default;
}
}

internal readonly struct InstrumentationFactory
Expand Down
13 changes: 12 additions & 1 deletion src/OpenTelemetry/Trace/Builder/TracerProviderBuilderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<Activity> BuildExportProcessor(
Expand Down
16 changes: 16 additions & 0 deletions test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// </copyright>

using System.Collections.Generic;
using System.Reflection;
using OpenTelemetry.Exporter;
using Xunit;

Expand All @@ -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<Metric>();
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddInMemoryExporter(exportedItems)
.Build();

Assert.Same(meterProvider, MeterProvider.Default);
buildMeterProviderBuilderField.SetValue(null, false);
}

private class MyExporter : BaseExporter<Metric>
{
public override ExportResult Export(in Batch<Metric> batch)
Expand Down
16 changes: 16 additions & 0 deletions test/OpenTelemetry.Tests/Trace/TracerProviderSdkTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down