Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c01ceab
Add recordMinMax param to histogram aggregations per spec
MikeGoldsmith Feb 16, 2026
8f364a5
Add tests for recordMinMax=false behavior
MikeGoldsmith Feb 16, 2026
e584f31
Update API diff for recordMinMax methods
MikeGoldsmith Feb 16, 2026
6e30bcb
Add tests for recordMinMax parameter in AggregationFactory
MikeGoldsmith Feb 16, 2026
3d34d6c
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java i…
MikeGoldsmith Feb 20, 2026
849cc50
Address review feedback
MikeGoldsmith Feb 20, 2026
7aaab68
Include recordMinMax in Aggregation toString()
MikeGoldsmith Feb 20, 2026
ec038ac
Apply spotless formatting
MikeGoldsmith Feb 20, 2026
d944b29
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java i…
MikeGoldsmith Feb 24, 2026
94da36b
Add HistogramOptions builder for histogram behavioral options
MikeGoldsmith Feb 24, 2026
e704187
Rename isRecordMinMax() to recordMinMax()
MikeGoldsmith Feb 27, 2026
542cf4d
Add ExplicitBucketHistogramOptions and Base2ExponentialHistogramOptio…
MikeGoldsmith Feb 27, 2026
565b91d
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java i…
MikeGoldsmith Feb 27, 2026
78e2805
Align histogram options with SpanLimits/LogLimits/RetryPolicy pattern
MikeGoldsmith Mar 2, 2026
3c5ac63
Merge branch 'main' of github.com:open-telemetry/opentelemetry-java i…
MikeGoldsmith Mar 2, 2026
dae105e
Fix deprecated API usage in PrometheusMetricReaderTest
MikeGoldsmith Mar 2, 2026
d881add
Apply suggestions from code review
MikeGoldsmith Mar 3, 2026
82cf7a9
regenerate docs
MikeGoldsmith Mar 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
Comparing source compatibility of opentelemetry-sdk-metrics-1.60.0-SNAPSHOT.jar against opentelemetry-sdk-metrics-1.59.0.jar
No changes.
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.Aggregation (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
=== UNCHANGED METHOD: PUBLIC STATIC io.opentelemetry.sdk.metrics.Aggregation base2ExponentialBucketHistogram(int, int)
+++ NEW ANNOTATION: java.lang.Deprecated
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.Aggregation base2ExponentialBucketHistogram(io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions)
=== UNCHANGED METHOD: PUBLIC STATIC io.opentelemetry.sdk.metrics.Aggregation explicitBucketHistogram(java.util.List<java.lang.Double><java.lang.Double>)
+++ NEW ANNOTATION: java.lang.Deprecated
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.Aggregation explicitBucketHistogram(io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions)
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder builder()
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions getDefault()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) int getMaxBuckets()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) int getMaxScale()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) boolean getRecordMinMax()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder toBuilder()
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions build()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder setMaxBuckets(int)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder setMaxScale(int)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions$Builder setRecordMinMax(boolean)
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions$Builder builder()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) java.util.List<java.lang.Double> getBucketBoundaries()
+++ NEW ANNOTATION: javax.annotation.Nullable
+++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions getDefault()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) boolean getRecordMinMax()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions$Builder toBuilder()
+++ NEW CLASS: PUBLIC(+) ABSTRACT(+) STATIC(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions$Builder (not serializable)
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
+++ NEW SUPERCLASS: java.lang.Object
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions build()
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions$Builder setBucketBoundaries(java.util.List<java.lang.Double>)
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions$Builder setRecordMinMax(boolean)
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.View;
Expand Down Expand Up @@ -782,7 +783,12 @@ void exponentialHistogramBucketConversion() {
.registerView(
InstrumentSelector.builder().setName("my.exponential.histogram").build(),
View.builder()
.setAggregation(Aggregation.base2ExponentialBucketHistogram(160, otelScale))
.setAggregation(
Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder()
.setMaxBuckets(160)
.setMaxScale(otelScale)
.build()))
.build())
.build()
.meterBuilder("test")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Base2ExponentialBucketHistogramAggregationModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogramAggregationModel;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions;
import io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions;
import java.util.List;

final class AggregationFactory implements Factory<AggregationModel, Aggregation> {
Expand Down Expand Up @@ -37,15 +39,20 @@ public Aggregation create(AggregationModel model, DeclarativeConfigContext conte
model.getBase2ExponentialBucketHistogram();
if (exponentialBucketHistogram != null) {
Integer maxScale = exponentialBucketHistogram.getMaxScale();
if (maxScale == null) {
maxScale = 20;
}
Integer maxSize = exponentialBucketHistogram.getMaxSize();
if (maxSize == null) {
maxSize = 160;
Boolean recordMinMax = exponentialBucketHistogram.getRecordMinMax();
Base2ExponentialHistogramOptions.Builder builder = Base2ExponentialHistogramOptions.builder();
if (maxScale != null) {
builder.setMaxScale(maxScale);
}
if (maxSize != null) {
builder.setMaxBuckets(maxSize);
}
if (recordMinMax != null) {
builder.setRecordMinMax(recordMinMax);
}
try {
return Aggregation.base2ExponentialBucketHistogram(maxSize, maxScale);
return Aggregation.base2ExponentialBucketHistogram(builder.build());
} catch (IllegalArgumentException e) {
throw new DeclarativeConfigException("Invalid exponential bucket histogram", e);
}
Expand All @@ -54,11 +61,16 @@ public Aggregation create(AggregationModel model, DeclarativeConfigContext conte
model.getExplicitBucketHistogram();
if (explicitBucketHistogram != null) {
List<Double> boundaries = explicitBucketHistogram.getBoundaries();
if (boundaries == null) {
return Aggregation.explicitBucketHistogram();
Boolean recordMinMax = explicitBucketHistogram.getRecordMinMax();
ExplicitBucketHistogramOptions.Builder builder = ExplicitBucketHistogramOptions.builder();
if (boundaries != null) {
builder.setBucketBoundaries(boundaries);
}
if (recordMinMax != null) {
builder.setRecordMinMax(recordMinMax);
}
try {
return Aggregation.explicitBucketHistogram(boundaries);
return Aggregation.explicitBucketHistogram(builder.build());
} catch (IllegalArgumentException e) {
throw new DeclarativeConfigException("Invalid explicit bucket histogram", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions;
import io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.InstrumentSelectorBuilder;
import io.opentelemetry.sdk.metrics.InstrumentType;
Expand Down Expand Up @@ -203,7 +205,8 @@ static Aggregation toAggregation(String aggregationName, Map<String, Object> agg
if (Aggregation.explicitBucketHistogram().equals(aggregation)) {
List<Double> bucketBoundaries = getBucketBoundaries(aggregationArgs);
if (bucketBoundaries != null) {
return Aggregation.explicitBucketHistogram(bucketBoundaries);
return Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder().setBucketBoundaries(bucketBoundaries).build());
}
}
if (Aggregation.base2ExponentialBucketHistogram().equals(aggregation)) {
Expand All @@ -215,7 +218,8 @@ static Aggregation toAggregation(String aggregationName, Map<String, Object> agg
}
// TODO: support configuring max_scale
if (maxBuckets != null) {
return Aggregation.base2ExponentialBucketHistogram(maxBuckets, 20);
return Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder().setMaxBuckets(maxBuckets).build());
}
}
return aggregation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LastValueAggregationModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SumAggregationModel;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions;
import io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions;
import java.util.Arrays;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -51,7 +53,11 @@ private static Stream<Arguments> createTestCases() {
new Base2ExponentialBucketHistogramAggregationModel()
.withMaxSize(2)
.withMaxScale(2)),
Aggregation.base2ExponentialBucketHistogram(2, 2)),
Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder()
.setMaxBuckets(2)
.setMaxScale(2)
.build())),
Arguments.of(
new AggregationModel()
.withExplicitBucketHistogram(
Expand All @@ -62,6 +68,67 @@ private static Stream<Arguments> createTestCases() {
.withExplicitBucketHistogram(
new ExplicitBucketHistogramAggregationModel()
.withBoundaries(Arrays.asList(1.0, 2.0))),
Aggregation.explicitBucketHistogram(Arrays.asList(1.0, 2.0))));
Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder()
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
.build())),
// Test recordMinMax parameter for explicit bucket histogram
Arguments.of(
new AggregationModel()
.withExplicitBucketHistogram(
new ExplicitBucketHistogramAggregationModel()
.withBoundaries(Arrays.asList(1.0, 2.0))
.withRecordMinMax(true)),
Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder()
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
.setRecordMinMax(true)
.build())),
Arguments.of(
new AggregationModel()
.withExplicitBucketHistogram(
new ExplicitBucketHistogramAggregationModel()
.withBoundaries(Arrays.asList(1.0, 2.0))
.withRecordMinMax(false)),
Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder()
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
.setRecordMinMax(false)
.build())),
Arguments.of(
new AggregationModel()
.withExplicitBucketHistogram(
new ExplicitBucketHistogramAggregationModel()
.withBoundaries(null)
.withRecordMinMax(false)),
Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder().setRecordMinMax(false).build())),
// Test recordMinMax parameter for exponential bucket histogram
Arguments.of(
new AggregationModel()
.withBase2ExponentialBucketHistogram(
new Base2ExponentialBucketHistogramAggregationModel()
.withMaxSize(2)
.withMaxScale(2)
.withRecordMinMax(true)),
Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder()
.setMaxBuckets(2)
.setMaxScale(2)
.setRecordMinMax(true)
.build())),
Arguments.of(
new AggregationModel()
.withBase2ExponentialBucketHistogram(
new Base2ExponentialBucketHistogramAggregationModel()
.withMaxSize(2)
.withMaxScale(2)
.withRecordMinMax(false)),
Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder()
.setMaxBuckets(2)
.setMaxScale(2)
.setRecordMinMax(false)
.build())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.IncludeExcludeModel;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ViewStreamModel;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions;
import io.opentelemetry.sdk.metrics.View;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -43,7 +44,11 @@ void create() {
.setAttributeFilter(
IncludeExcludePredicate.createExactMatching(
Arrays.asList("foo", "bar"), Collections.singletonList("baz")))
.setAggregation(Aggregation.explicitBucketHistogram(Arrays.asList(1.0, 2.0)))
.setAggregation(
Aggregation.explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder()
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
.build()))
.build();

View view =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ public enum HistogramAggregationParam {
new DoubleExplicitBucketHistogramAggregator(
ExplicitBucketHistogramUtils.createBoundaryArray(
ExplicitBucketHistogramUtils.DEFAULT_HISTOGRAM_BUCKET_BOUNDARIES),
/* recordMinMax= */ true,
ExemplarReservoirFactory.noSamples(),
IMMUTABLE_DATA)),
EXPLICIT_SINGLE_BUCKET(
new DoubleExplicitBucketHistogramAggregator(
ExplicitBucketHistogramUtils.createBoundaryArray(Collections.emptyList()),
/* recordMinMax= */ true,
ExemplarReservoirFactory.noSamples(),
IMMUTABLE_DATA)),
EXPONENTIAL_SMALL_CIRCULAR_BUFFER(
new DoubleBase2ExponentialHistogramAggregator(
ExemplarReservoirFactory.noSamples(), 20, 0, IMMUTABLE_DATA)),
ExemplarReservoirFactory.noSamples(), 20, 0, /* recordMinMax= */ true, IMMUTABLE_DATA)),
EXPONENTIAL_CIRCULAR_BUFFER(
new DoubleBase2ExponentialHistogramAggregator(
ExemplarReservoirFactory.noSamples(), 160, 0, IMMUTABLE_DATA));
ExemplarReservoirFactory.noSamples(), 160, 0, /* recordMinMax= */ true, IMMUTABLE_DATA));

private final Aggregator<?> aggregator;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions;
import io.opentelemetry.sdk.metrics.ExemplarFilter;
import io.opentelemetry.sdk.metrics.InstrumentType;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
Expand Down Expand Up @@ -113,7 +114,8 @@ public enum AggregationGenerator {
EXPLICIT_BUCKET_HISTOGRAM(Aggregation.explicitBucketHistogram()),
DEFAULT_BASE2_EXPONENTIAL_BUCKET_HISTOGRAM(Aggregation.base2ExponentialBucketHistogram()),
ZERO_MAX_SCALE_BASE2_EXPONENTIAL_BUCKET_HISTOGRAM(
Aggregation.base2ExponentialBucketHistogram(160, 0));
Aggregation.base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder().setMaxBuckets(160).setMaxScale(0).build()));

private final Aggregation aggregation;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package io.opentelemetry.sdk.metrics;

import io.opentelemetry.sdk.metrics.data.MetricDataType;
import io.opentelemetry.sdk.metrics.internal.aggregator.ExplicitBucketHistogramUtils;
import io.opentelemetry.sdk.metrics.internal.view.Base2ExponentialHistogramAggregation;
import io.opentelemetry.sdk.metrics.internal.view.DefaultAggregation;
import io.opentelemetry.sdk.metrics.internal.view.DropAggregation;
Expand Down Expand Up @@ -64,9 +65,25 @@ static Aggregation explicitBucketHistogram() {
*
* @param bucketBoundaries A list of (inclusive) upper bounds for the histogram. Should be in
* order from lowest to highest.
* @deprecated Use {@link #explicitBucketHistogram(ExplicitBucketHistogramOptions)} instead.
*/
@Deprecated
static Aggregation explicitBucketHistogram(List<Double> bucketBoundaries) {
return ExplicitBucketHistogramAggregation.create(bucketBoundaries);
return explicitBucketHistogram(
ExplicitBucketHistogramOptions.builder().setBucketBoundaries(bucketBoundaries).build());
}

/**
* Aggregates measurements into an explicit bucket {@link MetricDataType#HISTOGRAM}.
*
* @param options histogram options
*/
static Aggregation explicitBucketHistogram(ExplicitBucketHistogramOptions options) {
List<Double> boundaries = options.getBucketBoundaries();
if (boundaries == null) {
boundaries = ExplicitBucketHistogramUtils.DEFAULT_HISTOGRAM_BUCKET_BOUNDARIES;
}
return ExplicitBucketHistogramAggregation.create(boundaries, options.getRecordMinMax());
}

/**
Expand All @@ -89,8 +106,25 @@ static Aggregation base2ExponentialBucketHistogram() {
* accommodated. Setting maxScale may reduce the number of downscales. Additionally, the
* performance of computing bucket index is improved when scale is {@code <= 0}.
* @since 1.23.0
* @deprecated Use {@link #base2ExponentialBucketHistogram(Base2ExponentialHistogramOptions)}
* instead.
*/
@Deprecated
static Aggregation base2ExponentialBucketHistogram(int maxBuckets, int maxScale) {
return Base2ExponentialHistogramAggregation.create(maxBuckets, maxScale);
return base2ExponentialBucketHistogram(
Base2ExponentialHistogramOptions.builder()
.setMaxBuckets(maxBuckets)
.setMaxScale(maxScale)
.build());
}

/**
* Aggregates measurements into a base-2 {@link MetricDataType#EXPONENTIAL_HISTOGRAM}.
*
* @param options histogram options
*/
static Aggregation base2ExponentialBucketHistogram(Base2ExponentialHistogramOptions options) {
return Base2ExponentialHistogramAggregation.create(
options.getMaxBuckets(), options.getMaxScale(), options.getRecordMinMax());
}
}
Loading
Loading