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

Adding MeterProviderBuilder #1149

Merged
merged 2 commits into from Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 5 additions & 6 deletions examples/Console/TestPrometheusExporter.cs
Expand Up @@ -58,12 +58,11 @@ internal static async Task<object> RunAsync(int port, int pushIntervalInSecs, in
// Application which decides to enable OpenTelemetry metrics
// would setup a MeterProvider and make it default.
// All meters from this factory will be configured with the common processing pipeline.
MeterProvider.SetDefault(Sdk.CreateMeterProvider(mb =>
{
mb.SetMetricProcessor(processor);
mb.SetMetricExporter(promExporter);
mb.SetMetricPushInterval(TimeSpan.FromSeconds(pushIntervalInSecs));
}));
MeterProvider.SetDefault(Sdk.CreateMeterProviderBuilder()
.SetProcessor(processor)
Copy link
Member

Choose a reason for hiding this comment

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

@cijothomas do we want this to be Set or Add?

Copy link
Member

Choose a reason for hiding this comment

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

If we allow multiple Processor, then Add. Else Set.
This decision is not clear, so I'll leave it as is until we actually implement Metric Sdk.
(This PR just make consistent pattern as Tracer only - Sdk.CreateMeterBuilder().accumulate_stuff_for_building().Build pattern)

Copy link
Member

Choose a reason for hiding this comment

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

Roger that, thanks.

.SetExporter(promExporter)
.SetPushInterval(TimeSpan.FromSeconds(pushIntervalInSecs))
.Build());

// The following shows how libraries would obtain a MeterProvider.
// MeterProvider is the entry point, which provides Meter.
Expand Down
7 changes: 5 additions & 2 deletions src/OpenTelemetry/CHANGELOG.md
Expand Up @@ -2,8 +2,6 @@

## Unreleased

* Modified Sampler implementation to match the spec
([#1037](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1037))
* Changed `ActivityProcessor` to implement `IDisposable`
([#975](https://github.com/open-telemetry/opentelemetry-dotnet/pull/975))
* Samplers now get the actual TraceId of the Activity to be created.
Expand All @@ -23,6 +21,8 @@
[#1035](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1035))
* Changed `AddActivitySource` to `AddSource` with params support
([#1036](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1036))
* Modified Sampler implementation to match the spec
([#1037](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1037))
* Refactored simple export and batch export APIs
([#1078](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1078)
[#1081](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1081)
Expand All @@ -34,6 +34,9 @@
[#1127](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1127)
[#1129](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1129)
[#1135](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1135))
* Changed `MeterProviderBuilder` and `MeterProviderSdk` design to simply the
flow and usage
([#1149](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1149))
* Renamed `ParentOrElseSampler` to `ParentBasedSampler`
([#1173](https://github.com/open-telemetry/opentelemetry-dotnet/pull/1173))
* Renamed `ProbabilitySampler` to `TraceIdRatioBasedSampler`
Expand Down
67 changes: 0 additions & 67 deletions src/OpenTelemetry/Metrics/MeterBuilder.cs

This file was deleted.

90 changes: 90 additions & 0 deletions src/OpenTelemetry/Metrics/MeterProviderBuilder.cs
@@ -0,0 +1,90 @@
// <copyright file="MeterProviderBuilder.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.Collections.Generic;
using System.Threading;
using OpenTelemetry.Metrics.Export;
using static OpenTelemetry.Metrics.MeterProviderSdk;

namespace OpenTelemetry.Metrics
{
/// <summary>
/// Build MeterProvider with Exporter, Processor and PushInterval.
/// </summary>
public class MeterProviderBuilder
{
private static readonly TimeSpan DefaultPushInterval = TimeSpan.FromSeconds(60);
private MetricProcessor metricProcessor;
private MetricExporter metricExporter;
private TimeSpan metricPushInterval;

internal MeterProviderBuilder()
{
this.metricExporter = new NoopMetricExporter();
this.metricProcessor = new NoopMetricProcessor();
this.metricPushInterval = DefaultPushInterval;
}

/// <summary>
/// Sets processor.
/// </summary>
/// <param name="processor">Processor instance.</param>
/// <returns>Returns <see cref="MeterProviderBuilder"/> for chaining.</returns>
public MeterProviderBuilder SetProcessor(MetricProcessor processor)
{
this.metricProcessor = processor ?? new NoopMetricProcessor();
return this;
}

/// <summary>
/// Sets exporter.
/// </summary>
/// <param name="exporter">Exporter instance.</param>
/// <returns>Returns <see cref="MeterProviderBuilder"/> for chaining.</returns>
public MeterProviderBuilder SetExporter(MetricExporter exporter)
{
this.metricExporter = exporter ?? new NoopMetricExporter();
return this;
}

/// <summary>
/// Sets push interval.
/// </summary>
/// <param name="pushInterval">Push interval.</param>
/// <returns>Returns <see cref="MeterProviderBuilder"/> for chaining.</returns>
public MeterProviderBuilder SetPushInterval(TimeSpan pushInterval)
{
this.metricPushInterval = pushInterval == default ? DefaultPushInterval : pushInterval;
return this;
}

public MeterProvider Build()
{
var cancellationTokenSource = new CancellationTokenSource();
var meterRegistry = new Dictionary<MeterRegistryKey, MeterSdk>();

var controller = new PushMetricController(
meterRegistry,
this.metricProcessor,
this.metricExporter,
this.metricPushInterval,
cancellationTokenSource);

return new MeterProviderSdk(this.metricProcessor, meterRegistry, controller, cancellationTokenSource);
}
}
}
40 changes: 4 additions & 36 deletions src/OpenTelemetry/Sdk.cs
Expand Up @@ -14,13 +14,8 @@
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Threading;
using OpenTelemetry.Metrics;
using OpenTelemetry.Metrics.Export;
using OpenTelemetry.Trace;
using static OpenTelemetry.Metrics.MeterProviderSdk;

namespace OpenTelemetry
{
Expand All @@ -29,45 +24,18 @@ namespace OpenTelemetry
/// </summary>
public static class Sdk
{
private static readonly TimeSpan DefaultPushInterval = TimeSpan.FromSeconds(60);

/// <summary>
/// Gets a value indicating whether instrumentation is suppressed (disabled).
/// </summary>
public static bool SuppressInstrumentation => SuppressInstrumentationScope.IsSuppressed;

/// <summary>
/// Creates MeterProvider with the configuration provided.
/// Configuration involves MetricProcessor, Exporter and push internval.
/// Creates MeterProviderBuilder which should be used to build MeterProvider.
/// </summary>
/// <param name="configure">Action to configure MeterBuilder.</param>
/// <returns>MeterProvider instance, which must be disposed upon shutdown.</returns>
public static MeterProvider CreateMeterProvider(Action<MeterBuilder> configure)
/// <returns>MeterProviderBuilder instance, which should be used to build MeterProvider.</returns>
public static MeterProviderBuilder CreateMeterProviderBuilder()
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}

var meterBuilder = new MeterBuilder();
configure(meterBuilder);

var metricProcessor = meterBuilder.MetricProcessor ?? new NoopMetricProcessor();
var metricExporter = meterBuilder.MetricExporter ?? new NoopMetricExporter();
var cancellationTokenSource = new CancellationTokenSource();
var meterRegistry = new Dictionary<MeterRegistryKey, MeterSdk>();

// We only have PushMetricController now with only configurable thing being the push interval
var controller = new PushMetricController(
meterRegistry,
metricProcessor,
metricExporter,
meterBuilder.MetricPushInterval == default ? DefaultPushInterval : meterBuilder.MetricPushInterval,
cancellationTokenSource);

var meterProviderSdk = new MeterProviderSdk(metricProcessor, meterRegistry, controller, cancellationTokenSource);

return meterProviderSdk;
return new MeterProviderBuilder();
}

/// <summary>
Expand Down
Expand Up @@ -113,12 +113,12 @@ public async Task E2ETestMiddleware()

private static void CollectMetrics(UngroupedBatcher simpleProcessor, MetricExporter exporter)
{
var meter = Sdk.CreateMeterProvider(mb =>
{
mb.SetMetricProcessor(simpleProcessor);
mb.SetMetricExporter(exporter);
mb.SetMetricPushInterval(TimeSpan.FromMilliseconds(MetricPushIntervalMsec));
}).GetMeter("library1");
var meter = Sdk.CreateMeterProviderBuilder()
.SetProcessor(simpleProcessor)
.SetExporter(exporter)
.SetPushInterval(TimeSpan.FromMilliseconds(MetricPushIntervalMsec))
.Build()
.GetMeter("library1");

var testCounter = meter.CreateInt64Counter("testCounter");
var testMeasure = meter.CreateInt64Measure("testMeasure");
Expand Down
22 changes: 18 additions & 4 deletions test/OpenTelemetry.Tests/Metrics/CounterCleanUpTests.cs
Expand Up @@ -37,7 +37,11 @@ public CounterCleanUpTests(ITestOutputHelper output)
public void LongCounterBoundInstrumentsStatusUpdatedCorrectlySingleThread()
{
var testProcessor = new TestMetricProcessor();
var meter = Sdk.CreateMeterProvider(mb => mb.SetMetricProcessor(testProcessor)).GetMeter("library1") as MeterSdk;
var meter = Sdk.CreateMeterProviderBuilder()
.SetProcessor(testProcessor)
.Build()
.GetMeter("library1") as MeterSdk;

var testCounter = meter.CreateInt64Counter("testCounter") as CounterMetricSdkBase<long>;
var labels1 = new List<KeyValuePair<string, string>>();
labels1.Add(new KeyValuePair<string, string>("dim1", "value1"));
Expand Down Expand Up @@ -108,7 +112,10 @@ public void LongCounterBoundInstrumentsStatusUpdatedCorrectlySingleThread()
public void DoubleCounterBoundInstrumentsStatusUpdatedCorrectlySingleThread()
{
var testProcessor = new TestMetricProcessor();
var meter = Sdk.CreateMeterProvider(mb => mb.SetMetricProcessor(testProcessor)).GetMeter("library1") as MeterSdk;
var meter = Sdk.CreateMeterProviderBuilder()
.SetProcessor(testProcessor)
.Build()
.GetMeter("library1") as MeterSdk;
var testCounter = meter.CreateDoubleCounter("testCounter") as CounterMetricSdkBase<double>;

var labels1 = new List<KeyValuePair<string, string>>();
Expand Down Expand Up @@ -180,7 +187,11 @@ public void DoubleCounterBoundInstrumentsStatusUpdatedCorrectlySingleThread()
public void LongCounterBoundInstrumentsStatusUpdatedCorrectlyMultiThread()
{
var testProcessor = new TestMetricProcessor();
var meter = Sdk.CreateMeterProvider(mb => mb.SetMetricProcessor(testProcessor)).GetMeter("library1") as MeterSdk;
var meter = Sdk.CreateMeterProviderBuilder()
.SetProcessor(testProcessor)
.Build()
.GetMeter("library1") as MeterSdk;

var testCounter = meter.CreateInt64Counter("testCounter") as CounterMetricSdkBase<long>;

var labels1 = new List<KeyValuePair<string, string>>();
Expand Down Expand Up @@ -249,7 +260,10 @@ public void LongCounterBoundInstrumentsStatusUpdatedCorrectlyMultiThread()
public void DoubleCounterBoundInstrumentsStatusUpdatedCorrectlyMultiThread()
{
var testProcessor = new TestMetricProcessor();
var meter = Sdk.CreateMeterProvider(mb => mb.SetMetricProcessor(testProcessor)).GetMeter("library1") as MeterSdk;
var meter = Sdk.CreateMeterProviderBuilder()
.SetProcessor(testProcessor)
.Build()
.GetMeter("library1") as MeterSdk;
var testCounter = meter.CreateDoubleCounter("testCounter") as CounterMetricSdkBase<double>;

var labels1 = new List<KeyValuePair<string, string>>();
Expand Down
5 changes: 4 additions & 1 deletion test/OpenTelemetry.Tests/Metrics/MeterFactoryTests.cs
Expand Up @@ -28,7 +28,10 @@ public class MeterFactoryTests
public void DefaultMeterShouldBeCollectedAsWell()
{
var testProcessor = new TestMetricProcessor();
var meterProvider = (MeterProviderSdk)Sdk.CreateMeterProvider(mb => mb.SetMetricProcessor(testProcessor));
var meterProvider = Sdk.CreateMeterProviderBuilder()
.SetProcessor(testProcessor)
.Build() as MeterProviderSdk;

var controller = meterProvider.PushMetricController;
var defaultMeter = meterProvider.GetMeter(string.Empty) as MeterSdk;

Expand Down
10 changes: 6 additions & 4 deletions test/OpenTelemetry.Tests/Metrics/MeterProviderTests.cs
Expand Up @@ -41,7 +41,7 @@ public void MeterProvider_Default()
[Fact]
public void MeterProvider_SetDefault()
{
var meterProvider = Sdk.CreateMeterProvider(b => { });
var meterProvider = Sdk.CreateMeterProviderBuilder().Build();
MeterProvider.SetDefault(meterProvider);

var defaultMeter = MeterProvider.Default.GetMeter(string.Empty);
Expand All @@ -63,8 +63,9 @@ public void MeterProvider_SetDefaultNull()
[Fact]
public void MeterProvider_SetDefaultTwice_Throws()
{
MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { }));
Assert.Throws<InvalidOperationException>(() => MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { })));
var meterProvider = Sdk.CreateMeterProviderBuilder().Build();
MeterProvider.SetDefault(meterProvider);
Assert.Throws<InvalidOperationException>(() => MeterProvider.SetDefault(meterProvider));
}

[Fact]
Expand All @@ -74,7 +75,8 @@ public void MeterProvider_UpdateDefault_CachedTracer()
var noOpCounter = defaultMeter.CreateDoubleCounter("ctr");
Assert.IsType<NoopCounterMetric<double>>(noOpCounter);

MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { }));
var meterProvider = Sdk.CreateMeterProviderBuilder().Build();
MeterProvider.SetDefault(meterProvider);
var counter = defaultMeter.CreateDoubleCounter("ctr");
Assert.IsType<DoubleCounterMetricSdk>(counter);

Expand Down