From c12779d960918fdf7881a6d81d215e51e509ebd7 Mon Sep 17 00:00:00 2001 From: Asaf Mesika Date: Thu, 8 Feb 2024 17:29:16 +0200 Subject: [PATCH] Memory mode: Adding support for synchronous instruments - Last Value aggregation (#6196) --- .../internal/state/ProfileBenchmark.java | 2 +- .../internal/state/TestInstrumentType.java | 6 +- .../state/tester/DoubleLastValueTester.java | 50 ++++++++++++ .../state/tester/LongLastValueTester.java | 51 ++++++++++++ .../aggregator/DoubleLastValueAggregator.java | 27 +++++-- .../aggregator/LongLastValueAggregator.java | 29 +++++-- .../internal/view/LastValueAggregation.java | 6 +- .../DoubleLastValueAggregatorTest.java | 80 +++++++++++++++---- .../LongLastValueAggregatorTest.java | 69 ++++++++++++---- 9 files changed, 275 insertions(+), 45 deletions(-) create mode 100644 sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/DoubleLastValueTester.java create mode 100644 sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/LongLastValueTester.java diff --git a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/ProfileBenchmark.java b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/ProfileBenchmark.java index 26f4588582b..2d091bfd725 100644 --- a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/ProfileBenchmark.java +++ b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/ProfileBenchmark.java @@ -37,7 +37,7 @@ public static void main(String[] args) { // Parameters AggregationTemporality aggregationTemporality = AggregationTemporality.DELTA; MemoryMode memoryMode = MemoryMode.REUSABLE_DATA; - TestInstrumentType testInstrumentType = TestInstrumentType.EXPLICIT_BUCKET; + TestInstrumentType testInstrumentType = TestInstrumentType.DOUBLE_LAST_VALUE; InstrumentGarbageCollectionBenchmark.ThreadState benchmarkSetup = new InstrumentGarbageCollectionBenchmark.ThreadState(); diff --git a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java index 1cf082699be..98cc39a6657 100644 --- a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java +++ b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/TestInstrumentType.java @@ -9,9 +9,11 @@ import io.opentelemetry.sdk.metrics.Aggregation; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.internal.state.tester.AsyncCounterTester; +import io.opentelemetry.sdk.metrics.internal.state.tester.DoubleLastValueTester; import io.opentelemetry.sdk.metrics.internal.state.tester.DoubleSumTester; import io.opentelemetry.sdk.metrics.internal.state.tester.ExplicitBucketHistogramTester; import io.opentelemetry.sdk.metrics.internal.state.tester.ExponentialHistogramTester; +import io.opentelemetry.sdk.metrics.internal.state.tester.LongLastValueTester; import io.opentelemetry.sdk.metrics.internal.state.tester.LongSumTester; import java.util.List; import java.util.Random; @@ -23,7 +25,9 @@ public enum TestInstrumentType { EXPONENTIAL_HISTOGRAM(ExponentialHistogramTester::new), EXPLICIT_BUCKET(ExplicitBucketHistogramTester::new), LONG_SUM(LongSumTester::new, /* dataAllocRateReductionPercentage= */ 97.3f), - DOUBLE_SUM(DoubleSumTester::new, /* dataAllocRateReductionPercentage= */ 97.3f); + DOUBLE_SUM(DoubleSumTester::new, /* dataAllocRateReductionPercentage= */ 97.3f), + LONG_LAST_VALUE(LongLastValueTester::new, /* dataAllocRateReductionPercentage= */ 97.3f), + DOUBLE_LAST_VALUE(DoubleLastValueTester::new, /* dataAllocRateReductionPercentage= */ 97.3f); private final Supplier instrumentTesterInitializer; private final float dataAllocRateReductionPercentage; diff --git a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/DoubleLastValueTester.java b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/DoubleLastValueTester.java new file mode 100644 index 00000000000..c9144ad2c1a --- /dev/null +++ b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/DoubleLastValueTester.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.state.tester; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.sdk.metrics.Aggregation; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.internal.state.TestInstrumentType; +import java.util.List; +import java.util.Random; + +public class DoubleLastValueTester implements TestInstrumentType.InstrumentTester { + + @Override + public Aggregation testedAggregation() { + return Aggregation.lastValue(); + } + + @SuppressWarnings("ForLoopReplaceableByForEach") // This is for GC sensitivity testing: no streams + @Override + public TestInstrumentType.TestInstrumentsState buildInstruments( + double instrumentCount, + SdkMeterProvider sdkMeterProvider, + List attributesList, + Random random) { + Meter meter = sdkMeterProvider.meterBuilder("meter").build(); + meter + .gaugeBuilder("test.double.last.value") + .buildWithCallback( + observableDoubleMeasurement -> { + for (int j = 0; j < attributesList.size(); j++) { + observableDoubleMeasurement.record(1.2f, attributesList.get(j)); + } + }); + + return new TestInstrumentType.EmptyInstrumentsState(); + } + + @Override + public void recordValuesInInstruments( + TestInstrumentType.TestInstrumentsState testInstrumentsState, + List attributesList, + Random random) { + // Recording is done by the callback define above + } +} diff --git a/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/LongLastValueTester.java b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/LongLastValueTester.java new file mode 100644 index 00000000000..c766f74e290 --- /dev/null +++ b/sdk/metrics/src/jmhBasedTest/java/io/opentelemetry/sdk/metrics/internal/state/tester/LongLastValueTester.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.state.tester; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.sdk.metrics.Aggregation; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.metrics.internal.state.TestInstrumentType; +import java.util.List; +import java.util.Random; + +public class LongLastValueTester implements TestInstrumentType.InstrumentTester { + + @Override + public Aggregation testedAggregation() { + return Aggregation.lastValue(); + } + + @SuppressWarnings({"ForLoopReplaceableByForEach", "resource"}) + @Override + public TestInstrumentType.TestInstrumentsState buildInstruments( + double instrumentCount, + SdkMeterProvider sdkMeterProvider, + List attributesList, + Random random) { + Meter meter = sdkMeterProvider.meterBuilder("meter").build(); + meter + .gaugeBuilder("test.long.last.value") + .ofLongs() + .buildWithCallback( + observableLongMeasurement -> { + for (int j = 0; j < attributesList.size(); j++) { + observableLongMeasurement.record(1, attributesList.get(j)); + } + }); + + return new TestInstrumentType.EmptyInstrumentsState(); + } + + @Override + public void recordValuesInInstruments( + TestInstrumentType.TestInstrumentsState testInstrumentsState, + List attributesList, + Random random) { + // Recording is done by the callback define above + } +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregator.java index 8f0a622e3af..2063cb212d7 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregator.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.metrics.data.DoublePointData; @@ -42,15 +43,17 @@ public final class DoubleLastValueAggregator implements Aggregator { private final Supplier> reservoirSupplier; + private final MemoryMode memoryMode; public DoubleLastValueAggregator( - Supplier> reservoirSupplier) { + Supplier> reservoirSupplier, MemoryMode memoryMode) { this.reservoirSupplier = reservoirSupplier; + this.memoryMode = memoryMode; } @Override public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get()); + return new Handle(reservoirSupplier.get(), memoryMode); } @Override @@ -114,8 +117,16 @@ static final class Handle extends AggregatorHandle current = new AtomicReference<>(DEFAULT_VALUE); - private Handle(ExemplarReservoir reservoir) { + // Only used when memoryMode is REUSABLE_DATA + @Nullable private final MutableDoublePointData reusablePoint; + + private Handle(ExemplarReservoir reservoir, MemoryMode memoryMode) { super(reservoir); + if (memoryMode == MemoryMode.REUSABLE_DATA) { + reusablePoint = new MutableDoublePointData(); + } else { + reusablePoint = null; + } } @Override @@ -126,8 +137,14 @@ protected DoublePointData doAggregateThenMaybeReset( List exemplars, boolean reset) { Double value = reset ? this.current.getAndSet(DEFAULT_VALUE) : this.current.get(); - return ImmutableDoublePointData.create( - startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + if (reusablePoint != null) { + reusablePoint.set( + startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + return reusablePoint; + } else { + return ImmutableDoublePointData.create( + startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + } } @Override diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregator.java index 5b3064822c9..27422733c43 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregator.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.LongPointData; @@ -39,14 +40,17 @@ */ public final class LongLastValueAggregator implements Aggregator { private final Supplier> reservoirSupplier; + private final MemoryMode memoryMode; - public LongLastValueAggregator(Supplier> reservoirSupplier) { + public LongLastValueAggregator( + Supplier> reservoirSupplier, MemoryMode memoryMode) { this.reservoirSupplier = reservoirSupplier; + this.memoryMode = memoryMode; } @Override public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get()); + return new Handle(reservoirSupplier.get(), memoryMode); } @Override @@ -109,8 +113,16 @@ static final class Handle extends AggregatorHandle current = new AtomicReference<>(DEFAULT_VALUE); - Handle(ExemplarReservoir exemplarReservoir) { + // Only used when memoryMode is REUSABLE_DATA + @Nullable private final MutableLongPointData reusablePoint; + + Handle(ExemplarReservoir exemplarReservoir, MemoryMode memoryMode) { super(exemplarReservoir); + if (memoryMode == MemoryMode.REUSABLE_DATA) { + reusablePoint = new MutableLongPointData(); + } else { + reusablePoint = null; + } } @Override @@ -121,8 +133,15 @@ protected LongPointData doAggregateThenMaybeReset( List exemplars, boolean reset) { Long value = reset ? this.current.getAndSet(DEFAULT_VALUE) : this.current.get(); - return ImmutableLongPointData.create( - startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + + if (reusablePoint != null) { + reusablePoint.set( + startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + return reusablePoint; + } else { + return ImmutableLongPointData.create( + startEpochNanos, epochNanos, attributes, Objects.requireNonNull(value), exemplars); + } } @Override diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/LastValueAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/LastValueAggregation.java index 5a7579f3bf6..7dac6c6241d 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/LastValueAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/LastValueAggregation.java @@ -44,9 +44,11 @@ public Aggregator createAggr // For the initial version we do not sample exemplars on gauges. switch (instrumentDescriptor.getValueType()) { case LONG: - return (Aggregator) new LongLastValueAggregator(ExemplarReservoir::longNoSamples); + return (Aggregator) + new LongLastValueAggregator(ExemplarReservoir::longNoSamples, memoryMode); case DOUBLE: - return (Aggregator) new DoubleLastValueAggregator(ExemplarReservoir::doubleNoSamples); + return (Aggregator) + new DoubleLastValueAggregator(ExemplarReservoir::doubleNoSamples, memoryMode); } throw new IllegalArgumentException("Invalid instrument value type"); } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregatorTest.java index 5f7a276e1e9..b28a8e4879c 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleLastValueAggregatorTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.sdk.metrics.internal.aggregator; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; -import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -14,6 +13,7 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.metrics.data.DoublePointData; @@ -27,6 +27,8 @@ import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; /** Unit tests for {@link AggregatorHandle}. */ class DoubleLastValueAggregatorTest { @@ -35,16 +37,24 @@ class DoubleLastValueAggregatorTest { InstrumentationScopeInfo.empty(); private static final MetricDescriptor METRIC_DESCRIPTOR = MetricDescriptor.create("name", "description", "unit"); - private static final DoubleLastValueAggregator aggregator = - new DoubleLastValueAggregator(ExemplarReservoir::doubleNoSamples); + private DoubleLastValueAggregator aggregator; - @Test - void createHandle() { + private void init(MemoryMode memoryMode) { + aggregator = new DoubleLastValueAggregator(ExemplarReservoir::doubleNoSamples, memoryMode); + } + + @ParameterizedTest + @EnumSource(MemoryMode.class) + void createHandle(MemoryMode memoryMode) { + init(memoryMode); assertThat(aggregator.createHandle()).isInstanceOf(DoubleLastValueAggregator.Handle.class); } - @Test - void multipleRecords() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void multipleRecords(MemoryMode memoryMode) { + init(memoryMode); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordDouble(12.1); @@ -62,8 +72,11 @@ void multipleRecords() { .isEqualTo(14.1); } - @Test - void aggregateThenMaybeReset() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void aggregateThenMaybeReset(MemoryMode memoryMode) { + init(memoryMode); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); @@ -82,8 +95,11 @@ void aggregateThenMaybeReset() { .isEqualTo(12.1); } - @Test - void diff() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void diff(MemoryMode memoryMode) { + init(memoryMode); + Attributes attributes = Attributes.builder().put("test", "value").build(); DoubleExemplarData exemplar = ImmutableDoubleExemplarData.create( @@ -116,8 +132,11 @@ void diff() { .isEqualTo(ImmutableDoublePointData.create(0, 1, Attributes.empty(), 2, exemplars)); } - @Test - void diffInPlace() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void diffInPlace(MemoryMode memoryMode) { + init(memoryMode); + Attributes attributes = Attributes.builder().put("test", "value").build(); DoubleExemplarData exemplar = ImmutableDoubleExemplarData.create( @@ -158,8 +177,11 @@ void diffInPlace() { assertThat(previous.getExemplars()).isEqualTo(exemplars); } - @Test - void copyPoint() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void copyPoint(MemoryMode memoryMode) { + init(memoryMode); + MutableDoublePointData pointData = (MutableDoublePointData) aggregator.createReusablePoint(); Attributes attributes = Attributes.of(AttributeKey.longKey("test"), 100L); @@ -201,8 +223,11 @@ void copyPoint() { assertThat(toPointData.getExemplars()).isEqualTo(pointData.getExemplars()); } - @Test - void toMetricData() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void toMetricData(MemoryMode memoryMode) { + init(memoryMode); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordDouble(10); @@ -230,4 +255,25 @@ void toMetricData() { .hasEpochNanos(100) .hasValue(10))); } + + @Test + void testReusableDataOnCollect() { + init(MemoryMode.REUSABLE_DATA); + AggregatorHandle handle = aggregator.createHandle(); + handle.recordDouble(1); + DoublePointData pointData = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); + + handle.recordDouble(1); + DoublePointData pointData2 = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); + + assertThat(pointData).isSameAs(pointData2); + + handle.recordDouble(1); + DoublePointData pointDataWithReset = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ true); + + assertThat(pointData).isSameAs(pointDataWithReset); + } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregatorTest.java index 0ac5104898f..b9dfc386156 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongLastValueAggregatorTest.java @@ -13,6 +13,7 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.LongPointData; @@ -28,6 +29,8 @@ import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; /** Unit tests for {@link LongLastValueAggregator}. */ class LongLastValueAggregatorTest { @@ -36,16 +39,23 @@ class LongLastValueAggregatorTest { InstrumentationScopeInfo.empty(); private static final MetricDescriptor METRIC_DESCRIPTOR = MetricDescriptor.create("name", "description", "unit"); - private static final LongLastValueAggregator aggregator = - new LongLastValueAggregator(ExemplarReservoir::longNoSamples); + private LongLastValueAggregator aggregator; - @Test - void createHandle() { + private void init(MemoryMode memoryMode) { + aggregator = new LongLastValueAggregator(ExemplarReservoir::longNoSamples, memoryMode); + } + + @ParameterizedTest + @EnumSource(MemoryMode.class) + void createHandle(MemoryMode memoryMode) { + init(memoryMode); assertThat(aggregator.createHandle()).isInstanceOf(LongLastValueAggregator.Handle.class); } - @Test - void multipleRecords() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void multipleRecords(MemoryMode memoryMode) { + init(memoryMode); AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordLong(12); assertThat( @@ -62,8 +72,10 @@ void multipleRecords() { .isEqualTo(14L); } - @Test - void aggregateThenMaybeReset() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void aggregateThenMaybeReset(MemoryMode memoryMode) { + init(memoryMode); AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordLong(13); @@ -81,8 +93,11 @@ void aggregateThenMaybeReset() { .isEqualTo(12L); } - @Test - void diffInPlace() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void diffInPlace(MemoryMode memoryMode) { + init(memoryMode); + Attributes attributes = Attributes.builder().put("test", "value").build(); LongExemplarData exemplar = ImmutableLongExemplarData.create( @@ -123,8 +138,11 @@ void diffInPlace() { assertThat(previous.getExemplars()).isEqualTo(exemplars); } - @Test - void copyPoint() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void copyPoint(MemoryMode memoryMode) { + init(memoryMode); + MutableLongPointData pointData = (MutableLongPointData) aggregator.createReusablePoint(); Attributes attributes = Attributes.of(AttributeKey.longKey("test"), 100L); @@ -166,8 +184,11 @@ void copyPoint() { assertThat(toPointData.getExemplars()).isEqualTo(pointData.getExemplars()); } - @Test - void toMetricData() { + @ParameterizedTest + @EnumSource(MemoryMode.class) + void toMetricData(MemoryMode memoryMode) { + init(memoryMode); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordLong(10); @@ -192,4 +213,24 @@ void toMetricData() { Collections.singletonList( ImmutableLongPointData.create(2, 100, Attributes.empty(), 10))))); } + + @Test + void testReusablePointOnCollect() { + init(MemoryMode.REUSABLE_DATA); + AggregatorHandle handle = aggregator.createHandle(); + handle.recordLong(1); + LongPointData pointData = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); + + handle.recordLong(1); + LongPointData pointData2 = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); + + assertThat(pointData).isSameAs(pointData2); + + LongPointData pointDataWithReset = + handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ true); + + assertThat(pointData).isSameAs(pointDataWithReset); + } }