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

Change InMemoryExporter to clear collection before exporting Metrics #2937

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f944a1c
Merge pull request #1 from open-telemetry/main
TimothyMothra Jan 28, 2022
ba726c5
Merge branch 'open-telemetry:main' into main
TimothyMothra Feb 10, 2022
68d1977
Merge branch 'open-telemetry:main' into main
TimothyMothra Feb 15, 2022
9dcb839
poc for fix to InMemoryExporter
TimothyMothra Feb 16, 2022
34d15ec
Revert "poc for fix to InMemoryExporter"
TimothyMothra Feb 22, 2022
436f0dc
Merge branch 'open-telemetry:main' into main
TimothyMothra Feb 22, 2022
48bf1e9
change InMemoryExporter. update tests. add more tests.
TimothyMothra Feb 23, 2022
2d06efc
cleanup
TimothyMothra Feb 23, 2022
1617248
cleanup
TimothyMothra Feb 23, 2022
8aa4885
Merge branch 'main' into 2361
TimothyMothra Feb 23, 2022
4723675
cleanup tests
TimothyMothra Feb 24, 2022
f4b40fd
changelog
TimothyMothra Feb 24, 2022
70fc774
Merge branch 'main' into 2361
TimothyMothra Feb 24, 2022
99f3aa0
Update README.md
TimothyMothra Feb 24, 2022
93db30d
Update InMemoryExporter.cs
TimothyMothra Feb 24, 2022
d080e27
fix markdownlint
TimothyMothra Feb 24, 2022
31c7be9
Merge branch 'main' into 2361
cijothomas Feb 24, 2022
37aa2af
Update README.md
TimothyMothra Feb 24, 2022
d8a8b6e
cleanup
TimothyMothra Feb 24, 2022
d6b488c
Merge branch '2361' of https://github.com/TimothyMothra/opentelemetry…
TimothyMothra Feb 24, 2022
3078c97
Delete InMemoryExporterTests.cs
TimothyMothra Feb 24, 2022
b0a07aa
Merge branch 'main' into 2361
TimothyMothra Feb 24, 2022
598aa0d
Merge branch 'main' into 2361
TimothyMothra Feb 28, 2022
585177a
Merge branch 'main' into 2361
TimothyMothra Mar 1, 2022
8fa1aad
Merge branch 'main' into 2361
TimothyMothra Mar 4, 2022
6de7a75
Merge branch 'main' into 2361
cijothomas Mar 8, 2022
4f8de4d
Update docs/metrics/extending-the-sdk/README.md
TimothyMothra Mar 8, 2022
bffb822
Update docs/metrics/extending-the-sdk/README.md
TimothyMothra Mar 8, 2022
1fa45bd
Update src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs
TimothyMothra Mar 8, 2022
79c1357
Merge branch 'main' into 2361
TimothyMothra Mar 8, 2022
fc33bb2
Update docs/metrics/extending-the-sdk/README.md
TimothyMothra Mar 8, 2022
58dccbc
markdownlint
TimothyMothra Mar 8, 2022
021f308
Merge branch 'main' into 2361
TimothyMothra Mar 9, 2022
87ee7f7
Merge branch 'main' into 2361
cijothomas Mar 9, 2022
b16c6bc
Merge branch 'main' into 2361
TimothyMothra Mar 11, 2022
a6e5140
Merge branch 'main' into 2361
TimothyMothra Mar 14, 2022
a86f858
Merge branch 'main' into 2361
TimothyMothra Mar 15, 2022
05aa392
Merge branch 'main' into 2361
TimothyMothra Mar 16, 2022
697fb9f
discussing an alternate approach
TimothyMothra Mar 17, 2022
6edcc26
merge main
TimothyMothra Mar 17, 2022
4f3f330
clean up public api
TimothyMothra Mar 18, 2022
c91f522
remove whitespace
TimothyMothra Mar 18, 2022
735b297
remove whitespace
TimothyMothra Mar 18, 2022
5de8c9c
fix whitespace
TimothyMothra Mar 18, 2022
83af046
update changelog
TimothyMothra Mar 18, 2022
cfb8773
Merge branch 'main' into 2361
TimothyMothra Mar 18, 2022
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
8 changes: 6 additions & 2 deletions docs/metrics/extending-the-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ not covered by the built-in exporters:
does not implement any retry logic.
* Exporters should avoid generating telemetry and causing live-loop, this can be
done via `OpenTelemetry.SuppressInstrumentationScope`.
* Exporters receives a batch of `Metric`, and each `Metric`
can contain 1 or more `MetricPoint`s.
* Exporters receive a batch of `Metric`, and each `Metric` can contain one or
more `MetricPoint`s. The exporter should perform all actions
(e.g. serializing etc.) with the `Metric`s and `MetricsPoint`s in the batch
before returning control from `Export`, once the control is returned, the
exporter can no longer make any assumptions about the state of the Batch or
anything inside it.
* Exporters should use `Activity.TagObjects` collection instead of
`Activity.Tags` to obtain the full set of attributes (tags).
* Exporters should use `ParentProvider.GetResource()` to get the `Resource`
Expand Down
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Released 2022-Mar-04
* Adds the ability to configure `MetricReaderOptions` via the
`AddInMemoryExporter` extension method.
([#2931](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2931))
* Add `InMemoryMetricExporter` which inherits `InMemoryExporter`.
This new class will clear the exported collection before exporting `Metric`s.
This prevents the same `Metric` from being repeated in the exported collection.
([#2937](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2937))

## 1.2.0-rc2

Expand Down
15 changes: 7 additions & 8 deletions src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,27 @@

using System.Collections.Generic;

using OpenTelemetry.Internal;

namespace OpenTelemetry.Exporter
{
public class InMemoryExporter<T> : BaseExporter<T>
Copy link
Member

Choose a reason for hiding this comment

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

we can add comment here.

where T : class
{
private readonly ICollection<T> exportedItems;
internal readonly ICollection<T> ExportedItems;

public InMemoryExporter(ICollection<T> exportedItems)
{
this.exportedItems = exportedItems;
Guard.ThrowIfNull(exportedItems);

this.ExportedItems = exportedItems;
}

public override ExportResult Export(in Batch<T> batch)
{
if (this.exportedItems == null)
{
return ExportResult.Failure;
}

foreach (var data in batch)
{
this.exportedItems.Add(data);
this.ExportedItems.Add(data);
}

return ExportResult.Success;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private static MeterProviderBuilder AddInMemoryExporter(
{
configureMetricReader?.Invoke(metricReaderOptions);

var metricExporter = new InMemoryExporter<Metric>(exportedItems);
var metricExporter = new InMemoryMetricExporter(exportedItems);

var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader(
metricExporter,
Expand Down
41 changes: 41 additions & 0 deletions src/OpenTelemetry.Exporter.InMemory/InMemoryMetricExporter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// <copyright file="InMemoryMetricExporter.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.Collections.Generic;

using OpenTelemetry.Metrics;

namespace OpenTelemetry.Exporter
{
internal class InMemoryMetricExporter : InMemoryExporter<Metric>
{
public InMemoryMetricExporter(ICollection<Metric> exportedItems)
: base(exportedItems)
{
}

public override ExportResult Export(in Batch<Metric> batch)
{
// By design, The MetricApi reuses Metrics (MetricReader.metricsCurrentBatch).
// This means that exported Metrics will always reflect the latest values.
// Here, we clear the exported collection to prevent populating
// this with duplicate instances of the same Metric.
this.ExportedItems.Clear();
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 (InMemoryExporter) does the clearing:

  1. We are clearing something collection given to us by the user.
  2. This prevents the user from doing comparison between 2 exports.

We could simply let the user do this, if they chose to. And document this in the readme.


return base.Export(batch);
}
}
}
68 changes: 0 additions & 68 deletions test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public void ExportOnlyWhenPointChanged(AggregationTemporality temporality)
meterProvider.ForceFlush();
Assert.Single(exportedItems);

exportedItems.Clear();
meterProvider.ForceFlush();
if (temporality == AggregationTemporality.Cumulative)
{
Expand Down
17 changes: 0 additions & 17 deletions test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,6 @@ public void DuplicateInstrumentNamesFromDifferentMetersAreAllowed(AggregationTem
var anotherCounterSameNameDiffMeter = meter2.CreateCounter<long>("name1");
anotherCounterSameNameDiffMeter.Add(10);
counterLong.Add(10);
exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(2, exportedItems.Count);
}
Expand Down Expand Up @@ -641,7 +640,6 @@ public void CounterAggregationTest(bool exportDelta)
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(20, sumReceived);

exportedItems.Clear();
counterLong.Add(10);
counterLong.Add(10);
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Expand All @@ -655,7 +653,6 @@ public void CounterAggregationTest(bool exportDelta)
Assert.Equal(40, sumReceived);
}

exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
sumReceived = GetLongSum(exportedItems);
if (exportDelta)
Expand All @@ -667,7 +664,6 @@ public void CounterAggregationTest(bool exportDelta)
Assert.Equal(40, sumReceived);
}

exportedItems.Clear();
counterLong.Add(40);
counterLong.Add(20);
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Expand Down Expand Up @@ -713,7 +709,6 @@ public void ObservableCounterAggregationTest(bool exportDelta)
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(10, sumReceived);

exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
sumReceived = GetLongSum(exportedItems);
if (exportDelta)
Expand All @@ -725,7 +720,6 @@ public void ObservableCounterAggregationTest(bool exportDelta)
Assert.Equal(20, sumReceived);
}

exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
sumReceived = GetLongSum(exportedItems);
if (exportDelta)
Expand Down Expand Up @@ -803,7 +797,6 @@ public void ObservableCounterWithTagsAggregationTest(bool exportDelta)
ValidateMetricPointTags(tags3, metricPoint3.Tags);

// Export 2
exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Single(exportedItems);
metric = exportedItems[0];
Expand Down Expand Up @@ -954,8 +947,6 @@ public void DimensionsAreOrderInsensitiveWithSortedKeysFirst(bool exportDelta)
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(75, sumReceived);

exportedItems.Clear();

counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(10, new("Key2", "Value2"), new("Key3", "Value3"), new("Key1", "Value1"));
Expand Down Expand Up @@ -1045,8 +1036,6 @@ public void DimensionsAreOrderInsensitiveWithUnsortedKeysFirst(bool exportDelta)
long sumReceived = GetLongSum(exportedItems);
Assert.Equal(75, sumReceived);

exportedItems.Clear();

counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(5, new("Key2", "Value2"), new("Key1", "Value1"), new("Key3", "Value3"));
counterLong.Add(10, new("Key2", "Value2"), new("Key3", "Value3"), new("Key1", "Value1"));
Expand Down Expand Up @@ -1097,29 +1086,25 @@ public void TestInstrumentDisposal(AggregationTemporality temporality)

meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(2, exportedItems.Count);
exportedItems.Clear();

counter1.Add(10, new KeyValuePair<string, object>("key", "value"));
counter2.Add(10, new KeyValuePair<string, object>("key", "value"));
meter1.Dispose();

meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(2, exportedItems.Count);
exportedItems.Clear();

counter1.Add(10, new KeyValuePair<string, object>("key", "value"));
counter2.Add(10, new KeyValuePair<string, object>("key", "value"));
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Single(exportedItems);
exportedItems.Clear();

counter1.Add(10, new KeyValuePair<string, object>("key", "value"));
counter2.Add(10, new KeyValuePair<string, object>("key", "value"));
meter2.Dispose();

meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Single(exportedItems);
exportedItems.Clear();

counter1.Add(10, new KeyValuePair<string, object>("key", "value"));
counter2.Add(10, new KeyValuePair<string, object>("key", "value"));
Expand Down Expand Up @@ -1172,7 +1157,6 @@ int MetricPointCount()
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount());

exportedItems.Clear();
counterLong.Add(10);
for (int i = 0; i < MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault + 1; i++)
{
Expand All @@ -1192,7 +1176,6 @@ int MetricPointCount()
counterLong.Add(10, new KeyValuePair<string, object>("key", "valueA"));
counterLong.Add(10, new KeyValuePair<string, object>("key", "valueB"));
counterLong.Add(10, new KeyValuePair<string, object>("key", "valueC"));
exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public void CheckExportForRecordingButNotSampledActivity()
[Fact]
public void CheckExportDrainsBatchOnFailure()
{
using var exporter = new InMemoryExporter<Activity>(null);
using var exporter = new InMemoryExporter<Activity>(new List<Activity>());
using var processor = new BatchActivityExportProcessor(
exporter,
maxQueueSize: 3,
Expand Down