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

Refactor MeterProvider to be similar to TracerProvider #2141

Merged
merged 3 commits into from
Jul 16, 2021

Conversation

cijothomas
Copy link
Member

Changes

  1. Match MeterProvider more closely to TracerProvider, with most responsibilities pushed off elsewhere. MeterProvider just holds the configuration (processors, and views in the future..), just like tracerprovider.
  2. Reuse most of the already existing classes like BaseExporter, and model MetricExporter similar to TraceExporter. This is iteration 1, I expect many more rounds to this in follow up PRs.
  3. Add Push and Pull based exporter.
  4. Removed console exporter from SDK project, and moved it off to Exporter.Console project. (like logs and traces)
  5. The above forced the MetricItem and associated classes to be made public. Alternate option is to give internalsvisible to Console. Picked the former approach in this PR. The "MetricItem" interface is something we'll need to come back and modify based on feedback from OTLP Exporter work, and other exporters. It is also to be explored to avoid "MetricItem" class completely, and give the exporters access to the "aggregated in-memory stream" in a different way to avoid allocs.
  6. Only one "pipeline" works. Though any # of MetricProcessors can be added, adding more than one would result in incorrect metrics. This is going to be fixed in the immediately upcoming PR.
  7. The current code somewhat "shared" the aggregator for multiple exporters, if the exporters same exact same export interval. This PR breaks that capability. Will come back and see if this "shared" aggregator can be brought back. I think in the initial version, we'll have "duplicated" aggregators

Sorry about the long list of changes in single PR! All of this was interconnected, and I felt it was not worth the effort to split them. After this refactor, hoping to get very localized changes only :)

@cijothomas cijothomas requested a review from a team July 15, 2021 23:03
/// <returns><see cref="MeterProvider"/>.</returns>
public static MeterProviderBuilder AddProcessor(this MeterProviderBuilder meterProviderBuilder, MeasurementProcessor processor)
public static MeterProviderBuilder AddMeasurementProcessor(this MeterProviderBuilder meterProviderBuilder, MeasurementProcessor processor)
Copy link
Member Author

Choose a reason for hiding this comment

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

this might be removed from the spec. if that happens, we'll also remove here.

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 need it, it might be SetMeasurementProcessor since we don't allow multiple processors.

@@ -138,43 +127,21 @@ protected override void Dispose(bool disposing)
}
}

private async Task CollectorTask(CancellationToken token, int collectionPeriodMilliseconds, MetricProcessor[] processors)
private MetricItem Collect()
Copy link
Member Author

Choose a reason for hiding this comment

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

MeterProvider has this method, but it never calls this. Its called by MetricProcessors, whenever they want. Typically in fixed time intervals (PushExporter) or in response to Scrape requests (PullExporter). Eitherway, MeterProvider doesn't care.

this.getMetrics = getMetrics;
}

public void PullRequest()
Copy link
Member Author

Choose a reason for hiding this comment

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

Method called in response to some scrap request.

@@ -28,73 +28,6 @@ public class MetricApiTest
[Fact]
public void SimpleTest()
{
Copy link
Member Author

Choose a reason for hiding this comment

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

removed as this was not doing any Tests. Will be adding unit tests for all features in subsequent PRs.

@cijothomas cijothomas requested a review from victlu July 15, 2021 23:53
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private readonly List<Task> collectorTasks = new List<Task>();
private readonly MeterListener listener;
private readonly List<MeasurementProcessor> measurementProcessors = new List<MeasurementProcessor>();
private readonly List<MetricProcessor> metricProcessors = new List<MetricProcessor>();
Copy link
Member

Choose a reason for hiding this comment

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

Inside the SDK it might make sense to have one single MetricProcessor, which can be a CompositeProcessor (similar like what we did for log/trace). Not a blocker though.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes! that's the plan. Will orchestrate it in such a way that one processor read the state, and provides it to the next ones.. Needs some non-trivial change, so making it in coming PRs.

this.MeasurementProcessors.AddRange(measurementProcessors);

this.ExportProcessors.AddRange(metricExportProcessors);
foreach (var processor in this.metricProcessors)
Copy link
Member

Choose a reason for hiding this comment

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

Remember the linked list?

It might save the foreach heap allocation.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes. (this is at build time only, but yes will optimize)

Copy link
Member

@reyang reyang left a comment

Choose a reason for hiding this comment

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

LGTM.

@codecov
Copy link

codecov bot commented Jul 16, 2021

Codecov Report

Merging #2141 (c3ff6f5) into metrics (9a5d9fd) will decrease coverage by 5.42%.
The diff coverage is 0.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##           metrics    #2141      +/-   ##
===========================================
- Coverage    83.66%   78.24%   -5.43%     
===========================================
  Files          211      212       +1     
  Lines         6641     6632       -9     
===========================================
- Hits          5556     5189     -367     
- Misses        1085     1443     +358     
Impacted Files Coverage Δ
src/OpenTelemetry/Metrics/AggregatorStore.cs 0.00% <0.00%> (-88.41%) ⬇️
src/OpenTelemetry/Metrics/InstrumentState.cs 0.00% <0.00%> (-100.00%) ⬇️
...elemetry/Metrics/MeterProviderBuilderExtensions.cs 0.00% <0.00%> (-66.67%) ⬇️
...c/OpenTelemetry/Metrics/MeterProviderBuilderSdk.cs 0.00% <0.00%> (-92.00%) ⬇️
src/OpenTelemetry/Metrics/MeterProviderSdk.cs 0.00% <0.00%> (-97.27%) ⬇️
src/OpenTelemetry/Metrics/Processors/MetricItem.cs 0.00% <0.00%> (-100.00%) ⬇️
...elemetry/Metrics/Processors/PullMetricProcessor.cs 0.00% <0.00%> (ø)
...elemetry/Metrics/Processors/PushMetricProcessor.cs 0.00% <0.00%> (ø)
src/OpenTelemetry.Api/Metrics/MeterProvider.cs 0.00% <0.00%> (-100.00%) ⬇️
...rc/OpenTelemetry/Metrics/DataPoint/DataValue{T}.cs 0.00% <0.00%> (-100.00%) ⬇️
... and 22 more

namespace OpenTelemetry.Metrics
{
public abstract class MetricProcessor : BaseProcessor<MetricItem>
{
// GetMetric or GetMemoryState or GetAggregatedMetrics..
// ...or some other names
public abstract void SetGetMetricFunction(Func<MetricItem> getMetrics);
Copy link
Member

Choose a reason for hiding this comment

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

I might not be thinking about things right, but would it make sense for a MetricProcessor to have a handle on the ParentProvider kinda like how we do for traces? That way instead of calling SetGetMetricFunction(this.Collect) in the MeterProviderSdk you'd have a handle on the provider to call Collect directly.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like this idea. Will explore more on and try it in the subsequent PRs.

Copy link
Member

@alanwest alanwest left a comment

Choose a reason for hiding this comment

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

These are some great improvements!

@cijothomas cijothomas merged commit 63c28f0 into metrics Jul 16, 2021
@cijothomas cijothomas deleted the cijothomas/refactormetricsliketraces_part1 branch July 16, 2021 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants