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

[DRAFT] fixing InMemoryExporter & Metrics bug. new class: ExportableMetricCopy. new ctor: InMemoryExporter(Func) #3198

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6d1a88c
implementation
TimothyMothra Apr 15, 2022
e8a496c
OpenTelemetry.Tests
TimothyMothra Apr 15, 2022
be840b5
OpenTelemetry.Instrumentation.Http.Tests
TimothyMothra Apr 15, 2022
26c0d4a
OpenTelemetry.Instrumentation.AspNetCore.Tests
TimothyMothra Apr 15, 2022
9fbc304
OpenTelemetry.Instrumentation.AspNet.Tests
TimothyMothra Apr 15, 2022
be30a48
Benchmarks
TimothyMothra Apr 15, 2022
9e09be3
sort alphabetically
TimothyMothra Apr 15, 2022
357b3a3
more OpenTelemetry.Tests
TimothyMothra Apr 16, 2022
c75dc01
fix public api
TimothyMothra Apr 16, 2022
c8cbd0a
Merge branch 'main' into 2361_ExportableMetricCopy
cijothomas Apr 18, 2022
1a28ae7
remove extension methods that created InMemoryExporter<Metric>.
TimothyMothra Apr 20, 2022
ed66ad5
Merge branch '2361_ExportableMetricCopy' of https://github.com/Timoth…
TimothyMothra Apr 20, 2022
a7641c4
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 20, 2022
6d40549
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 20, 2022
26d7e1f
merge conflict: fix test
TimothyMothra Apr 20, 2022
9a0d99a
addressing code review feedback; cleanup and removing boilerplate
TimothyMothra Apr 21, 2022
3a59585
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 21, 2022
f2b2062
change to internal
TimothyMothra Apr 21, 2022
8c06f94
removed change to Batch
TimothyMothra Apr 21, 2022
5850db8
cleanup
TimothyMothra Apr 21, 2022
493520b
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 21, 2022
0027a4d
add extension class to tests.shared
TimothyMothra Apr 22, 2022
365b8cc
Merge branch '2361_ExportableMetricCopy' of https://github.com/Timoth…
TimothyMothra Apr 22, 2022
ec7ee18
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 22, 2022
f68b76e
cleanup
TimothyMothra Apr 22, 2022
42e4854
cleanup
TimothyMothra Apr 22, 2022
afb1d86
additional unit test
TimothyMothra Apr 22, 2022
cd5f68d
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 22, 2022
fb94b9a
failure exporter
TimothyMothra Apr 22, 2022
334779f
Merge branch '2361_ExportableMetricCopy' of https://github.com/Timoth…
TimothyMothra Apr 22, 2022
8dc80e6
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 22, 2022
054400d
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 25, 2022
534c674
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 26, 2022
3141ec3
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra Apr 28, 2022
942e952
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra May 4, 2022
e40acc5
Merge branch 'main' into 2361_ExportableMetricCopy
cijothomas May 5, 2022
38f0b6d
Merge branch 'main' into 2361_ExportableMetricCopy
TimothyMothra May 10, 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
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
OpenTelemetry.Exporter.InMemoryExporter<T>.InMemoryExporter(System.Func<OpenTelemetry.Batch<T>, OpenTelemetry.ExportResult> exportFunc) -> void
OpenTelemetry.Metrics.ExportableMetricCopy
OpenTelemetry.Metrics.ExportableMetricCopy.Description.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.ExportableMetricCopy(OpenTelemetry.Metrics.Metric metric) -> void
OpenTelemetry.Metrics.ExportableMetricCopy.MeterName.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.MeterVersion.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.MetricPoints.get -> System.Collections.Generic.IReadOnlyList<OpenTelemetry.Metrics.MetricPoint>
OpenTelemetry.Metrics.ExportableMetricCopy.MetricType.get -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.ExportableMetricCopy.Name.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.Unit.get -> string
OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.Metric> exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.Metric> exportedItems, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.ExportableMetricCopy> exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.ExportableMetricCopy> exportedItems, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>, OpenTelemetry.ExportResult> exportFunc) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>, OpenTelemetry.ExportResult> exportFunc, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
OpenTelemetry.Exporter.InMemoryExporter<T>.InMemoryExporter(System.Func<OpenTelemetry.Batch<T>, OpenTelemetry.ExportResult> exportFunc) -> void
OpenTelemetry.Metrics.ExportableMetricCopy
OpenTelemetry.Metrics.ExportableMetricCopy.Description.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.ExportableMetricCopy(OpenTelemetry.Metrics.Metric metric) -> void
OpenTelemetry.Metrics.ExportableMetricCopy.MeterName.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.MeterVersion.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.MetricPoints.get -> System.Collections.Generic.IReadOnlyList<OpenTelemetry.Metrics.MetricPoint>
OpenTelemetry.Metrics.ExportableMetricCopy.MetricType.get -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.ExportableMetricCopy.Name.get -> string
OpenTelemetry.Metrics.ExportableMetricCopy.Unit.get -> string
OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.Metric> exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.Metric> exportedItems, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.ExportableMetricCopy> exportedItems) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Collections.Generic.ICollection<OpenTelemetry.Metrics.ExportableMetricCopy> exportedItems, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>, OpenTelemetry.ExportResult> exportFunc) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.InMemoryExporterMetricsExtensions.AddInMemoryExporter(this OpenTelemetry.Metrics.MeterProviderBuilder builder, System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>, OpenTelemetry.ExportResult> exportFunc, System.Action<OpenTelemetry.Metrics.MetricReaderOptions> configureMetricReader) -> OpenTelemetry.Metrics.MeterProviderBuilder
58 changes: 58 additions & 0 deletions src/OpenTelemetry.Exporter.InMemory/ExportableMetricCopy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// <copyright file="ExportableMetricCopy.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;

namespace OpenTelemetry.Metrics
{
/// <summary>
/// This class represents a selective copy of <see cref="Metric"/>.
/// This contains the minimum fields and properties needed for most
/// unit testing scenarios.
/// </summary>
public class ExportableMetricCopy
{
private readonly MetricStreamIdentity instrumentIdentity;

public ExportableMetricCopy(Metric metric)
{
this.instrumentIdentity = metric.InstrumentIdentity;
this.MetricType = metric.MetricType;

List<MetricPoint> metricPoints = new();
foreach (ref readonly var metricPoint in metric.GetMetricPoints())
{
metricPoints.Add(metricPoint.Copy());
}

this.MetricPoints = metricPoints;
}

public string Name => this.instrumentIdentity.InstrumentName;

public string Description => this.instrumentIdentity.Description;

public string Unit => this.instrumentIdentity.Unit;

public string MeterName => this.instrumentIdentity.MeterName;

public MetricType MetricType { get; }

public string MeterVersion => this.instrumentIdentity.MeterVersion;

public IReadOnlyList<MetricPoint> MetricPoints { get; }
}
}
19 changes: 18 additions & 1 deletion src/OpenTelemetry.Exporter.InMemory/InMemoryExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;

namespace OpenTelemetry.Exporter
Expand All @@ -22,13 +23,29 @@ public class InMemoryExporter<T> : BaseExporter<T>
where T : class
{
private readonly ICollection<T> exportedItems;
private readonly ExportDelegate onExport;

public InMemoryExporter(ICollection<T> exportedItems)
{
if (typeof(T) == typeof(Metrics.Metric))
{
throw new NotSupportedException("Exported Metrics are not trustworthy because they can continue to be updated after export. Recommend use ExportableMetricCopy.");
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure I follow the reason behind this throw...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is by design to force the use of the Copy.
The thought behind this was to prevent users from creating the InMemoryExporter<Metric> because the Metric is known to be faulty. #3198 (comment)

I've documented some scenarios where the Metric can and cannot be trusted: #2361 (comment)

That being said, Prometheus and OTLP have some units tests where they need the actual Metric to provide to their own internals. (documented in the Summary above).

I'm eager to hear your perspective on this!
I'm trying to find the happy medium to support all these use cases while protecting users.
If we decide to allow users to create InMemoryExporter<Metric> we also need to inform/educate users on the risks.

Copy link
Member

Choose a reason for hiding this comment

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

We don't need to prevent users from using the one. A lot of tests are already using it, and working fine. (they understand the documented limitation of Metric that it may be updated after Export() call, but they are orchestrating things so as to not be affected)

This can be additional option, for InMemory users, who wants to test metrics, without being affected by the limitation that the memory could be updated.

Copy link
Member

Choose a reason for hiding this comment

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

To unblock progress - lets split PR into sub Prs.

  1. Add the additional option in InMemoryExporter to use MetricCopy, leave existing functionality untouched. i.e don't change unit tests, except the one breaking due to the metric-being-updated-after-export issue.
  2. We can use the SIG meeting to see if there are strong reasons favoring/against keeping the current exporter, and based on that keep it or remove it.

}

this.exportedItems = exportedItems;
this.onExport = this.DefaultExport;
}

public InMemoryExporter(Func<Batch<T>, ExportResult> exportFunc)
{
this.onExport = (in Batch<T> batch) => exportFunc(batch);
}

public override ExportResult Export(in Batch<T> batch)
private delegate ExportResult ExportDelegate(in Batch<T> batch);

public override ExportResult Export(in Batch<T> batch) => this.onExport(batch);

private ExportResult DefaultExport(in Batch<T> batch)
{
if (this.exportedItems == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,39 @@ public static class InMemoryExporterMetricsExtensions
/// Adds InMemory metric exporter to the <see cref="MeterProviderBuilder"/> using default options.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> builder to use.</param>
/// <param name="exportedItems">Collection which will be populated with the exported MetricItem.</param>
/// <param name="exportedItems">Collection which will be populated with the exported MetricItem represented as <see cref="ExportableMetricCopy"/>.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder builder, ICollection<Metric> exportedItems)
public static MeterProviderBuilder AddInMemoryExporter(
this MeterProviderBuilder builder,
ICollection<ExportableMetricCopy> exportedItems)
{
return builder.AddInMemoryExporter(exportedItems: exportedItems, configureMetricReader: null);
}

/// <summary>
/// Adds InMemory metric exporter to the <see cref="MeterProviderBuilder"/> using default options.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> builder to use.</param>
/// <param name="exportFunc">A function which will replace <see cref="InMemoryExporter{T}.Export(in Batch{T})"/>.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
public static MeterProviderBuilder AddInMemoryExporter(
this MeterProviderBuilder builder,
Func<Batch<Metric>, ExportResult> exportFunc)
{
return builder.AddInMemoryExporter(exportFunc: exportFunc, configureMetricReader: null);
}

/// <summary>
/// Adds InMemory metric exporter to the <see cref="MeterProviderBuilder"/> using default options.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> builder to use.</param>
/// <param name="exportedItems">Collection which will be populated with the exported MetricItem represented as <see cref="ExportableMetricCopy"/>.</param>
/// <param name="configureMetricReader"><see cref="MetricReader"/> configuration options.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
public static MeterProviderBuilder AddInMemoryExporter(
this MeterProviderBuilder builder,
ICollection<ExportableMetricCopy> exportedItems,
Action<MetricReaderOptions> configureMetricReader)
{
Guard.ThrowIfNull(builder);
Guard.ThrowIfNull(exportedItems);
Expand All @@ -45,45 +75,76 @@ public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder
{
return deferredMeterProviderBuilder.Configure((sp, builder) =>
{
AddInMemoryExporter(builder, exportedItems, sp.GetOptions<MetricReaderOptions>(), null);
AddInMemoryExporter(builder, exportedItems, sp.GetOptions<MetricReaderOptions>(), configureMetricReader);
});
}

return AddInMemoryExporter(builder, exportedItems, new MetricReaderOptions(), null);
return AddInMemoryExporter(builder, exportedItems, new MetricReaderOptions(), configureMetricReader);
}

/// <summary>
/// Adds InMemory metric exporter to the <see cref="MeterProviderBuilder"/> using default options.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> builder to use.</param>
/// <param name="exportedItems">Collection which will be populated with the exported MetricItem.</param>
/// <param name="exportFunc">A function which will replace <see cref="InMemoryExporter{T}.Export(in Batch{T})"/>.</param>
/// <param name="configureMetricReader"><see cref="MetricReader"/> configuration options.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
public static MeterProviderBuilder AddInMemoryExporter(this MeterProviderBuilder builder, ICollection<Metric> exportedItems, Action<MetricReaderOptions> configureMetricReader)
public static MeterProviderBuilder AddInMemoryExporter(
this MeterProviderBuilder builder,
Func<Batch<Metric>, ExportResult> exportFunc,
TimothyMothra marked this conversation as resolved.
Show resolved Hide resolved
Action<MetricReaderOptions> configureMetricReader)
{
Guard.ThrowIfNull(builder);
Guard.ThrowIfNull(exportedItems);
Guard.ThrowIfNull(exportFunc);

if (builder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder)
{
return deferredMeterProviderBuilder.Configure((sp, builder) =>
{
AddInMemoryExporter(builder, exportedItems, sp.GetOptions<MetricReaderOptions>(), configureMetricReader);
AddInMemoryExporter(builder, exportFunc, sp.GetOptions<MetricReaderOptions>(), configureMetricReader);
});
}

return AddInMemoryExporter(builder, exportedItems, new MetricReaderOptions(), configureMetricReader);
return AddInMemoryExporter(builder, exportFunc, new MetricReaderOptions(), configureMetricReader);
}

private static MeterProviderBuilder AddInMemoryExporter(
MeterProviderBuilder builder,
ICollection<ExportableMetricCopy> exportedItems,
MetricReaderOptions metricReaderOptions,
Action<MetricReaderOptions> configureMetricReader)
{
configureMetricReader?.Invoke(metricReaderOptions);

var metricExporter = new InMemoryExporter<Metric>(
exportFunc: metricBatch =>
{
foreach (var metric in metricBatch)
{
exportedItems.Add(new ExportableMetricCopy(metric));
}

return ExportResult.Success;
});

var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader(
metricExporter,
metricReaderOptions,
DefaultExportIntervalMilliseconds,
DefaultExportTimeoutMilliseconds);

return builder.AddReader(metricReader);
}

private static MeterProviderBuilder AddInMemoryExporter(
MeterProviderBuilder builder,
ICollection<Metric> exportedItems,
Func<Batch<Metric>, ExportResult> exportFunc,
MetricReaderOptions metricReaderOptions,
Action<MetricReaderOptions> configureMetricReader)
{
configureMetricReader?.Invoke(metricReaderOptions);

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

var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader(
metricExporter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\PeriodicExportingMetricReaderHelper.cs" Link="Includes\PeriodicExportingMetricReaderHelper.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry\Internal\ServiceProviderExtensions.cs" Link="Includes\ServiceProviderExtensions.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions src/OpenTelemetry/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("OpenTelemetry.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.InMemory" + AssemblyInfo.PublicKey)]
TimothyMothra marked this conversation as resolved.
Show resolved Hide resolved
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)]
Expand Down
1 change: 1 addition & 0 deletions src/OpenTelemetry/Metrics/HistogramBuckets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ internal HistogramBuckets Copy()
HistogramBuckets copy = new HistogramBuckets(this.ExplicitBounds);

Array.Copy(this.SnapshotBucketCounts, copy.SnapshotBucketCounts, this.SnapshotBucketCounts.Length);
Array.Copy(this.RunningBucketCounts, copy.RunningBucketCounts, this.RunningBucketCounts.Length);
copy.SnapshotSum = this.SnapshotSum;

return copy;
Expand Down
4 changes: 4 additions & 0 deletions test/Benchmarks/Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\test\OpenTelemetry.Tests\Shared\InMemoryExporterMetricsExtensions.cs" Link="Includes\InMemoryExporterMetricsExtensions.cs" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion test/Benchmarks/Metrics/HistogramBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void Setup()
this.bounds[i] = i * MaxValue / this.bounds.Length;
}

var exportedItems = new List<Metric>();
var exportedItems = new List<ExportableMetricCopy>();
Copy link
Member

Choose a reason for hiding this comment

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

is it required to force every test to use the new MetricCopy unless they need to rely on it?
Or is it by design that InMemoryExporter will force one to use the MetricCopy option only? What I don't need/care about the fact that Metric could be update after export() call is done?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, current approach was to force the use of the Copy.
See the comment above for more details #3198 (comment)


this.provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(this.meter.Name)
Expand Down
2 changes: 1 addition & 1 deletion test/Benchmarks/Metrics/MetricsBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void Setup()
{
this.meter = new Meter(Utils.GetCurrentMethodName());

var exportedItems = new List<Metric>();
var exportedItems = new List<ExportableMetricCopy>();
this.provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(this.meter.Name) // All instruments from this meter are enabled.
.AddInMemoryExporter(exportedItems, metricReaderOptions =>
Expand Down
4 changes: 2 additions & 2 deletions test/Benchmarks/Metrics/MetricsViewBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class MetricsViewBenchmarks
private static readonly ThreadLocal<Random> ThreadLocalRandom = new(() => new Random());
private static readonly string[] DimensionValues = new string[] { "DimVal1", "DimVal2", "DimVal3", "DimVal4", "DimVal5", "DimVal6", "DimVal7", "DimVal8", "DimVal9", "DimVal10" };
private static readonly int DimensionsValuesLength = DimensionValues.Length;
private List<Metric> metrics;
private List<ExportableMetricCopy> metrics;
private Counter<long> counter;
private MeterProvider provider;
private Meter meter;
Expand Down Expand Up @@ -81,7 +81,7 @@ public void Setup()
{
this.meter = new Meter(Utils.GetCurrentMethodName());
this.counter = this.meter.CreateCounter<long>("counter");
this.metrics = new List<Metric>();
this.metrics = new List<ExportableMetricCopy>();

if (this.ViewConfig == ViewConfiguration.NoView)
{
Expand Down
Loading