diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt index 4b43b12506f..ba34d454891 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-api-1.56.0-SNAPSHOT.jar against opentelemetry-api-1.54.1.jar +Comparing source compatibility of opentelemetry-api-1.56.0-SNAPSHOT.jar against opentelemetry-api-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-common.txt index 2663241ba31..8ca3abc2afd 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-common.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-common.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-common-1.56.0-SNAPSHOT.jar against opentelemetry-common-1.54.1.jar +Comparing source compatibility of opentelemetry-common-1.56.0-SNAPSHOT.jar against opentelemetry-common-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-context.txt b/docs/apidiffs/current_vs_latest/opentelemetry-context.txt index 828dc866aae..1959839abd4 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-context.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-context.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-context-1.56.0-SNAPSHOT.jar against opentelemetry-context-1.54.1.jar +Comparing source compatibility of opentelemetry-context-1.56.0-SNAPSHOT.jar against opentelemetry-context-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt index 9a4514ad34b..1eb8f8c1c0b 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-common.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-common-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-common-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-common-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-common-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt index 6a158ec6bbe..bd074fc65f1 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging-otlp.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-logging-otlp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-logging-otlp-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-logging-otlp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-logging-otlp-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt index 518843e42ea..b41867e243e 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-logging.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-logging-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-logging-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-logging-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-logging-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt index 9d43aaae666..5849b9ea3fc 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp-common.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-otlp-common-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-common-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-otlp-common-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-common-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt index 194f62cb30a..3bb32b11ec2 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-otlp.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-otlp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-otlp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-otlp-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt index 5fa56b9bde3..38ef8e6c4fe 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-grpc-managed-channel.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-sender-grpc-managed-channel-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-grpc-managed-channel-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-sender-grpc-managed-channel-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-grpc-managed-channel-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt index 0d989cf5932..e6af68eb46d 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-jdk.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-sender-jdk-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-jdk-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-sender-jdk-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-jdk-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt index 30a76bac9c2..6e8b5256aff 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-sender-okhttp.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-sender-okhttp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-okhttp-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-sender-okhttp-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-sender-okhttp-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt index 162c16b7bbf..a2f37d685c0 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-zipkin.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-exporter-zipkin-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-zipkin-1.54.1.jar +Comparing source compatibility of opentelemetry-exporter-zipkin-1.56.0-SNAPSHOT.jar against opentelemetry-exporter-zipkin-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt b/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt index 656ee291a1d..8512828d48c 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-extension-kotlin.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-extension-kotlin-1.56.0-SNAPSHOT.jar against opentelemetry-extension-kotlin-1.54.1.jar +Comparing source compatibility of opentelemetry-extension-kotlin-1.56.0-SNAPSHOT.jar against opentelemetry-extension-kotlin-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt b/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt index ab1e1427cd3..26f41fdafdb 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-extension-trace-propagators.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-extension-trace-propagators-1.56.0-SNAPSHOT.jar against opentelemetry-extension-trace-propagators-1.54.1.jar +Comparing source compatibility of opentelemetry-extension-trace-propagators-1.56.0-SNAPSHOT.jar against opentelemetry-extension-trace-propagators-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt b/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt index 5b06fc3a197..0be3d9eefee 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-opentracing-shim.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-opentracing-shim-1.56.0-SNAPSHOT.jar against opentelemetry-opentracing-shim-1.54.1.jar +Comparing source compatibility of opentelemetry-opentracing-shim-1.56.0-SNAPSHOT.jar against opentelemetry-opentracing-shim-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt index f2ba7fc5251..639554a6e58 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-common.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-common-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-common-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-common-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt index 20c17bcbb7c..7fd1c4bcfce 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure-spi.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-spi-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-spi-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-spi-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-spi-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt index 611da779512..bf17f02c5b3 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-autoconfigure.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-extension-autoconfigure-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-autoconfigure-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt index 17da481d9bf..2de6ddafb3f 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt index 865c32e701d..4541c4953d3 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-logs.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-logs-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-logs-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-logs-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-logs-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt index a1448718402..a97cc879eb4 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-metrics-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-metrics-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt index 07fe03036b4..9cf277814a7 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-testing.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-testing-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-testing-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-testing-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt index 349fd2cd635..5f7f1e832ac 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-trace-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.54.1.jar +Comparing source compatibility of opentelemetry-sdk-trace-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.55.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt index 95eb5961689..cd4c0cf7107 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk.txt @@ -1,10 +1,2 @@ -Comparing source compatibility of opentelemetry-sdk-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-1.54.1.jar -*** MODIFIED CLASS: PUBLIC NON_FINAL (<- FINAL) io.opentelemetry.sdk.OpenTelemetrySdk (not serializable) - === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.api.logs.LoggerProvider getLogsBridge() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.api.metrics.MeterProvider getMeterProvider() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.context.propagation.ContextPropagators getPropagators() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.sdk.logs.SdkLoggerProvider getSdkLoggerProvider() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.sdk.metrics.SdkMeterProvider getSdkMeterProvider() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.sdk.trace.SdkTracerProvider getSdkTracerProvider() - *** MODIFIED METHOD: PUBLIC FINAL (<- NON_FINAL) io.opentelemetry.api.trace.TracerProvider getTracerProvider() +Comparing source compatibility of opentelemetry-sdk-1.56.0-SNAPSHOT.jar against opentelemetry-sdk-1.55.0.jar +No changes. \ No newline at end of file diff --git a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramAggregationParam.java b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramAggregationParam.java index 162794f52d8..71bf89803cc 100644 --- a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramAggregationParam.java +++ b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramAggregationParam.java @@ -7,7 +7,7 @@ import static io.opentelemetry.sdk.common.export.MemoryMode.IMMUTABLE_DATA; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import java.util.Collections; /** The types of histogram aggregation to benchmark. */ @@ -17,27 +17,27 @@ public enum HistogramAggregationParam { new DoubleExplicitBucketHistogramAggregator( ExplicitBucketHistogramUtils.createBoundaryArray( ExplicitBucketHistogramUtils.DEFAULT_HISTOGRAM_BUCKET_BOUNDARIES), - ExemplarReservoir::doubleNoSamples, + ExemplarReservoirFactory.noSamples(), IMMUTABLE_DATA)), EXPLICIT_SINGLE_BUCKET( new DoubleExplicitBucketHistogramAggregator( ExplicitBucketHistogramUtils.createBoundaryArray(Collections.emptyList()), - ExemplarReservoir::doubleNoSamples, + ExemplarReservoirFactory.noSamples(), IMMUTABLE_DATA)), EXPONENTIAL_SMALL_CIRCULAR_BUFFER( new DoubleBase2ExponentialHistogramAggregator( - ExemplarReservoir::doubleNoSamples, 20, 0, IMMUTABLE_DATA)), + ExemplarReservoirFactory.noSamples(), 20, 0, IMMUTABLE_DATA)), EXPONENTIAL_CIRCULAR_BUFFER( new DoubleBase2ExponentialHistogramAggregator( - ExemplarReservoir::doubleNoSamples, 160, 0, IMMUTABLE_DATA)); + ExemplarReservoirFactory.noSamples(), 160, 0, IMMUTABLE_DATA)); - private final Aggregator aggregator; + private final Aggregator aggregator; - HistogramAggregationParam(Aggregator aggregator) { + HistogramAggregationParam(Aggregator aggregator) { this.aggregator = aggregator; } - public Aggregator getAggregator() { + public Aggregator getAggregator() { return this.aggregator; } } diff --git a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramBenchmark.java b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramBenchmark.java index a86bf733259..436eeb9bbb1 100644 --- a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramBenchmark.java +++ b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramBenchmark.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.internal.aggregator; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; import java.util.concurrent.TimeUnit; import java.util.function.DoubleSupplier; import org.openjdk.jmh.annotations.Benchmark; @@ -33,7 +35,7 @@ public class HistogramBenchmark { public static class ThreadState { @Param HistogramValueGenerator valueGen; @Param HistogramAggregationParam aggregation; - private AggregatorHandle aggregatorHandle; + private AggregatorHandle aggregatorHandle; private DoubleSupplier valueSupplier; @Setup(Level.Trial) @@ -45,7 +47,8 @@ public final void setup() { public void record() { // Record a number of samples. for (int i = 0; i < 2000; i++) { - this.aggregatorHandle.recordDouble(valueSupplier.getAsDouble()); + this.aggregatorHandle.recordDouble( + valueSupplier.getAsDouble(), Attributes.empty(), Context.current()); } } } diff --git a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramScaleBenchmark.java b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramScaleBenchmark.java index ab2bc6b57c7..456e8e9fd94 100644 --- a/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramScaleBenchmark.java +++ b/sdk/metrics/src/jmh/java/io/opentelemetry/sdk/metrics/internal/aggregator/HistogramScaleBenchmark.java @@ -5,6 +5,8 @@ package io.opentelemetry.sdk.metrics.internal.aggregator; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; import java.util.concurrent.TimeUnit; import java.util.function.DoubleSupplier; import org.openjdk.jmh.annotations.Benchmark; @@ -39,7 +41,7 @@ public class HistogramScaleBenchmark { public static class ThreadState { @Param HistogramValueGenerator valueGen; @Param HistogramAggregationParam aggregation; - private AggregatorHandle aggregatorHandle; + private AggregatorHandle aggregatorHandle; private DoubleSupplier valueSupplier; @Setup(Level.Invocation) @@ -51,7 +53,8 @@ public final void setup() { public void record() { // Record a number of samples. for (int i = 0; i < 20000; i++) { - this.aggregatorHandle.recordDouble(valueSupplier.getAsDouble()); + this.aggregatorHandle.recordDouble( + valueSupplier.getAsDouble(), Attributes.empty(), Context.current()); } } } 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 b31b3721428..525506725b3 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 @@ -304,7 +304,7 @@ WriteableMetricStorage registerSynchronousMetricStorage(InstrumentDescriptor ins /** Register new asynchronous storage associated with a given instrument. */ SdkObservableMeasurement registerObservableMeasurement( InstrumentDescriptor instrumentDescriptor) { - List> registeredStorages = new ArrayList<>(); + List> registeredStorages = new ArrayList<>(); for (Map.Entry entry : readerStorageRegistries.entrySet()) { RegisteredReader reader = entry.getKey(); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AbstractSumAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AbstractSumAggregator.java index 612219a2836..a7574254408 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AbstractSumAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AbstractSumAggregator.java @@ -11,7 +11,7 @@ import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; abstract class AbstractSumAggregator - implements Aggregator { + implements Aggregator { private final boolean isMonotonic; AbstractSumAggregator(InstrumentDescriptor instrumentDescriptor) { diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/Aggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/Aggregator.java index db167bab5b4..79492f61c66 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/Aggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/Aggregator.java @@ -7,8 +7,6 @@ import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.MetricDataType; import io.opentelemetry.sdk.metrics.data.PointData; @@ -25,9 +23,9 @@ * at any time. */ @Immutable -public interface Aggregator { +public interface Aggregator { /** Returns the drop aggregator, an aggregator that drops measurements. */ - static Aggregator drop() { + static Aggregator drop() { return DropAggregator.INSTANCE; } @@ -37,7 +35,7 @@ static Aggregator drop() { * * @return a new {@link AggregatorHandle}. */ - AggregatorHandle createHandle(); + AggregatorHandle createHandle(); /** * Returns a new DELTA point by computing the difference between two cumulative points. diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorFactory.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorFactory.java index 071df0fca81..8c5941acba3 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorFactory.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorFactory.java @@ -6,7 +6,6 @@ package io.opentelemetry.sdk.metrics.internal.aggregator; import io.opentelemetry.sdk.common.export.MemoryMode; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; @@ -31,7 +30,7 @@ public interface AggregatorFactory { * @return a new {@link Aggregator}. {@link Aggregator#drop()} indicates no measurements should be * recorded. */ - Aggregator createAggregator( + Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandle.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandle.java index 2bf7c8c4db6..8a88082b456 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandle.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandle.java @@ -7,10 +7,14 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.metrics.data.ExemplarData; +import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; +import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import java.util.List; +import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; /** @@ -24,14 +28,28 @@ * at any time. */ @ThreadSafe -public abstract class AggregatorHandle { +public abstract class AggregatorHandle { + + private static final String UNSUPPORTED_LONG_MESSAGE = + "This aggregator does not support long values."; + private static final String UNSUPPORTED_DOUBLE_MESSAGE = + "This aggregator does not support double values."; // A reservoir of sampled exemplars for this time period. - private final ExemplarReservoir exemplarReservoir; + @Nullable private final DoubleExemplarReservoir doubleReservoirFactory; + @Nullable private final LongExemplarReservoir longReservoirFactory; + private final boolean isDoubleType; private volatile boolean valuesRecorded = false; - protected AggregatorHandle(ExemplarReservoir exemplarReservoir) { - this.exemplarReservoir = exemplarReservoir; + protected AggregatorHandle(ExemplarReservoirFactory reservoirFactory) { + this.isDoubleType = isDoubleType(); + if (isDoubleType) { + this.doubleReservoirFactory = reservoirFactory.createDoubleExemplarReservoir(); + this.longReservoirFactory = null; + } else { + this.doubleReservoirFactory = null; + this.longReservoirFactory = reservoirFactory.createLongExemplarReservoir(); + } } /** @@ -44,35 +62,60 @@ public final T aggregateThenMaybeReset( valuesRecorded = false; } - return doAggregateThenMaybeReset( + if (isDoubleType) { + return doAggregateThenMaybeResetDoubles( + startEpochNanos, + epochNanos, + attributes, + throwUnsupportedIfNull(this.doubleReservoirFactory, UNSUPPORTED_DOUBLE_MESSAGE) + .collectAndResetDoubles(attributes), + reset); + } + return doAggregateThenMaybeResetLongs( startEpochNanos, epochNanos, attributes, - exemplarReservoir.collectAndReset(attributes), + throwUnsupportedIfNull(this.longReservoirFactory, UNSUPPORTED_LONG_MESSAGE) + .collectAndResetLongs(attributes), reset); } + /** + * Indicates whether this {@link AggregatorHandle} supports double or long values. + * + *

If it supports doubles, it MUST implement {@link #doAggregateThenMaybeResetDoubles(long, + * long, Attributes, List, boolean)} and {@link #doRecordDouble(double)}. + * + *

If it supports long, it MUST implement {@link #doAggregateThenMaybeResetLongs(long, long, + * Attributes, List, boolean)} and {@link #doRecordLong(long)}. + * + * @return true if it supports doubles, false if it supports longs. + */ + protected abstract boolean isDoubleType(); + /** Implementation of the {@link #aggregateThenMaybeReset(long, long, Attributes, boolean)} . */ - protected abstract T doAggregateThenMaybeReset( + protected T doAggregateThenMaybeResetDoubles( long startEpochNanos, long epochNanos, Attributes attributes, - List exemplars, - boolean reset); + List exemplars, + boolean reset) { + throw new UnsupportedOperationException(UNSUPPORTED_DOUBLE_MESSAGE); + } - public final void recordLong(long value, Attributes attributes, Context context) { - exemplarReservoir.offerLongMeasurement(value, attributes, context); - recordLong(value); + /** Implementation of the {@link #aggregateThenMaybeReset(long, long, Attributes, boolean)} . */ + protected T doAggregateThenMaybeResetLongs( + long startEpochNanos, + long epochNanos, + Attributes attributes, + List exemplars, + boolean reset) { + throw new UnsupportedOperationException(UNSUPPORTED_LONG_MESSAGE); } - /** - * Updates the current aggregator with a newly recorded {@code long} value. - * - *

Visible for Testing - * - * @param value the new {@code long} value to be added. - */ - public final void recordLong(long value) { + public void recordLong(long value, Attributes attributes, Context context) { + throwUnsupportedIfNull(this.longReservoirFactory, UNSUPPORTED_LONG_MESSAGE) + .offerLongMeasurement(value, attributes, context); doRecordLong(value); valuesRecorded = true; } @@ -82,23 +125,12 @@ public final void recordLong(long value) { * values. */ protected void doRecordLong(long value) { - throw new UnsupportedOperationException( - "This aggregator does not support recording long values."); + throw new UnsupportedOperationException("This aggregator does not support long values."); } public final void recordDouble(double value, Attributes attributes, Context context) { - exemplarReservoir.offerDoubleMeasurement(value, attributes, context); - recordDouble(value); - } - - /** - * Updates the current aggregator with a newly recorded {@code double} value. - * - *

Visible for Testing - * - * @param value the new {@code double} value to be added. - */ - public final void recordDouble(double value) { + throwUnsupportedIfNull(this.doubleReservoirFactory, UNSUPPORTED_DOUBLE_MESSAGE) + .offerDoubleMeasurement(value, attributes, context); doRecordDouble(value); valuesRecorded = true; } @@ -108,8 +140,7 @@ public final void recordDouble(double value) { * double values. */ protected void doRecordDouble(double value) { - throw new UnsupportedOperationException( - "This aggregator does not support recording double values."); + throw new UnsupportedOperationException(UNSUPPORTED_DOUBLE_MESSAGE); } /** @@ -120,4 +151,11 @@ protected void doRecordDouble(double value) { public boolean hasRecordedValues() { return valuesRecorded; } + + private static S throwUnsupportedIfNull(@Nullable S value, String message) { + if (value == null) { + throw new UnsupportedOperationException(message); + } + return value; + } } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregator.java index 18b5b60ee4b..d6ff832f4af 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregator.java @@ -6,6 +6,7 @@ package io.opentelemetry.sdk.metrics.internal.aggregator; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.DynamicPrimitiveLongList; @@ -21,11 +22,10 @@ import io.opentelemetry.sdk.metrics.internal.data.MutableExponentialHistogramBuckets; import io.opentelemetry.sdk.metrics.internal.data.MutableExponentialHistogramPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collection; import java.util.List; -import java.util.function.Supplier; import javax.annotation.Nullable; /** @@ -35,9 +35,9 @@ * at any time. */ public final class DoubleBase2ExponentialHistogramAggregator - implements Aggregator { + implements Aggregator { - private final Supplier> reservoirSupplier; + private final ExemplarReservoirFactory reservoirFactory; private final int maxBuckets; private final int maxScale; private final MemoryMode memoryMode; @@ -45,22 +45,22 @@ public final class DoubleBase2ExponentialHistogramAggregator /** * Constructs an exponential histogram aggregator. * - * @param reservoirSupplier Supplier of exemplar reservoirs per-stream. + * @param reservoirFactory Supplier of exemplar reservoirs per-stream. */ public DoubleBase2ExponentialHistogramAggregator( - Supplier> reservoirSupplier, + ExemplarReservoirFactory reservoirFactory, int maxBuckets, int maxScale, MemoryMode memoryMode) { - this.reservoirSupplier = reservoirSupplier; + this.reservoirFactory = reservoirFactory; this.maxBuckets = maxBuckets; this.maxScale = maxScale; this.memoryMode = memoryMode; } @Override - public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get(), maxBuckets, maxScale, memoryMode); + public AggregatorHandle createHandle() { + return new Handle(reservoirFactory, maxBuckets, maxScale, memoryMode); } @Override @@ -79,8 +79,7 @@ public MetricData toMetricData( ImmutableExponentialHistogramData.create(temporality, points)); } - static final class Handle - extends AggregatorHandle { + static final class Handle extends AggregatorHandle { private final int maxBuckets; private final int maxScale; @Nullable private DoubleBase2ExponentialHistogramBuckets positiveBuckets; @@ -97,11 +96,11 @@ static final class Handle @Nullable private final MutableExponentialHistogramPointData reusablePoint; Handle( - ExemplarReservoir reservoir, + ExemplarReservoirFactory reservoirFactory, int maxBuckets, int maxScale, MemoryMode memoryMode) { - super(reservoir); + super(reservoirFactory); this.maxBuckets = maxBuckets; this.maxScale = maxScale; this.sum = 0; @@ -118,7 +117,7 @@ static final class Handle } @Override - protected synchronized ExponentialHistogramPointData doAggregateThenMaybeReset( + protected synchronized ExponentialHistogramPointData doAggregateThenMaybeResetDoubles( long startEpochNanos, long epochNanos, Attributes attributes, @@ -262,8 +261,16 @@ protected synchronized void doRecordDouble(double value) { } @Override - protected void doRecordLong(long value) { - doRecordDouble((double) value); + protected boolean isDoubleType() { + return true; + } + + @Override + public void recordLong(long value, Attributes attributes, Context context) { + // Since there is no LongExplicitBucketHistogramAggregator and we need to support measurements + // from LongHistogram, we redirect calls from #recordLong to #recordDouble. Without this, the + // base AggregatorHandle implementation of #recordLong throws. + super.recordDouble((double) value, attributes, context); } void downScale(int by) { diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregator.java index 82d71f25313..f98ba0e622c 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregator.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.internal.GuardedBy; +import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.PrimitiveLongList; @@ -19,14 +20,13 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; import io.opentelemetry.sdk.metrics.internal.data.MutableHistogramPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.function.Supplier; import javax.annotation.Nullable; /** @@ -36,26 +36,24 @@ * at any time. */ public final class DoubleExplicitBucketHistogramAggregator - implements Aggregator { + implements Aggregator { private final double[] boundaries; private final MemoryMode memoryMode; // a cache for converting to MetricData private final List boundaryList; - private final Supplier> reservoirSupplier; + private final ExemplarReservoirFactory reservoirFactory; /** * Constructs an explicit bucket histogram aggregator. * * @param boundaries Bucket boundaries, in-order. - * @param reservoirSupplier Supplier of exemplar reservoirs per-stream. + * @param reservoirFactory Supplier of exemplar reservoirs per-stream. * @param memoryMode The {@link MemoryMode} to use in this aggregator. */ public DoubleExplicitBucketHistogramAggregator( - double[] boundaries, - Supplier> reservoirSupplier, - MemoryMode memoryMode) { + double[] boundaries, ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { this.boundaries = boundaries; this.memoryMode = memoryMode; @@ -64,12 +62,12 @@ public DoubleExplicitBucketHistogramAggregator( boundaryList.add(v); } this.boundaryList = Collections.unmodifiableList(boundaryList); - this.reservoirSupplier = reservoirSupplier; + this.reservoirFactory = reservoirFactory; } @Override - public AggregatorHandle createHandle() { - return new Handle(this.boundaryList, this.boundaries, reservoirSupplier.get(), memoryMode); + public AggregatorHandle createHandle() { + return new Handle(boundaryList, boundaries, reservoirFactory, memoryMode); } @Override @@ -88,7 +86,7 @@ public MetricData toMetricData( ImmutableHistogramData.create(temporality, pointData)); } - static final class Handle extends AggregatorHandle { + static final class Handle extends AggregatorHandle { // read-only private final List boundaryList; // read-only @@ -117,9 +115,9 @@ static final class Handle extends AggregatorHandle boundaryList, double[] boundaries, - ExemplarReservoir reservoir, + ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { - super(reservoir); + super(reservoirFactory); this.boundaryList = boundaryList; this.boundaries = boundaries; this.counts = new long[this.boundaries.length + 1]; @@ -133,7 +131,20 @@ static final class Handle extends AggregatorHandle { - private final Supplier> reservoirSupplier; +public final class DoubleLastValueAggregator implements Aggregator { + private final ExemplarReservoirFactory reservoirFactory; private final MemoryMode memoryMode; public DoubleLastValueAggregator( - Supplier> reservoirSupplier, MemoryMode memoryMode) { - this.reservoirSupplier = reservoirSupplier; + ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + this.reservoirFactory = reservoirFactory; this.memoryMode = memoryMode; } @Override - public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get(), memoryMode); + public AggregatorHandle createHandle() { + return new Handle(reservoirFactory, memoryMode); } @Override @@ -94,15 +92,15 @@ public MetricData toMetricData( ImmutableGaugeData.create(points)); } - static final class Handle extends AggregatorHandle { + static final class Handle extends AggregatorHandle { private final AtomicReference current = new AtomicReference<>(null); private final AtomicLong valueBits = new AtomicLong(); // Only used when memoryMode is REUSABLE_DATA @Nullable private final MutableDoublePointData reusablePoint; - private Handle(ExemplarReservoir reservoir, MemoryMode memoryMode) { - super(reservoir); + private Handle(ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + super(reservoirFactory); if (memoryMode == MemoryMode.REUSABLE_DATA) { reusablePoint = new MutableDoublePointData(); } else { @@ -111,7 +109,7 @@ private Handle(ExemplarReservoir reservoir, MemoryMode memor } @Override - protected DoublePointData doAggregateThenMaybeReset( + protected DoublePointData doAggregateThenMaybeResetDoubles( long startEpochNanos, long epochNanos, Attributes attributes, @@ -129,6 +127,11 @@ protected DoublePointData doAggregateThenMaybeReset( } } + @Override + protected boolean isDoubleType() { + return true; + } + @Override protected void doRecordDouble(double value) { valueBits.set(Double.doubleToLongBits(value)); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregator.java index c0701d7e0ec..2af43ffd559 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregator.java @@ -20,11 +20,10 @@ import io.opentelemetry.sdk.metrics.internal.data.MutableDoublePointData; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collection; import java.util.List; -import java.util.function.Supplier; import javax.annotation.Nullable; /** @@ -35,29 +34,29 @@ */ public final class DoubleSumAggregator extends AbstractSumAggregator { - private final Supplier> reservoirSupplier; + private final ExemplarReservoirFactory reservoirFactory; private final MemoryMode memoryMode; /** * Constructs a sum aggregator. * * @param instrumentDescriptor The instrument being recorded, used to compute monotonicity. - * @param reservoirSupplier Supplier of exemplar reservoirs per-stream. + * @param reservoirFactory Supplier of exemplar reservoirs per-stream. * @param memoryMode The memory mode to use. */ public DoubleSumAggregator( InstrumentDescriptor instrumentDescriptor, - Supplier> reservoirSupplier, + ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { super(instrumentDescriptor); - this.reservoirSupplier = reservoirSupplier; + this.reservoirFactory = reservoirFactory; this.memoryMode = memoryMode; } @Override - public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get(), memoryMode); + public AggregatorHandle createHandle() { + return new Handle(reservoirFactory, memoryMode); } @Override @@ -107,19 +106,24 @@ public MetricData toMetricData( ImmutableSumData.create(isMonotonic(), temporality, points)); } - static final class Handle extends AggregatorHandle { + static final class Handle extends AggregatorHandle { private final DoubleAdder current = AdderUtil.createDoubleAdder(); // Only used if memoryMode == MemoryMode.REUSABLE_DATA @Nullable private final MutableDoublePointData reusablePoint; - Handle(ExemplarReservoir exemplarReservoir, MemoryMode memoryMode) { - super(exemplarReservoir); + Handle(ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + super(reservoirFactory); reusablePoint = memoryMode == MemoryMode.REUSABLE_DATA ? new MutableDoublePointData() : null; } @Override - protected DoublePointData doAggregateThenMaybeReset( + protected boolean isDoubleType() { + return true; + } + + @Override + protected DoublePointData doAggregateThenMaybeResetDoubles( long startEpochNanos, long epochNanos, Attributes attributes, diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DropAggregator.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DropAggregator.java index 28336b8fb4a..935655ca789 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DropAggregator.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/aggregator/DropAggregator.java @@ -13,7 +13,7 @@ import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collection; import java.util.Collections; @@ -25,7 +25,7 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public final class DropAggregator implements Aggregator { +public final class DropAggregator implements Aggregator { private static final PointData POINT_DATA = new PointData() { @@ -50,12 +50,17 @@ public List getExemplars() { } }; - public static final Aggregator INSTANCE = new DropAggregator(); + public static final Aggregator INSTANCE = new DropAggregator(); - private static final AggregatorHandle HANDLE = - new AggregatorHandle(ExemplarReservoir.doubleNoSamples()) { + private static final AggregatorHandle HANDLE = + new AggregatorHandle(ExemplarReservoirFactory.noSamples()) { @Override - protected PointData doAggregateThenMaybeReset( + protected boolean isDoubleType() { + return true; + } + + @Override + protected PointData doAggregateThenMaybeResetDoubles( long startEpochNanos, long epochNanos, Attributes attributes, @@ -74,7 +79,7 @@ protected void doRecordDouble(double value) {} private DropAggregator() {} @Override - public AggregatorHandle createHandle() { + public AggregatorHandle createHandle() { return HANDLE; } 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 e5a8d67682d..45a22880bd2 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 @@ -17,13 +17,12 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; import io.opentelemetry.sdk.metrics.internal.data.MutableLongPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import javax.annotation.Nullable; /** @@ -37,19 +36,18 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public final class LongLastValueAggregator implements Aggregator { - private final Supplier> reservoirSupplier; +public final class LongLastValueAggregator implements Aggregator { + private final ExemplarReservoirFactory reservoirFactory; private final MemoryMode memoryMode; - public LongLastValueAggregator( - Supplier> reservoirSupplier, MemoryMode memoryMode) { - this.reservoirSupplier = reservoirSupplier; + public LongLastValueAggregator(ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + this.reservoirFactory = reservoirFactory; this.memoryMode = memoryMode; } @Override - public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get(), memoryMode); + public AggregatorHandle createHandle() { + return new Handle(reservoirFactory, memoryMode); } @Override @@ -89,15 +87,15 @@ public MetricData toMetricData( ImmutableGaugeData.create(points)); } - static final class Handle extends AggregatorHandle { + static final class Handle extends AggregatorHandle { @Nullable private static final Long DEFAULT_VALUE = null; private final AtomicReference current = new AtomicReference<>(DEFAULT_VALUE); // Only used when memoryMode is REUSABLE_DATA @Nullable private final MutableLongPointData reusablePoint; - Handle(ExemplarReservoir exemplarReservoir, MemoryMode memoryMode) { - super(exemplarReservoir); + Handle(ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + super(reservoirFactory); if (memoryMode == MemoryMode.REUSABLE_DATA) { reusablePoint = new MutableLongPointData(); } else { @@ -106,7 +104,12 @@ static final class Handle extends AggregatorHandle { - private final Supplier> reservoirSupplier; + private final ExemplarReservoirFactory reservoirFactory; private final MemoryMode memoryMode; public LongSumAggregator( InstrumentDescriptor instrumentDescriptor, - Supplier> reservoirSupplier, + ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { super(instrumentDescriptor); - this.reservoirSupplier = reservoirSupplier; + this.reservoirFactory = reservoirFactory; this.memoryMode = memoryMode; } @Override - public AggregatorHandle createHandle() { - return new Handle(reservoirSupplier.get(), memoryMode); + public AggregatorHandle createHandle() { + return new Handle(reservoirFactory, memoryMode); } @Override @@ -100,20 +99,20 @@ public MetricData toMetricData( ImmutableSumData.create(isMonotonic(), temporality, points)); } - static final class Handle extends AggregatorHandle { + static final class Handle extends AggregatorHandle { private final LongAdder current = AdderUtil.createLongAdder(); // Only used if memoryMode == MemoryMode.REUSABLE_DATA @Nullable private final MutableLongPointData reusablePointData; - Handle(ExemplarReservoir exemplarReservoir, MemoryMode memoryMode) { - super(exemplarReservoir); + Handle(ExemplarReservoirFactory reservoirFactory, MemoryMode memoryMode) { + super(reservoirFactory); reusablePointData = memoryMode == MemoryMode.REUSABLE_DATA ? new MutableLongPointData() : null; } @Override - protected LongPointData doAggregateThenMaybeReset( + protected LongPointData doAggregateThenMaybeResetLongs( long startEpochNanos, long epochNanos, Attributes attributes, @@ -129,6 +128,11 @@ protected LongPointData doAggregateThenMaybeReset( } } + @Override + protected boolean isDoubleType() { + return false; + } + @Override public void doRecordLong(long value) { current.add(value); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleExemplarReservoir.java new file mode 100644 index 00000000000..9cf6084b55a --- /dev/null +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleExemplarReservoir.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.exemplar; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; +import io.opentelemetry.sdk.metrics.data.ExemplarData; +import java.util.List; + +/** + * An interface for an exemplar reservoir of double samples. + * + *

This represents a reservoir for a specific "point" of metric data. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + * + * @see LongExemplarReservoir + * @see ExemplarReservoirFactory + */ +public interface DoubleExemplarReservoir { + + /** Offers a measurement to be sampled. */ + void offerDoubleMeasurement(double value, Attributes attributes, Context context); + + /** + * Returns an immutable list of exemplars for exporting from the current reservoir. + * + *

Additionally, clears the reservoir for the next sampling period. + * + * @param pointAttributes the {@link Attributes} associated with the metric point. {@link + * ExemplarData}s should filter these out of their final data state. + * @return An (immutable) list of sampled exemplars for this point. Implementers are expected to + * filter out {@code pointAttributes} from the original recorded attributes. + */ + List collectAndResetDoubles(Attributes pointAttributes); +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleFilteredExemplarReservoir.java similarity index 51% rename from sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoir.java rename to sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleFilteredExemplarReservoir.java index 17415f9d06e..9d768e56a10 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoir.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleFilteredExemplarReservoir.java @@ -7,15 +7,15 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.metrics.data.ExemplarData; +import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import java.util.List; /** A reservoir that has a pre-filter on measurements. */ -class FilteredExemplarReservoir implements ExemplarReservoir { +class DoubleFilteredExemplarReservoir implements DoubleExemplarReservoir { private final ExemplarFilter filter; - private final ExemplarReservoir reservoir; + private final DoubleExemplarReservoir reservoir; - FilteredExemplarReservoir(ExemplarFilter filter, ExemplarReservoir reservoir) { + DoubleFilteredExemplarReservoir(ExemplarFilter filter, DoubleExemplarReservoir reservoir) { this.filter = filter; this.reservoir = reservoir; } @@ -28,14 +28,7 @@ public void offerDoubleMeasurement(double value, Attributes attributes, Context } @Override - public void offerLongMeasurement(long value, Attributes attributes, Context context) { - if (filter.shouldSampleMeasurement(value, attributes, context)) { - reservoir.offerLongMeasurement(value, attributes, context); - } - } - - @Override - public List collectAndReset(Attributes pointAttributes) { - return reservoir.collectAndReset(pointAttributes); + public List collectAndResetDoubles(Attributes pointAttributes) { + return reservoir.collectAndResetDoubles(pointAttributes); } } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoir.java deleted file mode 100644 index c0de6e0df6a..00000000000 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoir.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.metrics.internal.exemplar; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.common.Clock; -import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; -import java.util.List; -import java.util.Random; -import java.util.function.Supplier; - -/** - * An interface for an exemplar reservoir of samples. - * - *

This represents a reservoir for a specific "point" of metric data. - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -public interface ExemplarReservoir { - - /** - * Wraps an {@link ExemplarReservoir}, casting calls from {@link - * ExemplarReservoir#offerLongMeasurement(long, Attributes, Context)} to {@link - * ExemplarReservoir#offerDoubleMeasurement(double, Attributes, Context)} such that {@link - * ExemplarReservoir#collectAndReset(Attributes)} only returns {@link DoubleExemplarData}. - * - *

This is used for {@link Aggregation#explicitBucketHistogram()} and {@link - * Aggregation#base2ExponentialBucketHistogram()} which only support double measurements. - */ - static ExemplarReservoir longToDouble(ExemplarReservoir delegate) { - return new LongToDoubleExemplarReservoir<>(delegate); - } - - /** Wraps a {@link ExemplarReservoir} with a measurement pre-filter. */ - static ExemplarReservoir filtered( - ExemplarFilter filter, ExemplarReservoir original) { - return new FilteredExemplarReservoir<>(filter, original); - } - - /** A double exemplar reservoir that stores no exemplars. */ - static ExemplarReservoir doubleNoSamples() { - return NoopExemplarReservoir.DOUBLE_INSTANCE; - } - - /** A long exemplar reservoir that stores no exemplars. */ - static ExemplarReservoir longNoSamples() { - return NoopExemplarReservoir.LONG_INSTANCE; - } - - /** - * A double reservoir with fixed size that stores the given number of exemplars. - * - * @param clock The clock to use when annotating measurements with time. - * @param size The maximum number of exemplars to preserve. - * @param randomSupplier The random number generator to use for sampling. - */ - static ExemplarReservoir doubleFixedSizeReservoir( - Clock clock, int size, Supplier randomSupplier) { - return RandomFixedSizeExemplarReservoir.createDouble(clock, size, randomSupplier); - } - - /** - * A long reservoir with fixed size that stores the given number of exemplars. - * - * @param clock The clock to use when annotating measurements with time. - * @param size The maximum number of exemplars to preserve. - * @param randomSupplier The random number generator to use for sampling. - */ - static ExemplarReservoir longFixedSizeReservoir( - Clock clock, int size, Supplier randomSupplier) { - return RandomFixedSizeExemplarReservoir.createLong(clock, size, randomSupplier); - } - - /** - * A Reservoir sampler that preserves the latest seen measurement per-histogram bucket. - * - * @param clock The clock to use when annotating measurements with time. - * @param boundaries A list of (inclusive) upper bounds for the histogram. Should be in order from - * lowest to highest. - */ - static ExemplarReservoir histogramBucketReservoir( - Clock clock, List boundaries) { - return new HistogramExemplarReservoir(clock, boundaries); - } - - /** Offers a {@code double} measurement to be sampled. */ - void offerDoubleMeasurement(double value, Attributes attributes, Context context); - - /** Offers a {@code long} measurement to be sampled. */ - void offerLongMeasurement(long value, Attributes attributes, Context context); - - /** - * Returns an immutable list of Exemplars for exporting from the current reservoir. - * - *

Additionally, clears the reservoir for the next sampling period. - * - * @param pointAttributes the {@link Attributes} associated with the metric point. {@link - * ExemplarData}s should filter these out of their final data state. - * @return An (immutable) list of sampled exemplars for this point. Implementers are expected to - * filter out {@code pointAttributes} from the original recorded attributes. - */ - List collectAndReset(Attributes pointAttributes); -} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoirFactory.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoirFactory.java new file mode 100644 index 00000000000..b44f08b7746 --- /dev/null +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/ExemplarReservoirFactory.java @@ -0,0 +1,105 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.exemplar; + +import io.opentelemetry.sdk.common.Clock; +import java.util.List; +import java.util.Random; +import java.util.function.Supplier; + +/** + * An exemplar reservoir factory is responsible for creating exemplar reservoir instances (i.e. + * {@link DoubleExemplarReservoir} or {@link LongExemplarReservoir}) for aggregation handles. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public interface ExemplarReservoirFactory { + + /** + * Wraps exemplar reservoirs returned by a {@link ExemplarReservoirFactory} with a measurement + * pre-filter. + */ + static ExemplarReservoirFactory filtered( + ExemplarFilter filter, ExemplarReservoirFactory original) { + return new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return new DoubleFilteredExemplarReservoir( + filter, original.createDoubleExemplarReservoir()); + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return new LongFilteredExemplarReservoir(filter, original.createLongExemplarReservoir()); + } + }; + } + + /** An exemplar reservoir that stores no exemplars. */ + static ExemplarReservoirFactory noSamples() { + return new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return NoopExemplarReservoir.INSTANCE; + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return NoopExemplarReservoir.INSTANCE; + } + }; + } + + /** + * A reservoir with fixed size that stores the given number of exemplars. + * + * @param clock The clock to use when annotating measurements with time. + * @param size The maximum number of exemplars to preserve. + * @param randomSupplier The random number generator to use for sampling. + */ + static ExemplarReservoirFactory fixedSizeReservoir( + Clock clock, int size, Supplier randomSupplier) { + return new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return RandomFixedSizeExemplarReservoir.create(clock, size, randomSupplier); + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return RandomFixedSizeExemplarReservoir.create(clock, size, randomSupplier); + } + }; + } + + /** + * A Reservoir sampler that preserves the latest seen measurement per-histogram bucket. + * + * @param clock The clock to use when annotating measurements with time. + * @param boundaries A list of (inclusive) upper bounds for the histogram. Should be in order from + * lowest to highest. + */ + static ExemplarReservoirFactory histogramBucketReservoir(Clock clock, List boundaries) { + return new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return new HistogramExemplarReservoir(clock, boundaries); + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return new HistogramExemplarReservoir(clock, boundaries); + } + }; + } + + /** Create an exemplar reservoir for double measurements. */ + DoubleExemplarReservoir createDoubleExemplarReservoir(); + + /** Create an exemplar reservoir for long measurements. */ + LongExemplarReservoir createLongExemplarReservoir(); +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FixedSizeExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FixedSizeExemplarReservoir.java index 20254de5991..9ae6ec90e0b 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FixedSizeExemplarReservoir.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FixedSizeExemplarReservoir.java @@ -8,7 +8,9 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.Clock; +import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.metrics.data.ExemplarData; +import io.opentelemetry.sdk.metrics.data.LongExemplarData; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -16,26 +18,20 @@ import javax.annotation.Nullable; /** Base for fixed-size reservoir sampling of Exemplars. */ -abstract class FixedSizeExemplarReservoir implements ExemplarReservoir { +class FixedSizeExemplarReservoir implements DoubleExemplarReservoir, LongExemplarReservoir { @Nullable private ReservoirCell[] storage; private final ReservoirCellSelector reservoirCellSelector; - private final BiFunction mapAndResetCell; private final int size; private final Clock clock; private volatile boolean hasMeasurements = false; /** Instantiates an exemplar reservoir of fixed size. */ - FixedSizeExemplarReservoir( - Clock clock, - int size, - ReservoirCellSelector reservoirCellSelector, - BiFunction mapAndResetCell) { + FixedSizeExemplarReservoir(Clock clock, int size, ReservoirCellSelector reservoirCellSelector) { this.storage = null; // lazily initialize to avoid allocations this.size = size; this.clock = clock; this.reservoirCellSelector = reservoirCellSelector; - this.mapAndResetCell = mapAndResetCell; } @Override @@ -50,6 +46,16 @@ public void offerLongMeasurement(long value, Attributes attributes, Context cont } } + @Override + public List collectAndResetDoubles(Attributes pointAttributes) { + return doCollectAndReset(pointAttributes, ReservoirCell::getAndResetDouble); + } + + @Override + public List collectAndResetLongs(Attributes pointAttributes) { + return doCollectAndReset(pointAttributes, ReservoirCell::getAndResetLong); + } + @Override public void offerDoubleMeasurement(double value, Attributes attributes, Context context) { if (storage == null) { @@ -70,8 +76,8 @@ private ReservoirCell[] initStorage() { return storage; } - @Override - public List collectAndReset(Attributes pointAttributes) { + public List doCollectAndReset( + Attributes pointAttributes, BiFunction mapAndResetCell) { if (!hasMeasurements || storage == null) { return Collections.emptyList(); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoir.java index ac06e64058e..8b5ae4f97e0 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoir.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoir.java @@ -8,19 +8,14 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.Clock; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils; import java.util.List; /** A reservoir that records the latest measurement for each histogram bucket. */ -class HistogramExemplarReservoir extends FixedSizeExemplarReservoir { +class HistogramExemplarReservoir extends FixedSizeExemplarReservoir { HistogramExemplarReservoir(Clock clock, List boundaries) { - super( - clock, - boundaries.size() + 1, - new HistogramCellSelector(boundaries), - ReservoirCell::getAndResetDouble); + super(clock, boundaries.size() + 1, new HistogramCellSelector(boundaries)); } @Override diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongExemplarReservoir.java new file mode 100644 index 00000000000..47f2172c0cf --- /dev/null +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongExemplarReservoir.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.exemplar; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.metrics.data.ExemplarData; +import io.opentelemetry.sdk.metrics.data.LongExemplarData; +import java.util.List; + +/** + * An interface for an exemplar reservoir of long samples. + * + *

This represents a reservoir for a specific "point" of metric data. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + * + * @see DoubleExemplarReservoir + * @see ExemplarReservoirFactory + */ +public interface LongExemplarReservoir { + + /** Offers a measurement to be sampled. */ + void offerLongMeasurement(long value, Attributes attributes, Context context); + + /** + * Returns an immutable list of exemplars for exporting from the current reservoir. + * + *

Additionally, clears the reservoir for the next sampling period. + * + * @param pointAttributes the {@link Attributes} associated with the metric point. {@link + * ExemplarData}s should filter these out of their final data state. + * @return An (immutable) list of sampled exemplars for this point. Implementers are expected to + * filter out {@code pointAttributes} from the original recorded attributes. + */ + List collectAndResetLongs(Attributes pointAttributes); +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongFilteredExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongFilteredExemplarReservoir.java new file mode 100644 index 00000000000..1cd2024674d --- /dev/null +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongFilteredExemplarReservoir.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.metrics.internal.exemplar; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.metrics.data.LongExemplarData; +import java.util.List; + +/** A reservoir that has a pre-filter on measurements. */ +class LongFilteredExemplarReservoir implements LongExemplarReservoir { + private final ExemplarFilter filter; + private final LongExemplarReservoir reservoir; + + LongFilteredExemplarReservoir(ExemplarFilter filter, LongExemplarReservoir reservoir) { + this.filter = filter; + this.reservoir = reservoir; + } + + @Override + public void offerLongMeasurement(long value, Attributes attributes, Context context) { + if (filter.shouldSampleMeasurement(value, attributes, context)) { + reservoir.offerLongMeasurement(value, attributes, context); + } + } + + @Override + public List collectAndResetLongs(Attributes pointAttributes) { + return reservoir.collectAndResetLongs(pointAttributes); + } +} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoir.java deleted file mode 100644 index c3a6b98fced..00000000000 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoir.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.metrics.internal.exemplar; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import java.util.List; - -class LongToDoubleExemplarReservoir implements ExemplarReservoir { - - private final ExemplarReservoir delegate; - - LongToDoubleExemplarReservoir(ExemplarReservoir delegate) { - this.delegate = delegate; - } - - @Override - public void offerDoubleMeasurement(double value, Attributes attributes, Context context) { - delegate.offerDoubleMeasurement(value, attributes, context); - } - - @Override - public void offerLongMeasurement(long value, Attributes attributes, Context context) { - offerDoubleMeasurement((double) value, attributes, context); - } - - @Override - public List collectAndReset(Attributes pointAttributes) { - return delegate.collectAndReset(pointAttributes); - } -} diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/NoopExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/NoopExemplarReservoir.java index ec08dd7db42..b501d9cf548 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/NoopExemplarReservoir.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/NoopExemplarReservoir.java @@ -8,18 +8,14 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.LongExemplarData; import java.util.Collections; import java.util.List; /** A reservoir that keeps no exemplars. */ -class NoopExemplarReservoir implements ExemplarReservoir { +class NoopExemplarReservoir implements LongExemplarReservoir, DoubleExemplarReservoir { - static final NoopExemplarReservoir LONG_INSTANCE = - new NoopExemplarReservoir<>(); - static final NoopExemplarReservoir DOUBLE_INSTANCE = - new NoopExemplarReservoir<>(); + static final NoopExemplarReservoir INSTANCE = new NoopExemplarReservoir(); private NoopExemplarReservoir() {} @@ -34,7 +30,12 @@ public void offerLongMeasurement(long value, Attributes attributes, Context cont } @Override - public List collectAndReset(Attributes pointAttributes) { + public List collectAndResetDoubles(Attributes pointAttributes) { + return Collections.emptyList(); + } + + @Override + public List collectAndResetLongs(Attributes pointAttributes) { return Collections.emptyList(); } } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoir.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoir.java index 5880394b37f..86e0c6a0ec4 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoir.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoir.java @@ -8,13 +8,9 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.Clock; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.internal.concurrent.AdderUtil; import io.opentelemetry.sdk.metrics.internal.concurrent.LongAdder; import java.util.Random; -import java.util.function.BiFunction; import java.util.function.Supplier; /** @@ -22,30 +18,19 @@ * where the probability of sampling decrease as the number of observations continue. * *

When measurements are collected via {@link - * FixedSizeExemplarReservoir#collectAndReset(Attributes)}, the observation count is reset, making - * the probability of samplings effectively 1.0. + * FixedSizeExemplarReservoir#collectAndResetDoubles(Attributes)} (Attributes)} and {@link + * FixedSizeExemplarReservoir#collectAndResetLongs(Attributes)}, the observation count is reset, + * making the probability of samplings effectively 1.0. */ -class RandomFixedSizeExemplarReservoir - extends FixedSizeExemplarReservoir { +class RandomFixedSizeExemplarReservoir extends FixedSizeExemplarReservoir { - private RandomFixedSizeExemplarReservoir( - Clock clock, - int size, - Supplier randomSupplier, - BiFunction mapAndResetCell) { - super(clock, size, new RandomCellSelector(randomSupplier), mapAndResetCell); + private RandomFixedSizeExemplarReservoir(Clock clock, int size, Supplier randomSupplier) { + super(clock, size, new RandomCellSelector(randomSupplier)); } - static RandomFixedSizeExemplarReservoir createLong( + static RandomFixedSizeExemplarReservoir create( Clock clock, int size, Supplier randomSupplier) { - return new RandomFixedSizeExemplarReservoir<>( - clock, size, randomSupplier, ReservoirCell::getAndResetLong); - } - - static RandomFixedSizeExemplarReservoir createDouble( - Clock clock, int size, Supplier randomSupplier) { - return new RandomFixedSizeExemplarReservoir<>( - clock, size, randomSupplier, ReservoirCell::getAndResetDouble); + return new RandomFixedSizeExemplarReservoir(clock, size, randomSupplier); } static class RandomCellSelector implements ReservoirCellSelector { 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 6463226f8bc..62a686e35b2 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 @@ -16,7 +16,6 @@ import io.opentelemetry.sdk.internal.ThrottlingLogger; import io.opentelemetry.sdk.metrics.View; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; @@ -46,15 +45,14 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public final class AsynchronousMetricStorage - implements MetricStorage { +public final class AsynchronousMetricStorage implements MetricStorage { private static final Logger logger = Logger.getLogger(AsynchronousMetricStorage.class.getName()); private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger); private final RegisteredReader registeredReader; private final MetricDescriptor metricDescriptor; private final AggregationTemporality aggregationTemporality; - private final Aggregator aggregator; + private final Aggregator aggregator; private final AttributesProcessor attributesProcessor; private final MemoryMode memoryMode; @@ -65,16 +63,16 @@ public final class AsynchronousMetricStorage> aggregatorHandles; + private final Map> aggregatorHandles; // Only populated if aggregationTemporality == DELTA private Map lastPoints; // Only populated if memoryMode == REUSABLE_DATA private final ObjectPool reusablePointsPool; - private final ObjectPool> reusableHandlesPool; - private final Function> handleBuilder; - private final BiConsumer> handleReleaser; + private final ObjectPool> reusableHandlesPool; + private final Function> handleBuilder; + private final BiConsumer> handleReleaser; private final BiConsumer pointReleaser; private final List reusablePointsList = new ArrayList<>(); @@ -92,7 +90,7 @@ public final class AsynchronousMetricStorage aggregator, + Aggregator aggregator, AttributesProcessor attributesProcessor, int maxCardinality, boolean enabled) { @@ -126,16 +124,15 @@ private AsynchronousMetricStorage( * Create an asynchronous storage instance for the {@link View} and {@link InstrumentDescriptor}. */ // TODO(anuraaga): The cast to generic type here looks suspicious. - public static - AsynchronousMetricStorage create( - RegisteredReader registeredReader, - RegisteredView registeredView, - InstrumentDescriptor instrumentDescriptor, - boolean enabled) { + public static AsynchronousMetricStorage create( + RegisteredReader registeredReader, + RegisteredView registeredView, + InstrumentDescriptor instrumentDescriptor, + boolean enabled) { View view = registeredView.getView(); MetricDescriptor metricDescriptor = MetricDescriptor.create(view, registeredView.getViewSourceInfo(), instrumentDescriptor); - Aggregator aggregator = + Aggregator aggregator = ((AggregatorFactory) view.getAggregation()) .createAggregator( instrumentDescriptor, @@ -153,14 +150,14 @@ AsynchronousMetricStorage create( /** Record callback measurement from {@link ObservableLongMeasurement}. */ void record(Attributes attributes, long value) { attributes = validateAndProcessAttributes(attributes); - AggregatorHandle handle = aggregatorHandles.computeIfAbsent(attributes, handleBuilder); + AggregatorHandle handle = aggregatorHandles.computeIfAbsent(attributes, handleBuilder); handle.recordLong(value, attributes, Context.current()); } /** Record callback measurement from {@link ObservableDoubleMeasurement}. */ void record(Attributes attributes, double value) { attributes = validateAndProcessAttributes(attributes); - AggregatorHandle handle = aggregatorHandles.computeIfAbsent(attributes, handleBuilder); + AggregatorHandle handle = aggregatorHandles.computeIfAbsent(attributes, handleBuilder); handle.recordDouble(value, attributes, Context.current()); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java index 77070ace40d..c95a62596d2 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/DefaultSynchronousMetricStorage.java @@ -15,7 +15,6 @@ import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.ThrottlingLogger; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; @@ -41,7 +40,7 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public final class DefaultSynchronousMetricStorage +public final class DefaultSynchronousMetricStorage implements SynchronousMetricStorage { private static final Logger internalLogger = @@ -51,8 +50,8 @@ public final class DefaultSynchronousMetricStorage aggregator; - private volatile AggregatorHolder aggregatorHolder = new AggregatorHolder<>(); + private final Aggregator aggregator; + private volatile AggregatorHolder aggregatorHolder = new AggregatorHolder<>(); private final AttributesProcessor attributesProcessor; private final MemoryMode memoryMode; @@ -62,7 +61,7 @@ public final class DefaultSynchronousMetricStorage> + private volatile ConcurrentHashMap> previousCollectionAggregatorHandles = new ConcurrentHashMap<>(); /** @@ -71,7 +70,7 @@ public final class DefaultSynchronousMetricStorage> aggregatorHandlePool = + private final ConcurrentLinkedQueue> aggregatorHandlePool = new ConcurrentLinkedQueue<>(); private boolean enabled; @@ -79,7 +78,7 @@ public final class DefaultSynchronousMetricStorage aggregator, + Aggregator aggregator, AttributesProcessor attributesProcessor, int maxCardinality, boolean enabled) { @@ -97,7 +96,7 @@ public final class DefaultSynchronousMetricStorage> getAggregatorHandlePool() { + Queue> getAggregatorHandlePool() { return aggregatorHandlePool; } @@ -106,9 +105,9 @@ public void recordLong(long value, Attributes attributes, Context context) { if (!enabled) { return; } - AggregatorHolder aggregatorHolder = getHolderForRecord(); + AggregatorHolder aggregatorHolder = getHolderForRecord(); try { - AggregatorHandle handle = + AggregatorHandle handle = getAggregatorHandle(aggregatorHolder.aggregatorHandles, attributes, context); handle.recordLong(value, attributes, context); } finally { @@ -131,9 +130,9 @@ public void recordDouble(double value, Attributes attributes, Context context) { + ". Dropping measurement."); return; } - AggregatorHolder aggregatorHolder = getHolderForRecord(); + AggregatorHolder aggregatorHolder = getHolderForRecord(); try { - AggregatorHandle handle = + AggregatorHandle handle = getAggregatorHandle(aggregatorHolder.aggregatorHandles, attributes, context); handle.recordDouble(value, attributes, context); } finally { @@ -159,9 +158,9 @@ public boolean isEnabled() { * #releaseHolderForRecord(AggregatorHolder)} when record operation completes to signal to that * its safe to proceed with Collect operations. */ - private AggregatorHolder getHolderForRecord() { + private AggregatorHolder getHolderForRecord() { do { - AggregatorHolder aggregatorHolder = this.aggregatorHolder; + AggregatorHolder aggregatorHolder = this.aggregatorHolder; int recordsInProgress = aggregatorHolder.activeRecordingThreads.addAndGet(2); if (recordsInProgress % 2 == 0) { return aggregatorHolder; @@ -177,17 +176,17 @@ private AggregatorHolder getHolderForRecord() { * Called on the {@link AggregatorHolder} obtained from {@link #getHolderForRecord()} to indicate * that recording is complete, and it is safe to collect. */ - private void releaseHolderForRecord(AggregatorHolder aggregatorHolder) { + private void releaseHolderForRecord(AggregatorHolder aggregatorHolder) { aggregatorHolder.activeRecordingThreads.addAndGet(-2); } - private AggregatorHandle getAggregatorHandle( - ConcurrentHashMap> aggregatorHandles, + private AggregatorHandle getAggregatorHandle( + ConcurrentHashMap> aggregatorHandles, Attributes attributes, Context context) { Objects.requireNonNull(attributes, "attributes"); attributes = attributesProcessor.process(attributes, context); - AggregatorHandle handle = aggregatorHandles.get(attributes); + AggregatorHandle handle = aggregatorHandles.get(attributes); if (handle != null) { return handle; } @@ -207,7 +206,7 @@ private AggregatorHandle getAggregatorHandle( } } // Get handle from pool if available, else create a new one. - AggregatorHandle newHandle = aggregatorHandlePool.poll(); + AggregatorHandle newHandle = aggregatorHandlePool.poll(); if (newHandle == null) { newHandle = aggregator.createHandle(); } @@ -227,9 +226,9 @@ public MetricData collect( ? registeredReader.getLastCollectEpochNanos() : startEpochNanos; - ConcurrentHashMap> aggregatorHandles; + ConcurrentHashMap> aggregatorHandles; if (reset) { - AggregatorHolder holder = this.aggregatorHolder; + AggregatorHolder holder = this.aggregatorHolder; this.aggregatorHolder = (memoryMode == REUSABLE_DATA) ? new AggregatorHolder<>(previousCollectionAggregatorHandles) @@ -327,8 +326,8 @@ public MetricDescriptor getMetricDescriptor() { return metricDescriptor; } - private static class AggregatorHolder { - private final ConcurrentHashMap> aggregatorHandles; + private static class AggregatorHolder { + private final ConcurrentHashMap> aggregatorHandles; // Recording threads grab the current interval (AggregatorHolder) and atomically increment // this by 2 before recording against it (and then decrement by two when done). // @@ -349,8 +348,7 @@ private AggregatorHolder() { aggregatorHandles = new ConcurrentHashMap<>(); } - private AggregatorHolder( - ConcurrentHashMap> aggregatorHandles) { + private AggregatorHolder(ConcurrentHashMap> aggregatorHandles) { this.aggregatorHandles = aggregatorHandles; } } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SdkObservableMeasurement.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SdkObservableMeasurement.java index 6e195fa545f..697402339b3 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SdkObservableMeasurement.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SdkObservableMeasurement.java @@ -31,7 +31,7 @@ public final class SdkObservableMeasurement private final ThrottlingLogger throttlingLogger = new ThrottlingLogger(logger); private final InstrumentationScopeInfo instrumentationScopeInfo; private final InstrumentDescriptor instrumentDescriptor; - private final List> storages; + private final List> storages; // These fields are set before invoking callbacks. They allow measurements to be recorded to the // storages for correct reader, and with the correct time. @@ -40,7 +40,7 @@ public final class SdkObservableMeasurement private SdkObservableMeasurement( InstrumentationScopeInfo instrumentationScopeInfo, InstrumentDescriptor instrumentDescriptor, - List> storages) { + List> storages) { this.instrumentationScopeInfo = instrumentationScopeInfo; this.instrumentDescriptor = instrumentDescriptor; this.storages = storages; @@ -57,7 +57,7 @@ private SdkObservableMeasurement( public static SdkObservableMeasurement create( InstrumentationScopeInfo instrumentationScopeInfo, InstrumentDescriptor instrumentDescriptor, - List> storages) { + List> storages) { return new SdkObservableMeasurement(instrumentationScopeInfo, instrumentDescriptor, storages); } @@ -73,7 +73,7 @@ public InstrumentationScopeInfo getInstrumentationScopeInfo() { public void setActiveReader( RegisteredReader registeredReader, long startEpochNanos, long epochNanos) { this.activeReader = registeredReader; - for (AsynchronousMetricStorage storage : storages) { + for (AsynchronousMetricStorage storage : storages) { if (storage.getRegisteredReader().equals(activeReader)) { storage.setEpochInformation(startEpochNanos, epochNanos); } @@ -91,7 +91,7 @@ InstrumentDescriptor getInstrumentDescriptor() { return instrumentDescriptor; } - List> getStorages() { + List> getStorages() { return storages; } @@ -108,7 +108,7 @@ public void record(long value, Attributes attributes) { return; } - for (AsynchronousMetricStorage storage : storages) { + for (AsynchronousMetricStorage storage : storages) { if (storage.getRegisteredReader().equals(activeReader)) { storage.record(attributes, value); } @@ -139,7 +139,7 @@ public void record(double value, Attributes attributes) { return; } - for (AsynchronousMetricStorage storage : storages) { + for (AsynchronousMetricStorage storage : storages) { if (storage.getRegisteredReader().equals(activeReader)) { storage.record(attributes, value); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorage.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorage.java index efb49692563..bc9d8f60610 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorage.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorage.java @@ -6,7 +6,6 @@ package io.opentelemetry.sdk.metrics.internal.state; import io.opentelemetry.sdk.metrics.View; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; @@ -36,7 +35,7 @@ static SynchronousMetricStorage empty() { * @return The storage, or {@link EmptyMetricStorage#empty()} if the instrument should not be * recorded. */ - static SynchronousMetricStorage create( + static SynchronousMetricStorage create( RegisteredReader registeredReader, RegisteredView registeredView, InstrumentDescriptor instrumentDescriptor, @@ -45,7 +44,7 @@ static SynchronousMetricStorage cr View view = registeredView.getView(); MetricDescriptor metricDescriptor = MetricDescriptor.create(view, registeredView.getViewSourceInfo(), instrumentDescriptor); - Aggregator aggregator = + Aggregator aggregator = ((AggregatorFactory) view.getAggregation()) .createAggregator( instrumentDescriptor, exemplarFilter, registeredReader.getReader().getMemoryMode()); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregation.java index a4facefca7a..b1ada9252e4 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregation.java @@ -11,7 +11,6 @@ import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.RandomSupplier; import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.MetricDataType; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; @@ -19,7 +18,7 @@ import io.opentelemetry.sdk.metrics.internal.aggregator.DoubleBase2ExponentialHistogramAggregator; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; /** * Exponential bucket histogram aggregation configuration. @@ -66,20 +65,18 @@ public static Aggregation create(int maxBuckets, int maxScale) { @Override @SuppressWarnings("unchecked") - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { - return (Aggregator) + return (Aggregator) new DoubleBase2ExponentialHistogramAggregator( - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.longToDouble( - ExemplarReservoir.doubleFixedSizeReservoir( - Clock.getDefault(), - Runtime.getRuntime().availableProcessors(), - RandomSupplier.platformDefault()))), + ExemplarReservoirFactory.filtered( + exemplarFilter, + ExemplarReservoirFactory.fixedSizeReservoir( + Clock.getDefault(), + Runtime.getRuntime().availableProcessors(), + RandomSupplier.platformDefault())), maxBuckets, maxScale, memoryMode); diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DefaultAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DefaultAggregation.java index 494e486c333..e329ff9425f 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DefaultAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DefaultAggregation.java @@ -8,7 +8,6 @@ import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.ThrottlingLogger; import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -58,7 +57,7 @@ private static Aggregation resolve(InstrumentDescriptor instrument, boolean with } @Override - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DropAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DropAggregation.java index 2b27938c20a..38db4acd381 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DropAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/DropAggregation.java @@ -7,7 +7,6 @@ import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -32,11 +31,11 @@ private DropAggregation() {} @Override @SuppressWarnings("unchecked") - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { - return (Aggregator) Aggregator.drop(); + return (Aggregator) Aggregator.drop(); } @Override diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/ExplicitBucketHistogramAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/ExplicitBucketHistogramAggregation.java index e452d02792d..40c0dbabc8d 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/ExplicitBucketHistogramAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/ExplicitBucketHistogramAggregation.java @@ -8,7 +8,6 @@ import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -16,7 +15,7 @@ import io.opentelemetry.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import java.util.List; /** @@ -50,19 +49,17 @@ private ExplicitBucketHistogramAggregation(List bucketBoundaries) { @Override @SuppressWarnings("unchecked") - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { - return (Aggregator) + return (Aggregator) new DoubleExplicitBucketHistogramAggregator( bucketBoundaryArray, - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.longToDouble( - ExemplarReservoir.histogramBucketReservoir( - Clock.getDefault(), bucketBoundaries))), + ExemplarReservoirFactory.filtered( + exemplarFilter, + ExemplarReservoirFactory.histogramBucketReservoir( + Clock.getDefault(), bucketBoundaries)), memoryMode); } 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 693af692c93..5157d846025 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 @@ -10,9 +10,6 @@ import io.opentelemetry.sdk.internal.RandomSupplier; import io.opentelemetry.sdk.metrics.Aggregation; import io.opentelemetry.sdk.metrics.InstrumentType; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -20,8 +17,7 @@ import io.opentelemetry.sdk.metrics.internal.aggregator.LongLastValueAggregator; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; -import java.util.function.Supplier; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; /** * Last-value aggregation configuration. @@ -41,37 +37,24 @@ private LastValueAggregation() {} @Override @SuppressWarnings("unchecked") - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { - // For the initial version we do not sample exemplars on gauges. + ExemplarReservoirFactory reservoirFactory = + ExemplarReservoirFactory.filtered( + exemplarFilter, + ExemplarReservoirFactory.fixedSizeReservoir( + Clock.getDefault(), + Runtime.getRuntime().availableProcessors(), + RandomSupplier.platformDefault())); + switch (instrumentDescriptor.getValueType()) { case LONG: - { - Supplier> reservoirFactory = - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.longFixedSizeReservoir( - Clock.getDefault(), - Runtime.getRuntime().availableProcessors(), - RandomSupplier.platformDefault())); - return (Aggregator) new LongLastValueAggregator(reservoirFactory, memoryMode); - } + return (Aggregator) new LongLastValueAggregator(reservoirFactory, memoryMode); case DOUBLE: - { - Supplier> reservoirFactory = - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.doubleFixedSizeReservoir( - Clock.getDefault(), - Runtime.getRuntime().availableProcessors(), - RandomSupplier.platformDefault())); - return (Aggregator) new DoubleLastValueAggregator(reservoirFactory, memoryMode); - } + return (Aggregator) new DoubleLastValueAggregator(reservoirFactory, memoryMode); } throw new IllegalArgumentException("Invalid instrument value type"); } diff --git a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/SumAggregation.java b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/SumAggregation.java index 7ca1294666b..52a24521348 100644 --- a/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/SumAggregation.java +++ b/sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/view/SumAggregation.java @@ -9,9 +9,6 @@ import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.internal.RandomSupplier; import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -19,8 +16,7 @@ import io.opentelemetry.sdk.metrics.internal.aggregator.LongSumAggregator; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; -import java.util.function.Supplier; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; /** * A sum aggregation configuration. @@ -39,37 +35,24 @@ private SumAggregation() {} @Override @SuppressWarnings("unchecked") - public Aggregator createAggregator( + public Aggregator createAggregator( InstrumentDescriptor instrumentDescriptor, ExemplarFilter exemplarFilter, MemoryMode memoryMode) { + ExemplarReservoirFactory reservoirFactory = + ExemplarReservoirFactory.filtered( + exemplarFilter, + ExemplarReservoirFactory.fixedSizeReservoir( + Clock.getDefault(), + Runtime.getRuntime().availableProcessors(), + RandomSupplier.platformDefault())); switch (instrumentDescriptor.getValueType()) { case LONG: - { - Supplier> reservoirFactory = - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.longFixedSizeReservoir( - Clock.getDefault(), - Runtime.getRuntime().availableProcessors(), - RandomSupplier.platformDefault())); - return (Aggregator) - new LongSumAggregator(instrumentDescriptor, reservoirFactory, memoryMode); - } + return (Aggregator) + new LongSumAggregator(instrumentDescriptor, reservoirFactory, memoryMode); case DOUBLE: - { - Supplier> reservoirFactory = - () -> - ExemplarReservoir.filtered( - exemplarFilter, - ExemplarReservoir.doubleFixedSizeReservoir( - Clock.getDefault(), - Runtime.getRuntime().availableProcessors(), - RandomSupplier.platformDefault())); - return (Aggregator) - new DoubleSumAggregator(instrumentDescriptor, reservoirFactory, memoryMode); - } + return (Aggregator) + new DoubleSumAggregator(instrumentDescriptor, reservoirFactory, memoryMode); } throw new IllegalArgumentException("Invalid instrument value type"); } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandleTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandleTest.java index 276b5e7b055..6b0b6ff36fe 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandleTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/AggregatorHandleTest.java @@ -18,9 +18,12 @@ import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoubleExemplarData; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nullable; @@ -33,33 +36,32 @@ @ExtendWith(MockitoExtension.class) class AggregatorHandleTest { - @Mock ExemplarReservoir doubleReservoir; - @Mock ExemplarReservoir longReservoir; + @Mock DoubleExemplarReservoir doubleReservoir; + @Mock LongExemplarReservoir longReservoir; @Test void testRecordings() { - TestAggregatorHandle testAggregator = new TestAggregatorHandle<>(doubleReservoir); + TestLongAggregatorHandle testLongAggregator = new TestLongAggregatorHandle(longReservoir); - testAggregator.recordLong(22); - assertThat(testAggregator.recordedLong.get()).isEqualTo(22); - assertThat(testAggregator.recordedDouble.get()).isEqualTo(0); + testLongAggregator.recordLong(22, Attributes.empty(), Context.current()); + assertThat(testLongAggregator.recordedLong.get()).isEqualTo(22); - testAggregator.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); - assertThat(testAggregator.recordedLong.get()).isEqualTo(0); - assertThat(testAggregator.recordedDouble.get()).isEqualTo(0); + testLongAggregator.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); + assertThat(testLongAggregator.recordedLong.get()).isEqualTo(0); - testAggregator.recordDouble(33.55); - assertThat(testAggregator.recordedLong.get()).isEqualTo(0); - assertThat(testAggregator.recordedDouble.get()).isEqualTo(33.55); + TestDoubleAggregatorHandle testDoubleAggregator = + new TestDoubleAggregatorHandle(doubleReservoir); - testAggregator.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); - assertThat(testAggregator.recordedLong.get()).isEqualTo(0); - assertThat(testAggregator.recordedDouble.get()).isEqualTo(0); + testDoubleAggregator.recordDouble(33.55, Attributes.empty(), Context.current()); + assertThat(testDoubleAggregator.recordedDouble.get()).isEqualTo(33.55); + + testDoubleAggregator.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); + assertThat(testDoubleAggregator.recordedDouble.get()).isEqualTo(0); } @Test void testOfferMeasurementLongToExemplar() { - TestAggregatorHandle testAggregator = new TestAggregatorHandle<>(longReservoir); + TestLongAggregatorHandle testAggregator = new TestLongAggregatorHandle(longReservoir); Attributes attributes = Attributes.builder().put("test", "value").build(); Context context = Context.root(); testAggregator.recordLong(1L, attributes, context); @@ -68,7 +70,7 @@ void testOfferMeasurementLongToExemplar() { @Test void testOfferMeasurementDoubleToExemplar() { - TestAggregatorHandle testAggregator = new TestAggregatorHandle<>(doubleReservoir); + TestDoubleAggregatorHandle testAggregator = new TestDoubleAggregatorHandle(doubleReservoir); Attributes attributes = Attributes.builder().put("test", "value").build(); Context context = Context.root(); testAggregator.recordDouble(1.0d, attributes, context); @@ -77,8 +79,7 @@ void testOfferMeasurementDoubleToExemplar() { @Test void testGenerateExemplarsOnCollect() { - TestAggregatorHandle testAggregator = - new TestAggregatorHandle<>(doubleReservoir); + TestDoubleAggregatorHandle testAggregator = new TestDoubleAggregatorHandle(doubleReservoir); Attributes attributes = Attributes.builder().put("test", "value").build(); DoubleExemplarData result = ImmutableDoubleExemplarData.create( @@ -92,29 +93,79 @@ void testGenerateExemplarsOnCollect() { 1); // We need to first record a value so that collect and reset does something. testAggregator.recordDouble(1.0, Attributes.empty(), Context.root()); - Mockito.when(doubleReservoir.collectAndReset(attributes)) + Mockito.when(doubleReservoir.collectAndResetDoubles(attributes)) .thenReturn(Collections.singletonList(result)); testAggregator.aggregateThenMaybeReset(0, 1, attributes, /* reset= */ true); - assertThat(testAggregator.recordedExemplars.get()).containsExactly(result); + assertThat(testAggregator.recordedExemplars.get()).isEqualTo(Collections.singletonList(result)); + } + + private static class TestDoubleAggregatorHandle extends TestAggregatorHandle { + + TestDoubleAggregatorHandle(DoubleExemplarReservoir reservoir) { + super(reservoir, null); + } + + @Override + protected boolean isDoubleType() { + return true; + } + } + + private static class TestLongAggregatorHandle extends TestAggregatorHandle { + + TestLongAggregatorHandle(LongExemplarReservoir reservoir) { + super(null, reservoir); + } + + @Override + protected boolean isDoubleType() { + return false; + } } - private static class TestAggregatorHandle - extends AggregatorHandle { + private abstract static class TestAggregatorHandle extends AggregatorHandle { final AtomicLong recordedLong = new AtomicLong(); final AtomicDouble recordedDouble = new AtomicDouble(); - final AtomicReference> recordedExemplars = new AtomicReference<>(); + final AtomicReference> recordedExemplars = new AtomicReference<>(); + + TestAggregatorHandle( + @Nullable DoubleExemplarReservoir doubleReservoir, + @Nullable LongExemplarReservoir longReservoir) { + super( + new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return Objects.requireNonNull(doubleReservoir); + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return Objects.requireNonNull(longReservoir); + } + }); + } - TestAggregatorHandle(ExemplarReservoir reservoir) { - super(reservoir); + @Nullable + @Override + protected PointData doAggregateThenMaybeResetDoubles( + long startEpochNanos, + long epochNanos, + Attributes attributes, + List exemplars, + boolean reset) { + recordedLong.set(0); + recordedDouble.set(0); + recordedExemplars.set(exemplars); + return null; } @Nullable @Override - protected PointData doAggregateThenMaybeReset( + protected PointData doAggregateThenMaybeResetLongs( long startEpochNanos, long epochNanos, Attributes attributes, - List exemplars, + List exemplars, boolean reset) { recordedLong.set(0); recordedDouble.set(0); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregatorTest.java index e774939dd4c..763d36fbec6 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleBase2ExponentialHistogramAggregatorTest.java @@ -27,7 +27,9 @@ import io.opentelemetry.sdk.metrics.internal.data.MutableExponentialHistogramBuckets; import io.opentelemetry.sdk.metrics.internal.data.MutableExponentialHistogramPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import io.opentelemetry.sdk.resources.Resource; import java.util.ArrayList; import java.util.Arrays; @@ -37,7 +39,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadPoolExecutor; -import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import org.assertj.core.data.Offset; @@ -53,7 +54,20 @@ @ExtendWith(MockitoExtension.class) class DoubleBase2ExponentialHistogramAggregatorTest { - @Mock ExemplarReservoir reservoir; + @Mock DoubleExemplarReservoir reservoir; + private final ExemplarReservoirFactory reservoirFactory = + new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return reservoir; + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + throw new UnsupportedOperationException(); + } + }; + private DoubleBase2ExponentialHistogramAggregator aggregator; private static final int MAX_SCALE = 20; @@ -68,10 +82,10 @@ private static Stream provideAggregat for (MemoryMode memoryMode : MemoryMode.values()) { parameters.add( new DoubleBase2ExponentialHistogramAggregator( - ExemplarReservoir::doubleNoSamples, 160, 20, memoryMode)); + ExemplarReservoirFactory.noSamples(), 160, 20, memoryMode)); parameters.add( new DoubleBase2ExponentialHistogramAggregator( - ExemplarReservoir::doubleNoSamples, 160, MAX_SCALE, memoryMode)); + ExemplarReservoirFactory.noSamples(), 160, MAX_SCALE, memoryMode)); } return parameters.stream(); } @@ -84,7 +98,7 @@ private static int valueToIndex(int scale, double value) { private void initialize(MemoryMode memoryMode) { aggregator = new DoubleBase2ExponentialHistogramAggregator( - ExemplarReservoir::doubleNoSamples, 160, 20, memoryMode); + ExemplarReservoirFactory.noSamples(), 160, 20, memoryMode); } @ParameterizedTest @@ -92,11 +106,11 @@ private void initialize(MemoryMode memoryMode) { void createHandle(MemoryMode memoryMode) { initialize(memoryMode); - AggregatorHandle handle = aggregator.createHandle(); + AggregatorHandle handle = aggregator.createHandle(); assertThat(handle).isInstanceOf(DoubleBase2ExponentialHistogramAggregator.Handle.class); ExponentialHistogramPointData point = ((DoubleBase2ExponentialHistogramAggregator.Handle) handle) - .doAggregateThenMaybeReset( + .doAggregateThenMaybeResetDoubles( 0, 1, Attributes.empty(), Collections.emptyList(), /* reset= */ true); assertThat(point.getPositiveBuckets()).isInstanceOf(EmptyExponentialHistogramBuckets.class); assertThat(point.getPositiveBuckets().getScale()).isEqualTo(MAX_SCALE); @@ -109,18 +123,17 @@ void createHandle(MemoryMode memoryMode) { void testRecordings(MemoryMode memoryMode) { initialize(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(0.5); - aggregatorHandle.recordDouble(1.0); - aggregatorHandle.recordDouble(12.0); - aggregatorHandle.recordDouble(15.213); - aggregatorHandle.recordDouble(12.0); - aggregatorHandle.recordDouble(-13.2); - aggregatorHandle.recordDouble(-2.01); - aggregatorHandle.recordDouble(-1); - aggregatorHandle.recordDouble(0.0); - aggregatorHandle.recordLong(0); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(0.5, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(1.0, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.0, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(15.213, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.0, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-13.2, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-2.01, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(0.0, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(0, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); @@ -155,12 +168,11 @@ void testRecordings(MemoryMode memoryMode) { void testInvalidRecording(MemoryMode memoryMode) { initialize(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); // Non-finite recordings should be ignored - aggregatorHandle.recordDouble(Double.POSITIVE_INFINITY); - aggregatorHandle.recordDouble(Double.NEGATIVE_INFINITY); - aggregatorHandle.recordDouble(Double.NaN); + aggregatorHandle.recordDouble(Double.POSITIVE_INFINITY, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(Double.NEGATIVE_INFINITY, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(Double.NaN, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); @@ -173,11 +185,10 @@ void testInvalidRecording(MemoryMode memoryMode) { @ParameterizedTest @MethodSource("provideAggregator") void testRecordingsAtLimits(DoubleBase2ExponentialHistogramAggregator aggregator) { - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordDouble(Double.MIN_VALUE); - aggregatorHandle.recordDouble(Double.MAX_VALUE); + aggregatorHandle.recordDouble(Double.MIN_VALUE, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(Double.MAX_VALUE, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); @@ -219,7 +230,7 @@ void testRecordingsAtLimits(DoubleBase2ExponentialHistogramAggregator aggregator @EnumSource(MemoryMode.class) void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { DoubleBase2ExponentialHistogramAggregator agg = - new DoubleBase2ExponentialHistogramAggregator(() -> reservoir, 160, MAX_SCALE, memoryMode); + new DoubleBase2ExponentialHistogramAggregator(reservoirFactory, 160, MAX_SCALE, memoryMode); Attributes attributes = Attributes.builder().put("test", "value").build(); DoubleExemplarData exemplar = @@ -233,10 +244,9 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { TraceState.getDefault()), 1); List exemplars = Collections.singletonList(exemplar); - Mockito.when(reservoir.collectAndReset(Attributes.empty())).thenReturn(exemplars); + Mockito.when(reservoir.collectAndResetDoubles(Attributes.empty())).thenReturn(exemplars); - AggregatorHandle aggregatorHandle = - agg.createHandle(); + AggregatorHandle aggregatorHandle = agg.createHandle(); aggregatorHandle.recordDouble(0, attributes, Context.root()); assertThat( @@ -252,10 +262,9 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { void aggregateThenMaybeReset(MemoryMode memoryMode) { initialize(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordDouble(5.0); + aggregatorHandle.recordDouble(5.0, Attributes.empty(), Context.current()); assertThat( Objects.requireNonNull( aggregatorHandle.aggregateThenMaybeReset( @@ -270,14 +279,13 @@ void aggregateThenMaybeReset(MemoryMode memoryMode) { void testInsert1M(MemoryMode memoryMode) { initialize(memoryMode); - AggregatorHandle handle = - aggregator.createHandle(); + AggregatorHandle handle = aggregator.createHandle(); int n = 1024 * 1024 - 1; double min = 16.0 / n; double d = min; for (int i = 0; i < n; i++) { - handle.recordDouble(d); + handle.recordDouble(d, Attributes.empty(), Context.current()); d += min; } @@ -299,15 +307,15 @@ void testDownScale(MemoryMode memoryMode) { DoubleBase2ExponentialHistogramAggregator.Handle handle = (DoubleBase2ExponentialHistogramAggregator.Handle) aggregator.createHandle(); // record a measurement to initialize positive buckets - handle.recordDouble(0.5); + handle.recordDouble(0.5, Attributes.empty(), Context.current()); handle.downScale(20); // down to zero scale // test histogram operates properly after being manually scaled down to 0 - handle.recordDouble(1.0); - handle.recordDouble(2.0); - handle.recordDouble(4.0); - handle.recordDouble(16.0); + handle.recordDouble(1.0, Attributes.empty(), Context.current()); + handle.recordDouble(2.0, Attributes.empty(), Context.current()); + handle.recordDouble(4.0, Attributes.empty(), Context.current()); + handle.recordDouble(16.0, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = Objects.requireNonNull( @@ -336,22 +344,17 @@ void testToMetricData(MemoryMode memoryMode) { TraceFlags.getDefault(), TraceState.getDefault()), 1); - @SuppressWarnings("unchecked") - Supplier> reservoirSupplier = - Mockito.mock(Supplier.class); - Mockito.when(reservoir.collectAndReset(Attributes.empty())) + Mockito.when(reservoir.collectAndResetDoubles(Attributes.empty())) .thenReturn(Collections.singletonList(exemplar)); - Mockito.when(reservoirSupplier.get()).thenReturn(reservoir); DoubleBase2ExponentialHistogramAggregator cumulativeAggregator = - new DoubleBase2ExponentialHistogramAggregator( - reservoirSupplier, 160, MAX_SCALE, memoryMode); + new DoubleBase2ExponentialHistogramAggregator(reservoirFactory, 160, MAX_SCALE, memoryMode); - AggregatorHandle aggregatorHandle = + AggregatorHandle aggregatorHandle = cumulativeAggregator.createHandle(); - aggregatorHandle.recordDouble(0); - aggregatorHandle.recordDouble(0); - aggregatorHandle.recordDouble(123.456); + aggregatorHandle.recordDouble(0, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(0, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(123.456, Attributes.empty(), Context.current()); ExponentialHistogramPointData expPoint = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); @@ -391,9 +394,9 @@ void testToMetricData(MemoryMode memoryMode) { buckets .hasTotalCount(0) .hasCounts(Collections.emptyList())))); - aggregatorHandle.recordDouble(1); - aggregatorHandle.recordDouble(-1); - aggregatorHandle.recordDouble(0); + aggregatorHandle.recordDouble(1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(0, Attributes.empty(), Context.current()); } MetricData metricDataDelta = @@ -413,8 +416,7 @@ void testToMetricData(MemoryMode memoryMode) { void testMultithreadedUpdates(MemoryMode memoryMode) throws InterruptedException { initialize(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); ImmutableList updates = ImmutableList.of(0D, 0.1D, -0.1D, 1D, -1D, 100D); int numberOfThreads = updates.size(); int numberOfUpdates = 10000; @@ -428,7 +430,7 @@ void testMultithreadedUpdates(MemoryMode memoryMode) throws InterruptedException Executors.callable( () -> { for (int j = 0; j < numberOfUpdates; j++) { - aggregatorHandle.recordDouble(v); + aggregatorHandle.recordDouble(v, Attributes.empty(), Context.current()); if (ThreadLocalRandom.current().nextInt(10) == 0) { aggregatorHandle.aggregateThenMaybeReset( 0, 1, Attributes.empty(), /* reset= */ false); @@ -487,9 +489,9 @@ public void verifyMutableDataUsedInReusableDataMemoryMode() { (DoubleBase2ExponentialHistogramAggregator.Handle) aggregator.createHandle(); // record a measurement to initialize positive buckets - handle.recordDouble(0.5); + handle.recordDouble(0.5, Attributes.empty(), Context.current()); // record a measurement to initialize negative buckets - handle.recordDouble(-13.2); + handle.recordDouble(-13.2, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = Objects.requireNonNull( @@ -501,8 +503,8 @@ public void verifyMutableDataUsedInReusableDataMemoryMode() { assertThat(point.getPositiveBuckets().getBucketCounts()).isNotEmpty(); assertThat(point.getNegativeBuckets().getBucketCounts()).isNotEmpty(); - handle.recordDouble(0.6); - handle.recordDouble(-16.3); + handle.recordDouble(0.6, Attributes.empty(), Context.current()); + handle.recordDouble(-16.3, Attributes.empty(), Context.current()); ExponentialHistogramPointData secondAggregatePoint = Objects.requireNonNull( @@ -520,9 +522,9 @@ public void verifyImmutableDataUsedInImmutableDataMemoryMode() { (DoubleBase2ExponentialHistogramAggregator.Handle) aggregator.createHandle(); // record a measurement to initialize positive buckets - handle.recordDouble(0.5); + handle.recordDouble(0.5, Attributes.empty(), Context.current()); // record a measurement to initialize negative buckets - handle.recordDouble(-13.2); + handle.recordDouble(-13.2, Attributes.empty(), Context.current()); ExponentialHistogramPointData point = Objects.requireNonNull( @@ -552,9 +554,9 @@ public void reusablePoint_emptyFirstThenRecordAndCheck() { assertThat(point.getNegativeBuckets()).isInstanceOf(EmptyExponentialHistogramBuckets.class); // record a measurement to initialize positive buckets - handle.recordDouble(0.5); + handle.recordDouble(0.5, Attributes.empty(), Context.current()); // record a measurement to initialize negative buckets - handle.recordDouble(-13.2); + handle.recordDouble(-13.2, Attributes.empty(), Context.current()); point = Objects.requireNonNull( diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregatorTest.java index f10787c7197..e883b5d2698 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleExplicitBucketHistogramAggregatorTest.java @@ -24,7 +24,9 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableHistogramPointData; import io.opentelemetry.sdk.metrics.internal.data.MutableHistogramPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import io.opentelemetry.sdk.resources.Resource; import java.util.Arrays; import java.util.Collections; @@ -45,7 +47,19 @@ @ExtendWith(MockitoExtension.class) class DoubleExplicitBucketHistogramAggregatorTest { - @Mock ExemplarReservoir reservoir; + @Mock DoubleExemplarReservoir reservoir; + private final ExemplarReservoirFactory reservoirFactory = + new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return reservoir; + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + throw new UnsupportedOperationException(); + } + }; private static final double[] boundaries = new double[] {10.0, 100.0, 1000.0}; private static final List boundariesList = @@ -60,7 +74,7 @@ class DoubleExplicitBucketHistogramAggregatorTest { private void init(MemoryMode memoryMode) { aggregator = new DoubleExplicitBucketHistogramAggregator( - boundaries, ExemplarReservoir::doubleNoSamples, memoryMode); + boundaries, ExemplarReservoirFactory.noSamples(), memoryMode); } @ParameterizedTest @@ -75,12 +89,11 @@ void createHandle(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void testRecordings(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordLong(20); - aggregatorHandle.recordLong(5); - aggregatorHandle.recordLong(150); - aggregatorHandle.recordLong(2000); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(20, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(5, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(150, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(2000, Attributes.empty(), Context.current()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) .isEqualTo( @@ -112,11 +125,10 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { TraceState.getDefault()), 1); List exemplars = Collections.singletonList(exemplar); - Mockito.when(reservoir.collectAndReset(Attributes.empty())).thenReturn(exemplars); + Mockito.when(reservoir.collectAndResetDoubles(Attributes.empty())).thenReturn(exemplars); DoubleExplicitBucketHistogramAggregator aggregator = - new DoubleExplicitBucketHistogramAggregator(boundaries, () -> reservoir, memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + new DoubleExplicitBucketHistogramAggregator(boundaries, reservoirFactory, memoryMode); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordDouble(0, attributes, Context.root()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) @@ -139,10 +151,9 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void aggregateThenMaybeReset(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(100); + aggregatorHandle.recordLong(100, Attributes.empty(), Context.current()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) .isEqualTo( @@ -158,7 +169,7 @@ void aggregateThenMaybeReset(MemoryMode memoryMode) { boundariesList, Arrays.asList(0L, 1L, 0L, 0L))); - aggregatorHandle.recordLong(0); + aggregatorHandle.recordLong(0, Attributes.empty(), Context.current()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) .isEqualTo( @@ -179,9 +190,8 @@ void aggregateThenMaybeReset(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void toMetricData(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordLong(10); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(10, Attributes.empty(), Context.current()); MetricData metricData = aggregator.toMetricData( @@ -250,9 +260,8 @@ void toMetricDataWithExemplars(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void testHistogramCounts(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(1.1); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(1.1, Attributes.empty(), Context.current()); HistogramPointData point = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true); assertThat(point).isNotNull(); @@ -263,8 +272,7 @@ void testHistogramCounts(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void testMultithreadedUpdates(MemoryMode memoryMode) throws InterruptedException { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); ImmutableList updates = ImmutableList.of(1L, 2L, 3L, 5L, 7L, 11L, 13L, 17L, 19L, 23L); int numberOfThreads = updates.size(); int numberOfUpdates = 10000; @@ -278,7 +286,7 @@ void testMultithreadedUpdates(MemoryMode memoryMode) throws InterruptedException Executors.callable( () -> { for (int j = 0; j < numberOfUpdates; j++) { - aggregatorHandle.recordLong(v); + aggregatorHandle.recordLong(v, Attributes.empty(), Context.current()); if (ThreadLocalRandom.current().nextInt(10) == 0) { aggregatorHandle.aggregateThenMaybeReset( 0, 1, Attributes.empty(), /* reset= */ false); @@ -306,19 +314,18 @@ void testMultithreadedUpdates(MemoryMode memoryMode) throws InterruptedException @Test void testReusableDataMemoryMode() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordLong(10); - aggregatorHandle.recordLong(20); - aggregatorHandle.recordLong(30); - aggregatorHandle.recordLong(40); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(10, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(20, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(30, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(40, Attributes.empty(), Context.current()); HistogramPointData pointData = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); assertThat(pointData).isExactlyInstanceOf(MutableHistogramPointData.class); - aggregatorHandle.recordLong(10); - aggregatorHandle.recordLong(20); + aggregatorHandle.recordLong(10, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(20, Attributes.empty(), Context.current()); HistogramPointData anotherPointData = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); 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 8234b172a7a..ee8f3645a93 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 @@ -13,6 +13,7 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; @@ -23,7 +24,7 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableDoublePointData; import io.opentelemetry.sdk.metrics.internal.data.MutableDoublePointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collections; import java.util.List; @@ -41,7 +42,7 @@ class DoubleLastValueAggregatorTest { private DoubleLastValueAggregator aggregator; private void init(MemoryMode memoryMode) { - aggregator = new DoubleLastValueAggregator(ExemplarReservoir::doubleNoSamples, memoryMode); + aggregator = new DoubleLastValueAggregator(ExemplarReservoirFactory.noSamples(), memoryMode); } @ParameterizedTest @@ -56,16 +57,15 @@ void createHandle(MemoryMode memoryMode) { void multipleRecords(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(12.1); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(12.1); - aggregatorHandle.recordDouble(13.1); - aggregatorHandle.recordDouble(14.1); + aggregatorHandle.recordDouble(13.1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(14.1, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -78,17 +78,16 @@ void multipleRecords(MemoryMode memoryMode) { void aggregateThenMaybeReset(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordDouble(13.1); + aggregatorHandle.recordDouble(13.1, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(13.1); - aggregatorHandle.recordDouble(12.1); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -229,9 +228,8 @@ void copyPoint(MemoryMode memoryMode) { void toMetricData(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(10); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(10, Attributes.empty(), Context.current()); MetricData metricData = aggregator.toMetricData( @@ -260,18 +258,18 @@ void toMetricData(MemoryMode memoryMode) { @Test void testReusableDataOnCollect() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle handle = aggregator.createHandle(); - handle.recordDouble(1); + AggregatorHandle handle = aggregator.createHandle(); + handle.recordDouble(1, Attributes.empty(), Context.current()); DoublePointData pointData = handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); - handle.recordDouble(1); + handle.recordDouble(1, Attributes.empty(), Context.current()); DoublePointData pointData2 = handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); assertThat(pointData).isSameAs(pointData2); - handle.recordDouble(1); + handle.recordDouble(1, Attributes.empty(), Context.current()); DoublePointData pointDataWithReset = handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ true); @@ -281,7 +279,7 @@ void testReusableDataOnCollect() { @Test void testNullPointerExceptionWhenUnset() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle handle = aggregator.createHandle(); + AggregatorHandle handle = aggregator.createHandle(); assertThatThrownBy( () -> handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ true)) .isInstanceOf(NullPointerException.class); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregatorTest.java index 0e6043f7211..4afd1672bc5 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/DoubleSumAggregatorTest.java @@ -27,7 +27,9 @@ import io.opentelemetry.sdk.metrics.internal.descriptor.Advice; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import io.opentelemetry.sdk.resources.Resource; import java.util.Collections; import java.util.List; @@ -43,7 +45,19 @@ @ExtendWith(MockitoExtension.class) class DoubleSumAggregatorTest { - @Mock ExemplarReservoir reservoir; + @Mock DoubleExemplarReservoir reservoir; + private final ExemplarReservoirFactory reservoirFactory = + new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + return reservoir; + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + throw new UnsupportedOperationException(); + } + }; private static final Resource resource = Resource.getDefault(); private static final InstrumentationScopeInfo scope = InstrumentationScopeInfo.empty(); @@ -62,7 +76,7 @@ private void init(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.DOUBLE, Advice.empty()), - ExemplarReservoir::doubleNoSamples, + ExemplarReservoirFactory.noSamples(), memoryMode); } @@ -77,13 +91,12 @@ void createHandle(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void multipleRecords(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(12.1); - aggregatorHandle.recordDouble(12.1); - aggregatorHandle.recordDouble(12.1); - aggregatorHandle.recordDouble(12.1); - aggregatorHandle.recordDouble(12.1); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12.1, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -95,14 +108,13 @@ void multipleRecords(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void multipleRecords_WithNegatives(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(12); - aggregatorHandle.recordDouble(12); - aggregatorHandle.recordDouble(-23); - aggregatorHandle.recordDouble(12); - aggregatorHandle.recordDouble(12); - aggregatorHandle.recordDouble(-11); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-23, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-11, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -114,19 +126,18 @@ void multipleRecords_WithNegatives(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void aggregateThenMaybeReset(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordDouble(13); - aggregatorHandle.recordDouble(12); + aggregatorHandle.recordDouble(13, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(25); - aggregatorHandle.recordDouble(12); - aggregatorHandle.recordDouble(-25); + aggregatorHandle.recordDouble(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordDouble(-25, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -149,7 +160,7 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { TraceState.getDefault()), 1); List exemplars = Collections.singletonList(exemplar); - Mockito.when(reservoir.collectAndReset(Attributes.empty())).thenReturn(exemplars); + Mockito.when(reservoir.collectAndResetDoubles(Attributes.empty())).thenReturn(exemplars); DoubleSumAggregator aggregator = new DoubleSumAggregator( InstrumentDescriptor.create( @@ -159,10 +170,9 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.DOUBLE, Advice.empty()), - () -> reservoir, + reservoirFactory, memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordDouble(0, attributes, Context.root()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) @@ -195,7 +205,7 @@ void mergeAndDiff(MemoryMode memoryMode) { instrumentType, InstrumentValueType.LONG, Advice.empty()), - ExemplarReservoir::doubleNoSamples, + ExemplarReservoirFactory.noSamples(), memoryMode); DoublePointData diffed = @@ -305,9 +315,8 @@ void copyPoint(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void toMetricData(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(10); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(10, Attributes.empty(), Context.current()); MetricData metricData = aggregator.toMetricData( @@ -366,14 +375,13 @@ void toMetricDataWithExemplars(MemoryMode memoryMode) { @Test void sameObjectReturnedOnReusableDataMemoryMode() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle aggregatorHandle = - aggregator.createHandle(); - aggregatorHandle.recordDouble(1.0); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordDouble(1.0, Attributes.empty(), Context.current()); DoublePointData firstCollection = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); - aggregatorHandle.recordDouble(1.0); + aggregatorHandle.recordDouble(1.0, Attributes.empty(), Context.current()); DoublePointData secondCollection = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); 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 2a4f6ecf11c..1cf98c58aca 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 @@ -12,6 +12,7 @@ import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; @@ -24,7 +25,7 @@ import io.opentelemetry.sdk.metrics.internal.data.ImmutableMetricData; import io.opentelemetry.sdk.metrics.internal.data.MutableLongPointData; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; import io.opentelemetry.sdk.resources.Resource; import java.util.Collections; import java.util.List; @@ -42,7 +43,7 @@ class LongLastValueAggregatorTest { private LongLastValueAggregator aggregator; private void init(MemoryMode memoryMode) { - aggregator = new LongLastValueAggregator(ExemplarReservoir::longNoSamples, memoryMode); + aggregator = new LongLastValueAggregator(ExemplarReservoirFactory.noSamples(), memoryMode); } @ParameterizedTest @@ -56,15 +57,15 @@ void createHandle(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void multipleRecords(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(12); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(12L); - aggregatorHandle.recordLong(13); - aggregatorHandle.recordLong(14); + aggregatorHandle.recordLong(13, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(14, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -76,16 +77,16 @@ void multipleRecords(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void aggregateThenMaybeReset(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(13); + aggregatorHandle.recordLong(13, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(13L); - aggregatorHandle.recordLong(12); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -189,8 +190,8 @@ void copyPoint(MemoryMode memoryMode) { void toMetricData(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(10); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(10, Attributes.empty(), Context.current()); MetricData metricData = aggregator.toMetricData( @@ -217,12 +218,12 @@ void toMetricData(MemoryMode memoryMode) { @Test void testReusablePointOnCollect() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle handle = aggregator.createHandle(); - handle.recordLong(1); + AggregatorHandle handle = aggregator.createHandle(); + handle.recordLong(1, Attributes.empty(), Context.current()); LongPointData pointData = handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); - handle.recordLong(1); + handle.recordLong(1, Attributes.empty(), Context.current()); LongPointData pointData2 = handle.aggregateThenMaybeReset(0, 10, Attributes.empty(), /* reset= */ false); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongSumAggregatorTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongSumAggregatorTest.java index 408403fd952..d2742050ea0 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongSumAggregatorTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/aggregator/LongSumAggregatorTest.java @@ -27,7 +27,9 @@ import io.opentelemetry.sdk.metrics.internal.descriptor.Advice; import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor; import io.opentelemetry.sdk.metrics.internal.descriptor.MetricDescriptor; -import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.DoubleExemplarReservoir; +import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarReservoirFactory; +import io.opentelemetry.sdk.metrics.internal.exemplar.LongExemplarReservoir; import io.opentelemetry.sdk.resources.Resource; import java.util.Collections; import java.util.List; @@ -43,7 +45,19 @@ @ExtendWith(MockitoExtension.class) class LongSumAggregatorTest { - @Mock ExemplarReservoir reservoir; + @Mock LongExemplarReservoir reservoir; + private final ExemplarReservoirFactory reservoirFactory = + new ExemplarReservoirFactory() { + @Override + public DoubleExemplarReservoir createDoubleExemplarReservoir() { + throw new UnsupportedOperationException(); + } + + @Override + public LongExemplarReservoir createLongExemplarReservoir() { + return reservoir; + } + }; private static final Resource resource = Resource.getDefault(); private static final InstrumentationScopeInfo library = InstrumentationScopeInfo.empty(); @@ -61,7 +75,7 @@ private void init(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.LONG, Advice.empty()), - ExemplarReservoir::longNoSamples, + ExemplarReservoirFactory.noSamples(), memoryMode); } @@ -76,12 +90,12 @@ void createHandle(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void multipleRecords(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -93,13 +107,13 @@ void multipleRecords(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void multipleRecords_WithNegatives(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(-23); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(-11); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(-23, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(-11, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -111,18 +125,18 @@ void multipleRecords_WithNegatives(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void aggregateThenMaybeReset(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(13); - aggregatorHandle.recordLong(12); + aggregatorHandle.recordLong(13, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) .getValue()) .isEqualTo(25); - aggregatorHandle.recordLong(12); - aggregatorHandle.recordLong(-25); + aggregatorHandle.recordLong(12, Attributes.empty(), Context.current()); + aggregatorHandle.recordLong(-25, Attributes.empty(), Context.current()); assertThat( aggregatorHandle .aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true) @@ -145,7 +159,7 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { TraceState.getDefault()), 1); List exemplars = Collections.singletonList(exemplar); - Mockito.when(reservoir.collectAndReset(Attributes.empty())).thenReturn(exemplars); + Mockito.when(reservoir.collectAndResetLongs(Attributes.empty())).thenReturn(exemplars); LongSumAggregator aggregator = new LongSumAggregator( InstrumentDescriptor.create( @@ -155,9 +169,9 @@ void aggregateThenMaybeReset_WithExemplars(MemoryMode memoryMode) { InstrumentType.COUNTER, InstrumentValueType.LONG, Advice.empty()), - () -> reservoir, + reservoirFactory, memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); aggregatorHandle.recordLong(0, attributes, Context.root()); assertThat( aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true)) @@ -189,7 +203,7 @@ void mergeAndDiff(MemoryMode memoryMode) { instrumentType, InstrumentValueType.LONG, Advice.empty()), - ExemplarReservoir::longNoSamples, + ExemplarReservoirFactory.noSamples(), memoryMode); LongPointData diffed = @@ -299,8 +313,8 @@ void copyPoint(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void toMetricData(MemoryMode memoryMode) { init(memoryMode); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(10); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); + aggregatorHandle.recordLong(10, Attributes.empty(), Context.current()); MetricData metricData = aggregator.toMetricData( @@ -360,13 +374,13 @@ void toMetricDataWithExemplars(MemoryMode memoryMode) { @Test void sameObjectReturnedOnReusableDataMemoryMode() { init(MemoryMode.REUSABLE_DATA); - AggregatorHandle aggregatorHandle = aggregator.createHandle(); + AggregatorHandle aggregatorHandle = aggregator.createHandle(); - aggregatorHandle.recordLong(1L); + aggregatorHandle.recordLong(1L, Attributes.empty(), Context.current()); LongPointData firstCollection = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); - aggregatorHandle.recordLong(1L); + aggregatorHandle.recordLong(1L, Attributes.empty(), Context.current()); LongPointData secondCollection = aggregatorHandle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ false); diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoirTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoirTest.java index a7b0b0a756b..7e4262981f3 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoirTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/FilteredExemplarReservoirTest.java @@ -8,12 +8,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import java.util.Collections; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -22,31 +23,56 @@ @ExtendWith(MockitoExtension.class) class FilteredExemplarReservoirTest { - @Mock ExemplarReservoir reservoir; + @Mock DoubleExemplarReservoir doubleReservoir; + @Mock LongExemplarReservoir longReservoir; @Mock ExemplarFilter filter; @Test - void testFilter_preventsSampling() { + void testFilterDouble_preventsSampling() { when(filter.shouldSampleMeasurement(anyDouble(), any(), any())).thenReturn(false); - ExemplarReservoir filtered = - new FilteredExemplarReservoir<>(filter, reservoir); + DoubleExemplarReservoir filtered = new DoubleFilteredExemplarReservoir(filter, doubleReservoir); filtered.offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); + verify(doubleReservoir, never()).offerDoubleMeasurement(anyDouble(), any(), any()); } @Test - void testFilter_allowsSampling() { + void testFilterLong_preventsSampling() { + when(filter.shouldSampleMeasurement(anyLong(), any(), any())).thenReturn(false); + LongExemplarReservoir filtered = new LongFilteredExemplarReservoir(filter, longReservoir); + filtered.offerLongMeasurement(1L, Attributes.empty(), Context.root()); + verify(longReservoir, never()).offerLongMeasurement(anyLong(), any(), any()); + } + + @Test + void testFilterDouble_allowsSampling() { when(filter.shouldSampleMeasurement(anyDouble(), any(), any())).thenReturn(true); - ExemplarReservoir filtered = - new FilteredExemplarReservoir<>(filter, reservoir); + DoubleExemplarReservoir filtered = new DoubleFilteredExemplarReservoir(filter, doubleReservoir); filtered.offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); - verify(reservoir).offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); + verify(doubleReservoir).offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); + } + + @Test + void testFilterLong_allowsSampling() { + when(filter.shouldSampleMeasurement(anyLong(), any(), any())).thenReturn(true); + LongExemplarReservoir filtered = new LongFilteredExemplarReservoir(filter, longReservoir); + filtered.offerLongMeasurement(1L, Attributes.empty(), Context.root()); + verify(longReservoir).offerLongMeasurement(1L, Attributes.empty(), Context.root()); + } + + @Test + void reservoirDouble_collectsUnderlying() { + when(doubleReservoir.collectAndResetDoubles(Attributes.empty())) + .thenReturn(Collections.emptyList()); + DoubleExemplarReservoir filtered = + new DoubleFilteredExemplarReservoir(filter, doubleReservoir) {}; + assertThat(filtered.collectAndResetDoubles(Attributes.empty())).isEmpty(); } @Test - void reservoir_collectsUnderlying() { - when(reservoir.collectAndReset(Attributes.empty())).thenReturn(Collections.emptyList()); - ExemplarReservoir filtered = - new FilteredExemplarReservoir<>(filter, reservoir); - assertThat(filtered.collectAndReset(Attributes.empty())).isEmpty(); + void reservoirLong_collectsUnderlying() { + when(longReservoir.collectAndResetLongs(Attributes.empty())) + .thenReturn(Collections.emptyList()); + LongExemplarReservoir filtered = new LongFilteredExemplarReservoir(filter, longReservoir) {}; + assertThat(filtered.collectAndResetLongs(Attributes.empty())).isEmpty(); } } diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoirTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoirTest.java index a6882dfe797..0a4963b03ff 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoirTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/HistogramExemplarReservoirTest.java @@ -10,7 +10,6 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.testing.time.TestClock; import java.time.Duration; import java.util.Arrays; @@ -21,18 +20,18 @@ class HistogramExemplarReservoirTest { @Test void noMeasurement_returnsEmpty() { TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = + HistogramExemplarReservoir reservoir = new HistogramExemplarReservoir(clock, Collections.emptyList()); - assertThat(reservoir.collectAndReset(Attributes.empty())).isEmpty(); + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())).isEmpty(); } @Test void oneBucket_samplesEverything() { TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = + HistogramExemplarReservoir reservoir = new HistogramExemplarReservoir(clock, Collections.emptyList()); reservoir.offerDoubleMeasurement(1.1, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -43,7 +42,7 @@ void oneBucket_samplesEverything() { // Measurement count is reset, we should sample a new measurement (and only one) clock.advance(Duration.ofSeconds(1)); reservoir.offerDoubleMeasurement(2, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -55,7 +54,7 @@ void oneBucket_samplesEverything() { clock.advance(Duration.ofSeconds(1)); reservoir.offerDoubleMeasurement(3, Attributes.empty(), Context.root()); reservoir.offerDoubleMeasurement(4, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -69,13 +68,13 @@ void oneBucket_samplesEverything() { void multipleBuckets_samplesIntoCorrectBucket() { TestClock clock = TestClock.create(); AttributeKey bucketKey = AttributeKey.longKey("bucket"); - ExemplarReservoir reservoir = + HistogramExemplarReservoir reservoir = new HistogramExemplarReservoir(clock, Arrays.asList(0d, 10d, 20d)); reservoir.offerDoubleMeasurement(-1.1, Attributes.of(bucketKey, 0L), Context.root()); reservoir.offerDoubleMeasurement(1, Attributes.of(bucketKey, 1L), Context.root()); reservoir.offerDoubleMeasurement(11, Attributes.of(bucketKey, 2L), Context.root()); reservoir.offerDoubleMeasurement(21, Attributes.of(bucketKey, 3L), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(4) .satisfiesExactlyInAnyOrder( e -> { @@ -99,10 +98,10 @@ void multipleBuckets_samplesIntoCorrectBucket() { @Test void longMeasurement_CastsToDouble() { TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = + HistogramExemplarReservoir reservoir = new HistogramExemplarReservoir(clock, Collections.emptyList()); reservoir.offerLongMeasurement(1L, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -113,7 +112,7 @@ void longMeasurement_CastsToDouble() { // Measurement count is reset, we should sample a new measurement (and only one) clock.advance(Duration.ofSeconds(1)); reservoir.offerLongMeasurement(2, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongRandomFixedSizeExemplarReservoirTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongRandomFixedSizeExemplarReservoirTest.java deleted file mode 100644 index fc754576401..00000000000 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongRandomFixedSizeExemplarReservoirTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.metrics.internal.exemplar; - -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; - -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanContext; -import io.opentelemetry.api.trace.TraceFlags; -import io.opentelemetry.api.trace.TraceState; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.internal.RandomSupplier; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; -import io.opentelemetry.sdk.testing.time.TestClock; -import java.time.Duration; -import java.util.Random; -import org.junit.jupiter.api.Test; - -class LongRandomFixedSizeExemplarReservoirTest { - private static final String TRACE_ID = "ff000000000000000000000000000041"; - private static final String SPAN_ID = "ff00000000000041"; - - @Test - public void noMeasurement_returnsEmpty() { - TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createLong(clock, 1, RandomSupplier.platformDefault()); - assertThat(reservoir.collectAndReset(Attributes.empty())).isEmpty(); - } - - @Test - public void oneMeasurement_alwaysSamplesFirstMeasurement() { - TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createLong(clock, 1, RandomSupplier.platformDefault()); - reservoir.offerLongMeasurement(1, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) - .hasSize(1) - .satisfiesExactly( - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(1); - assertThat(exemplar.getFilteredAttributes()).isEmpty(); - }); - - // Measurement count is reset, we should sample a new measurement (and only one) - clock.advance(Duration.ofSeconds(1)); - reservoir.offerLongMeasurement(2, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) - .hasSize(1) - .satisfiesExactly( - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(2); - assertThat(exemplar.getFilteredAttributes()).isEmpty(); - }); - } - - @Test - public void oneMeasurement_filtersAttributes() { - Attributes all = - Attributes.builder().put("one", 1).put("two", "two").put("three", true).build(); - Attributes partial = Attributes.builder().put("three", true).build(); - Attributes remaining = Attributes.builder().put("one", 1).put("two", "two").build(); - TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createLong(clock, 1, RandomSupplier.platformDefault()); - reservoir.offerLongMeasurement(1, all, Context.root()); - assertThat(reservoir.collectAndReset(partial)) - .satisfiesExactly( - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(1); - assertThat(exemplar.getFilteredAttributes()).isEqualTo(remaining); - }); - } - - @Test - public void oneMeasurement_includesTraceAndSpanIds() { - Attributes all = - Attributes.builder().put("one", 1).put("two", "two").put("three", true).build(); - Context context = - Context.root() - .with( - Span.wrap( - SpanContext.createFromRemoteParent( - TRACE_ID, SPAN_ID, TraceFlags.getSampled(), TraceState.getDefault()))); - TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createLong(clock, 1, RandomSupplier.platformDefault()); - reservoir.offerLongMeasurement(1, all, context); - assertThat(reservoir.collectAndReset(Attributes.empty())) - .satisfiesExactly( - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(1); - assertThat(exemplar.getFilteredAttributes()).isEqualTo(all); - assertThat(exemplar.getSpanContext().getTraceId()).isEqualTo(TRACE_ID); - assertThat(exemplar.getSpanContext().getSpanId()).isEqualTo(SPAN_ID); - }); - } - - @Test - public void multiMeasurements_preservesLatestSamples() { - AttributeKey key = AttributeKey.longKey("K"); - // We cannot mock random in latest jdk, so we create an override. - Random mockRandom = - new Random() { - @Override - public int nextInt(int max) { - switch (max) { - // Force one sample in bucket 1 and two in bucket 0. - case 2: - return 1; - default: - return 0; - } - } - }; - TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - ExemplarReservoir.longFixedSizeReservoir(clock, 2, () -> mockRandom); - reservoir.offerLongMeasurement(1, Attributes.of(key, 1L), Context.root()); - reservoir.offerLongMeasurement(2, Attributes.of(key, 2L), Context.root()); - reservoir.offerLongMeasurement(3, Attributes.of(key, 3L), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) - .satisfiesExactlyInAnyOrder( - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(2); - }, - exemplar -> { - assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); - assertThat(exemplar.getValue()).isEqualTo(3); - }); - } -} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoirTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoirTest.java deleted file mode 100644 index fc7a5a3c07a..00000000000 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/LongToDoubleExemplarReservoirTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.metrics.internal.exemplar; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.context.Context; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -class LongToDoubleExemplarReservoirTest { - @Mock ExemplarReservoir delegate; - - @Test - void offerDoubleMeasurement() { - ExemplarReservoir filtered = new LongToDoubleExemplarReservoir<>(delegate); - filtered.offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); - verify(delegate).offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); - verify(delegate, never()).offerLongMeasurement(anyLong(), any(), any()); - } - - @Test - void offerLongMeasurement() { - ExemplarReservoir filtered = new LongToDoubleExemplarReservoir<>(delegate); - filtered.offerLongMeasurement(1L, Attributes.empty(), Context.root()); - verify(delegate).offerDoubleMeasurement(1.0, Attributes.empty(), Context.root()); - verify(delegate, never()).offerLongMeasurement(anyLong(), any(), any()); - } -} diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleRandomFixedSizeExemplarReservoirTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoirTest.java similarity index 79% rename from sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleRandomFixedSizeExemplarReservoirTest.java rename to sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoirTest.java index 85a53fbeb0d..81b9a58bacc 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/DoubleRandomFixedSizeExemplarReservoirTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/exemplar/RandomFixedSizeExemplarReservoirTest.java @@ -15,31 +15,30 @@ import io.opentelemetry.api.trace.TraceState; import io.opentelemetry.context.Context; import io.opentelemetry.sdk.internal.RandomSupplier; -import io.opentelemetry.sdk.metrics.data.DoubleExemplarData; import io.opentelemetry.sdk.testing.time.TestClock; import java.time.Duration; import java.util.Random; import org.junit.jupiter.api.Test; -class DoubleRandomFixedSizeExemplarReservoirTest { +class RandomFixedSizeExemplarReservoirTest { private static final String TRACE_ID = "ff000000000000000000000000000041"; private static final String SPAN_ID = "ff00000000000041"; @Test public void noMeasurement_returnsEmpty() { TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createDouble(clock, 1, RandomSupplier.platformDefault()); - assertThat(reservoir.collectAndReset(Attributes.empty())).isEmpty(); + RandomFixedSizeExemplarReservoir reservoir = + RandomFixedSizeExemplarReservoir.create(clock, 1, RandomSupplier.platformDefault()); + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())).isEmpty(); } @Test public void oneMeasurement_alwaysSamplesFirstMeasurement() { TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createDouble(clock, 1, RandomSupplier.platformDefault()); + RandomFixedSizeExemplarReservoir reservoir = + RandomFixedSizeExemplarReservoir.create(clock, 1, RandomSupplier.platformDefault()); reservoir.offerDoubleMeasurement(1.1, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -51,7 +50,7 @@ public void oneMeasurement_alwaysSamplesFirstMeasurement() { // Measurement count is reset, we should sample a new measurement (and only one) clock.advance(Duration.ofSeconds(1)); reservoir.offerDoubleMeasurement(2, Attributes.empty(), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .hasSize(1) .satisfiesExactly( exemplar -> { @@ -68,10 +67,10 @@ public void oneMeasurement_filtersAttributes() { Attributes partial = Attributes.builder().put("three", true).build(); Attributes remaining = Attributes.builder().put("one", 1).put("two", "two").build(); TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createDouble(clock, 1, RandomSupplier.platformDefault()); + RandomFixedSizeExemplarReservoir reservoir = + RandomFixedSizeExemplarReservoir.create(clock, 1, RandomSupplier.platformDefault()); reservoir.offerDoubleMeasurement(1.1, all, Context.root()); - assertThat(reservoir.collectAndReset(partial)) + assertThat(reservoir.collectAndResetDoubles(partial)) .satisfiesExactly( exemplar -> { assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); @@ -91,10 +90,10 @@ public void oneMeasurement_includesTraceAndSpanIds() { SpanContext.createFromRemoteParent( TRACE_ID, SPAN_ID, TraceFlags.getSampled(), TraceState.getDefault()))); TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - RandomFixedSizeExemplarReservoir.createDouble(clock, 1, RandomSupplier.platformDefault()); + RandomFixedSizeExemplarReservoir reservoir = + RandomFixedSizeExemplarReservoir.create(clock, 1, RandomSupplier.platformDefault()); reservoir.offerDoubleMeasurement(1, all, context); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .satisfiesExactly( exemplar -> { assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); @@ -123,12 +122,13 @@ public int nextInt(int max) { } }; TestClock clock = TestClock.create(); - ExemplarReservoir reservoir = - ExemplarReservoir.doubleFixedSizeReservoir(clock, 2, () -> mockRandom); + DoubleExemplarReservoir reservoir = + ExemplarReservoirFactory.fixedSizeReservoir(clock, 2, () -> mockRandom) + .createDoubleExemplarReservoir(); reservoir.offerDoubleMeasurement(1, Attributes.of(key, 1L), Context.root()); reservoir.offerDoubleMeasurement(2, Attributes.of(key, 2L), Context.root()); reservoir.offerDoubleMeasurement(3, Attributes.of(key, 3L), Context.root()); - assertThat(reservoir.collectAndReset(Attributes.empty())) + assertThat(reservoir.collectAndResetDoubles(Attributes.empty())) .satisfiesExactlyInAnyOrder( exemplar -> { assertThat(exemplar.getEpochNanos()).isEqualTo(clock.now()); 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 d744a22c2db..860307d4777 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 @@ -67,8 +67,8 @@ class AsynchronousMetricStorageTest { @Mock private MetricReader reader; private RegisteredReader registeredReader; - private AsynchronousMetricStorage longCounterStorage; - private AsynchronousMetricStorage doubleCounterStorage; + private AsynchronousMetricStorage longCounterStorage; + private AsynchronousMetricStorage doubleCounterStorage; // Not using @BeforeEach since many methods require executing them for each MemoryMode void setup(MemoryMode memoryMode) { @@ -161,7 +161,7 @@ void recordDouble(MemoryMode memoryMode) { void record_ProcessesAttributes(MemoryMode memoryMode) { setup(memoryMode); - AsynchronousMetricStorage storage = + AsynchronousMetricStorage storage = AsynchronousMetricStorage.create( registeredReader, RegisteredView.create( diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/CallbackRegistrationTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/CallbackRegistrationTest.java index b6bc13a858c..80d02c90ff9 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/CallbackRegistrationTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/CallbackRegistrationTest.java @@ -67,9 +67,9 @@ class CallbackRegistrationTest { LogCapturer logs = LogCapturer.create().captureForType(CallbackRegistration.class); @Mock private MetricReader reader; - @Mock private AsynchronousMetricStorage storage1; - @Mock private AsynchronousMetricStorage storage2; - @Mock private AsynchronousMetricStorage storage3; + @Mock private AsynchronousMetricStorage storage1; + @Mock private AsynchronousMetricStorage storage2; + @Mock private AsynchronousMetricStorage storage3; private RegisteredReader registeredReader; private SdkObservableMeasurement measurement1; diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorageTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorageTest.java index bc1f5acffdd..e79f3ad9718 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorageTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/state/SynchronousMetricStorageTest.java @@ -26,8 +26,6 @@ import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.InstrumentValueType; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; -import io.opentelemetry.sdk.metrics.data.ExemplarData; -import io.opentelemetry.sdk.metrics.data.LongExemplarData; import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; @@ -84,7 +82,7 @@ public class SynchronousMetricStorageTest { private RegisteredReader deltaReader; private RegisteredReader cumulativeReader; private final TestClock testClock = TestClock.create(); - private Aggregator aggregator; + private Aggregator aggregator; private final AttributesProcessor attributesProcessor = AttributesProcessor.noop(); private void initialize(MemoryMode memoryMode) { @@ -111,7 +109,7 @@ private void initialize(MemoryMode memoryMode) { @EnumSource(MemoryMode.class) void recordDouble_NaN(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( cumulativeReader, METRIC_DESCRIPTOR, @@ -162,7 +160,7 @@ void attributesProcessor_applied(MemoryMode memoryMode) { void recordAndCollect_CumulativeDoesNotReset(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( cumulativeReader, METRIC_DESCRIPTOR, @@ -211,7 +209,7 @@ void recordAndCollect_CumulativeDoesNotReset(MemoryMode memoryMode) { void recordAndCollect_DeltaResets_ImmutableData() { initialize(IMMUTABLE_DATA); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -265,7 +263,7 @@ void recordAndCollect_DeltaResets_ImmutableData() { void recordAndCollect_DeltaResets_ReusableData() { initialize(MemoryMode.REUSABLE_DATA); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -368,7 +366,7 @@ void recordAndCollect_DeltaResets_ReusableData() { void recordAndCollect_CumulativeAtLimit(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( cumulativeReader, METRIC_DESCRIPTOR, @@ -440,7 +438,7 @@ void recordAndCollect_CumulativeAtLimit(MemoryMode memoryMode) { void recordAndCollect_DeltaAtLimit_ImmutableDataMemoryMode() { initialize(IMMUTABLE_DATA); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -541,7 +539,7 @@ void recordAndCollect_DeltaAtLimit_ImmutableDataMemoryMode() { void recordAndCollect_DeltaAtLimit_ReusableDataMemoryMode() { initialize(MemoryMode.REUSABLE_DATA); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -628,7 +626,7 @@ void recordAndCollect_DeltaAtLimit_ReusableDataMemoryMode() { void recordAndCollect_DeltaAtLimit_ReusableDataMemoryMode_ExpireUnused() { initialize(MemoryMode.REUSABLE_DATA); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -771,7 +769,7 @@ private static void assertOverflowDoesNotExists(MetricData metricData) { @ParameterizedTest @MethodSource("concurrentStressTestArguments") void recordAndCollect_concurrentStressTest( - DefaultSynchronousMetricStorage storage, BiConsumer collect) { + DefaultSynchronousMetricStorage storage, BiConsumer collect) { // Define record threads. Each records a value of 1.0, 2000 times List threads = new ArrayList<>(); CountDownLatch latch = new CountDownLatch(4); @@ -826,7 +824,7 @@ private static Stream concurrentStressTestArguments() { List argumentsList = new ArrayList<>(); for (MemoryMode memoryMode : MemoryMode.values()) { - Aggregator aggregator = + Aggregator aggregator = ((AggregatorFactory) Aggregation.sum()) .createAggregator(DESCRIPTOR, ExemplarFilter.alwaysOff(), memoryMode); @@ -872,7 +870,7 @@ private static Stream concurrentStressTestArguments() { void enabledThenDisable_isEnabled(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -891,7 +889,7 @@ void enabledThenDisable_isEnabled(MemoryMode memoryMode) { void enabledThenDisableThenEnable_isEnabled(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -911,7 +909,7 @@ void enabledThenDisableThenEnable_isEnabled(MemoryMode memoryMode) { void enabledThenDisable_recordAndCollect(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, @@ -932,7 +930,7 @@ void enabledThenDisable_recordAndCollect(MemoryMode memoryMode) { void enabledThenDisableThenEnable_recordAndCollect(MemoryMode memoryMode) { initialize(memoryMode); - DefaultSynchronousMetricStorage storage = + DefaultSynchronousMetricStorage storage = new DefaultSynchronousMetricStorage<>( deltaReader, METRIC_DESCRIPTOR, diff --git a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregationTest.java b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregationTest.java index 0479baafde3..57e096e01c1 100644 --- a/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregationTest.java +++ b/sdk/metrics/src/test/java/io/opentelemetry/sdk/metrics/internal/view/Base2ExponentialHistogramAggregationTest.java @@ -9,11 +9,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.Aggregation; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.InstrumentValueType; -import io.opentelemetry.sdk.metrics.data.ExemplarData; import io.opentelemetry.sdk.metrics.data.ExponentialHistogramPointData; import io.opentelemetry.sdk.metrics.internal.aggregator.Aggregator; import io.opentelemetry.sdk.metrics.internal.aggregator.AggregatorFactory; @@ -47,7 +47,7 @@ void invalidConfig_Throws() { @Test void minimumBucketsCanAccommodateMaxRange() { Aggregation aggregation = Base2ExponentialHistogramAggregation.create(2, 20); - Aggregator aggregator = + Aggregator aggregator = ((AggregatorFactory) aggregation) .createAggregator( InstrumentDescriptor.create( @@ -59,11 +59,10 @@ void minimumBucketsCanAccommodateMaxRange() { Advice.empty()), ExemplarFilter.alwaysOff(), MemoryMode.IMMUTABLE_DATA); - AggregatorHandle handle = - aggregator.createHandle(); + AggregatorHandle handle = aggregator.createHandle(); // Record max range - handle.recordDouble(Double.MIN_VALUE); - handle.recordDouble(Double.MAX_VALUE); + handle.recordDouble(Double.MIN_VALUE, Attributes.empty(), Context.current()); + handle.recordDouble(Double.MAX_VALUE, Attributes.empty(), Context.current()); ExponentialHistogramPointData pointData = handle.aggregateThenMaybeReset(0, 1, Attributes.empty(), /* reset= */ true);