diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/distribution/TimeWindowPercentileHistogram.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/distribution/TimeWindowPercentileHistogram.java index 3e73b4867d..3ddb5f0d8a 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/distribution/TimeWindowPercentileHistogram.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/distribution/TimeWindowPercentileHistogram.java @@ -64,7 +64,10 @@ public TimeWindowPercentileHistogram(Clock clock, DistributionStatisticConfig di protected TimeWindowPercentileHistogram(Clock clock, DistributionStatisticConfig distributionStatisticConfig, boolean supportsAggregablePercentiles, boolean isCumulativeBucketCounts, boolean includeInfinityBucket) { super(clock, distributionStatisticConfig, DoubleRecorder.class); - intervalHistogram = new DoubleHistogram(percentilePrecision(distributionStatisticConfig)); + intervalHistogram = new DoubleHistogram(computeHighestToLowestValueRatio(distributionStatisticConfig), + percentilePrecision(distributionStatisticConfig)); + intervalHistogram.setAutoResize(true); + this.isCumulativeBucketCounts = isCumulativeBucketCounts; Set monitoredBuckets = distributionStatisticConfig.getHistogramBuckets(supportsAggregablePercentiles); @@ -80,7 +83,8 @@ protected TimeWindowPercentileHistogram(Clock clock, DistributionStatisticConfig @Override DoubleRecorder newBucket() { - return new DoubleRecorder(percentilePrecision(distributionStatisticConfig)); + return new DoubleRecorder(computeHighestToLowestValueRatio(distributionStatisticConfig), + percentilePrecision(distributionStatisticConfig)); } @Override @@ -100,7 +104,8 @@ void resetBucket(DoubleRecorder bucket) { @Override DoubleHistogram newAccumulatedHistogram(DoubleRecorder[] ringBuffer) { - return new DoubleHistogram(percentilePrecision(distributionStatisticConfig)); + return new DoubleHistogram(computeHighestToLowestValueRatio(distributionStatisticConfig), + percentilePrecision(distributionStatisticConfig)); } @Override @@ -143,6 +148,27 @@ private int percentilePrecision(DistributionStatisticConfig config) { return config.getPercentilePrecision() == null ? 1 : config.getPercentilePrecision(); } + /** + * Compute the highestToLowestValueRatio based on the configured min/max expected + * values. This allows HdrHistogram to cover the expected range without frequent + * resizing. + * @param config The distribution statistic configuration + * @return The computed ratio, or 2 if not enough information is available + */ + private long computeHighestToLowestValueRatio(DistributionStatisticConfig config) { + Double min = config.getMinimumExpectedValueAsDouble(); + Double max = config.getMaximumExpectedValueAsDouble(); + + // Only compute ratio if both min and max are explicitly set and finite + if (min != null && max != null && min > 0 && max > min && !Double.isInfinite(max)) { + // Compute the ratio, ensuring it's at least 2 + long ratio = (long) Math.ceil(max / min); + return Math.max(ratio, 2L); + } + + return 2L; + } + @Override void outputSummary(PrintStream out, double bucketScaling) { accumulatedHistogram().outputPercentileDistribution(out, bucketScaling);