diff --git a/integration-tests/graal-incubating/build.gradle.kts b/integration-tests/graal-incubating/build.gradle.kts index 2b8dd50434b..cbc1a0ac1a8 100644 --- a/integration-tests/graal-incubating/build.gradle.kts +++ b/integration-tests/graal-incubating/build.gradle.kts @@ -1,5 +1,4 @@ import org.gradle.api.JavaVersion - plugins { id("otel.java-conventions") id("org.graalvm.buildtools.native") diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java index 8fb64ae7f38..eca95a84d7e 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkMeter.java @@ -318,6 +318,7 @@ SdkObservableMeasurement registerObservableMeasurement( registeredView, meterProviderSharedState.getClock(), instrumentDescriptor, + meterProviderSharedState.getExemplarFilter(), meterEnabled))); } } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorage.java index 3b4d1ac585a..aa899b5539f 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorage.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorage.java @@ -15,7 +15,6 @@ import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.common.internal.ThrottlingLogger; -import io.opentelemetry.sdk.metrics.ExemplarFilter; import io.opentelemetry.sdk.metrics.View; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; @@ -106,6 +105,7 @@ public static AsynchronousMetricStorage create( RegisteredView registeredView, Clock clock, InstrumentDescriptor instrumentDescriptor, + ExemplarFilterInternal exemplarFilter, boolean enabled) { View view = registeredView.getView(); MetricDescriptor metricDescriptor = @@ -117,9 +117,7 @@ public static AsynchronousMetricStorage create( Aggregator aggregator = ((AggregatorFactory) view.getAggregation()) .createAggregator( - instrumentDescriptor, - ExemplarFilterInternal.asExemplarFilterInternal(ExemplarFilter.alwaysOff()), - registeredReader.getReader().getMemoryMode()); + instrumentDescriptor, exemplarFilter, registeredReader.getReader().getMemoryMode()); AttributesProcessor attributesProcessor = registeredView.getViewAttributesProcessor(); int cardinalityLimit = registeredView.getCardinalityLimit(); return aggregationTemporality == AggregationTemporality.DELTA diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterProviderSharedState.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterProviderSharedState.java index 0cd4895f068..46dace490df 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterProviderSharedState.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/MeterProviderSharedState.java @@ -37,6 +37,6 @@ public static MeterProviderSharedState create( /** Returns the {@link Resource} to attach telemetry to. */ public abstract Resource getResource(); - /** Returns the {@link ExemplarFilterInternal} for remembering synchronous measurements. */ + /** Returns the {@link ExemplarFilterInternal} for remembering measurements. */ public abstract ExemplarFilterInternal getExemplarFilter(); } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkDoubleGaugeTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkDoubleGaugeTest.java index c39558ce978..ba7ddfdbdbf 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkDoubleGaugeTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkDoubleGaugeTest.java @@ -173,6 +173,65 @@ void collectMetrics_WithExemplars() { .build()))))); } + @Test + void observable_CollectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader reader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .setClock(testClock) + .setResource(RESOURCE) + .registerMetricReader(reader) + .build(); + + sdkMeterProvider + .get(getClass().getName()) + .gaugeBuilder("testGauge") + .buildWithCallback(measurement -> measurement.record(12d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(reader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testGauge") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> point.hasValue(12d).hasExemplars()))); + } + + @Test + void observable_CollectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader reader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .setClock(testClock) + .setResource(RESOURCE) + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(reader) + .build(); + + sdkMeterProvider + .get(getClass().getName()) + .gaugeBuilder("testGauge") + .buildWithCallback(measurement -> measurement.record(12d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(reader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testGauge") + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(12d) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12d))))); + } + @Test void collectMetrics_WithMultipleCollects() { long startTime = testClock.now(); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkLongGaugeTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkLongGaugeTest.java index 98d464a019a..bf74f818a4a 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkLongGaugeTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkLongGaugeTest.java @@ -167,6 +167,66 @@ void collectMetrics_WithExemplars() { .build()))))); } + @Test + void observable_CollectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader reader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .setClock(testClock) + .setResource(RESOURCE) + .registerMetricReader(reader) + .build(); + + sdkMeterProvider + .get(getClass().getName()) + .gaugeBuilder("testGauge") + .ofLongs() + .buildWithCallback(measurement -> measurement.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(reader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testGauge") + .hasLongGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying(point -> point.hasValue(12).hasExemplars()))); + } + + @Test + void observable_CollectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader reader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + SdkMeterProvider.builder() + .setClock(testClock) + .setResource(RESOURCE) + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(reader) + .build(); + + sdkMeterProvider + .get(getClass().getName()) + .gaugeBuilder("testGauge") + .ofLongs() + .buildWithCallback(measurement -> measurement.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(reader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testGauge") + .hasLongGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(12) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12))))); + } + @Test void collectMetrics_WithMultipleCollects() { long startTime = testClock.now(); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkMeterProviderTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkMeterProviderTest.java index d8036a5f724..ffa2a24fea1 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkMeterProviderTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkMeterProviderTest.java @@ -945,6 +945,37 @@ void collectAll_DropAggregator() { metric -> assertThat(metric).hasResource(RESOURCE).hasName("async-counter")); } + @Test + void collectAll_AsyncInstrumentAlwaysOnExemplars() { + InMemoryMetricReader collector = InMemoryMetricReader.create(); + Meter meter = + sdkMeterProviderBuilder + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(collector) + .build() + .get("my-meter"); + + meter + .counterBuilder("async-counter") + .buildWithCallback(measurement -> measurement.record(1, Attributes.empty())); + + assertThat(collector.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasResource(RESOURCE) + .hasName("async-counter") + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(1) + .hasAttributes(Attributes.empty()) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(1))))); + } + @Test void shutdown() { when(metricReader.getDefaultAggregation(any())).thenCallRealMethod(); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleCounterTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleCounterTest.java index cc1c887bf3a..93fa99a5942 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleCounterTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleCounterTest.java @@ -202,4 +202,57 @@ void collectMetrics_DeltaSumAggregator() { .hasValue(0) .hasAttributes(attributeEntry("k", "v"))))); } + + @Test + void collectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder.registerMetricReader(sdkMeterReader).build(); + sdkMeterProvider + .get(getClass().getName()) + .counterBuilder("testObserver") + .ofDoubles() + .buildWithCallback(result -> result.record(12.1d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasDoubleSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> point.hasValue(12.1d).hasExemplars()))); + } + + @Test + void collectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(sdkMeterReader) + .build(); + sdkMeterProvider + .get(getClass().getName()) + .counterBuilder("testObserver") + .ofDoubles() + .buildWithCallback(result -> result.record(12.1d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasDoubleSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(12.1d) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12.1d))))); + } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleUpDownCounterTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleUpDownCounterTest.java index 8b212220093..6ae2b8e9763 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleUpDownCounterTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableDoubleUpDownCounterTest.java @@ -202,4 +202,57 @@ void customAggregationThrows() { .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Custom Aggregation implementations are currently not supported."); } + + @Test + void collectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder.registerMetricReader(sdkMeterReader).build(); + sdkMeterProvider + .get(getClass().getName()) + .upDownCounterBuilder("testObserver") + .ofDoubles() + .buildWithCallback(result -> result.record(12.1d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasDoubleSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> point.hasValue(12.1d).hasExemplars()))); + } + + @Test + void collectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(sdkMeterReader) + .build(); + sdkMeterProvider + .get(getClass().getName()) + .upDownCounterBuilder("testObserver") + .ofDoubles() + .buildWithCallback(result -> result.record(12.1d, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasDoubleSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(12.1d) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12.1d))))); + } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongCounterTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongCounterTest.java index f4208b1c26d..4ff6e09e546 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongCounterTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongCounterTest.java @@ -168,4 +168,54 @@ void collectMetrics_DeltaSumAggregator() { .hasValue(0) .hasAttributes(attributeEntry("k", "v"))))); } + + @Test + void collectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder.registerMetricReader(sdkMeterReader).build(); + sdkMeterProvider + .get(getClass().getName()) + .counterBuilder("testObserver") + .buildWithCallback(result -> result.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying(point -> point.hasValue(12).hasExemplars()))); + } + + @Test + void collectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(sdkMeterReader) + .build(); + sdkMeterProvider + .get(getClass().getName()) + .counterBuilder("testObserver") + .buildWithCallback(result -> result.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(12) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12))))); + } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongUpDownCounterTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongUpDownCounterTest.java index 33c3c17167d..b316bc8c6e0 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongUpDownCounterTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/SdkObservableLongUpDownCounterTest.java @@ -170,4 +170,54 @@ void collectMetrics_DeltaSumAggregator() { .hasValue(0) .hasAttributes(attributeEntry("k", "v"))))); } + + @Test + void collectMetrics_DefaultExemplarFilter_NoExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder.registerMetricReader(sdkMeterReader).build(); + sdkMeterProvider + .get(getClass().getName()) + .upDownCounterBuilder("testObserver") + .buildWithCallback(result -> result.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying(point -> point.hasValue(12).hasExemplars()))); + } + + @Test + void collectMetrics_AlwaysOnExemplarFilter_CollectsExemplars() { + InMemoryMetricReader sdkMeterReader = InMemoryMetricReader.create(); + SdkMeterProvider sdkMeterProvider = + sdkMeterProviderBuilder + .setExemplarFilter(ExemplarFilter.alwaysOn()) + .registerMetricReader(sdkMeterReader) + .build(); + sdkMeterProvider + .get(getClass().getName()) + .upDownCounterBuilder("testObserver") + .buildWithCallback(result -> result.record(12, Attributes.empty())); + + testClock.advance(Duration.ofNanos(SECOND_NANOS)); + assertThat(sdkMeterReader.collectAllMetrics()) + .satisfiesExactly( + metric -> + assertThat(metric) + .hasName("testObserver") + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(12) + .hasExemplarsSatisfying( + exemplar -> exemplar.hasValue(12))))); + } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorageTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorageTest.java index 4ad556422b5..e16c61fbb34 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorageTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/AsynchronousMetricStorageTest.java @@ -6,6 +6,7 @@ package io.opentelemetry.sdk.metrics.internal.state; import static io.opentelemetry.sdk.common.export.MemoryMode.REUSABLE_DATA; +import static io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilterInternal.asExemplarFilterInternal; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; import static org.mockito.ArgumentMatchers.any; @@ -16,6 +17,7 @@ import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.metrics.ExemplarFilter; import io.opentelemetry.sdk.metrics.InstrumentSelector; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.InstrumentValueType; @@ -76,10 +78,15 @@ class AsynchronousMetricStorageTest { // Not using @BeforeEach since many methods require executing them for each MemoryMode void setup(MemoryMode memoryMode) { - setup(memoryMode, AggregationTemporality.CUMULATIVE); + setup(memoryMode, AggregationTemporality.CUMULATIVE, ExemplarFilter.alwaysOff()); } void setup(MemoryMode memoryMode, AggregationTemporality temporality) { + setup(memoryMode, temporality, ExemplarFilter.alwaysOff()); + } + + void setup( + MemoryMode memoryMode, AggregationTemporality temporality, ExemplarFilter exemplarFilter) { when(reader.getAggregationTemporality(any())).thenReturn(temporality); when(reader.getMemoryMode()).thenReturn(memoryMode); registeredReader = RegisteredReader.create(reader, ViewRegistry.create()); @@ -96,6 +103,7 @@ void setup(MemoryMode memoryMode, AggregationTemporality temporality) { InstrumentType.COUNTER, InstrumentValueType.LONG, Advice.empty()), + asExemplarFilterInternal(exemplarFilter), /* enabled= */ true); doubleCounterStorage = AsynchronousMetricStorage.create( @@ -109,6 +117,7 @@ void setup(MemoryMode memoryMode, AggregationTemporality temporality) { InstrumentType.COUNTER, InstrumentValueType.DOUBLE, Advice.empty()), + asExemplarFilterInternal(exemplarFilter), /* enabled= */ true); } @@ -186,6 +195,7 @@ void record_ProcessesAttributes(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.LONG, Advice.empty()), + asExemplarFilterInternal(ExemplarFilter.alwaysOff()), /* enabled= */ true); storage.record(Attributes.builder().put("key1", "a").put("key2", "b").build(), 1); @@ -421,6 +431,7 @@ void collect_DeltaComputesDiff(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.LONG, Advice.empty()), + asExemplarFilterInternal(ExemplarFilter.alwaysOff()), /* enabled= */ true); // Record measurement and collect at time 10 @@ -482,6 +493,24 @@ void collect_DeltaComputesDiff(MemoryMode memoryMode) { .hasAttributes(Attributes.builder().put("key", "value2").build()))); } + @ParameterizedTest + @EnumSource(MemoryMode.class) + void recordLong_AlwaysOnCollectsExemplars(MemoryMode memoryMode) { + setup(memoryMode, AggregationTemporality.CUMULATIVE, ExemplarFilter.alwaysOn()); + + longCounterStorage.record(Attributes.empty(), 3); + + assertThat(longCounterStorage.collect(resource, scope, testClock.now())) + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point + .hasValue(3) + .hasAttributes(Attributes.empty()) + .hasExemplarsSatisfying(exemplar -> exemplar.hasValue(3)))); + } + @Test void collect_reusableData_reusedObjectsAreReturnedOnSecondCall() { setup(REUSABLE_DATA);