diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index 27391a6a7..749cfe4b6 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Run acceptance tests run: mise run acceptance-test diff --git a/.github/workflows/api-diff.yml b/.github/workflows/api-diff.yml index ea5566409..fc4cf2070 100644 --- a/.github/workflows/api-diff.yml +++ b/.github/workflows/api-diff.yml @@ -34,8 +34,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1aac83548..b2c57c817 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,8 +14,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/.github/workflows/bump-api-diff-baseline.yml b/.github/workflows/bump-api-diff-baseline.yml index a9d5e0328..ced6d6436 100644 --- a/.github/workflows/bump-api-diff-baseline.yml +++ b/.github/workflows/bump-api-diff-baseline.yml @@ -35,8 +35,8 @@ jobs: persist-credentials: true - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/.github/workflows/generate-protobuf.yml b/.github/workflows/generate-protobuf.yml index c21f21a65..a2666ebd8 100644 --- a/.github/workflows/generate-protobuf.yml +++ b/.github/workflows/generate-protobuf.yml @@ -20,8 +20,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/.github/workflows/github-pages.yaml b/.github/workflows/github-pages.yaml index 2d9c23ef1..722c2ce7c 100644 --- a/.github/workflows/github-pages.yaml +++ b/.github/workflows/github-pages.yaml @@ -39,8 +39,8 @@ jobs: fetch-depth: 0 - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 cache: "false" - name: Setup Pages id: pages diff --git a/.github/workflows/java-version-matrix-tests.yml b/.github/workflows/java-version-matrix-tests.yml index a9fe18a4a..58979b171 100644 --- a/.github/workflows/java-version-matrix-tests.yml +++ b/.github/workflows/java-version-matrix-tests.yml @@ -33,8 +33,8 @@ jobs: - name: Set up mise uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/.github/workflows/jmx-exporter-compatibility.yml b/.github/workflows/jmx-exporter-compatibility.yml index 93a72f909..b7cf4e8b1 100644 --- a/.github/workflows/jmx-exporter-compatibility.yml +++ b/.github/workflows/jmx-exporter-compatibility.yml @@ -24,8 +24,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 working_directory: .mise/envs/jmx-exporter - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 52600d464..ad8964bd8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,8 +23,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Lint env: diff --git a/.github/workflows/micrometer-compatibility.yml b/.github/workflows/micrometer-compatibility.yml index 32c358e54..2d15c0f8e 100644 --- a/.github/workflows/micrometer-compatibility.yml +++ b/.github/workflows/micrometer-compatibility.yml @@ -32,8 +32,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 working_directory: .mise/envs/micrometer - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index 90750250b..44cf92138 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -15,8 +15,8 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 working_directory: .mise/envs/native - name: Run native tests working-directory: .mise/envs/native diff --git a/.github/workflows/nightly-benchmarks.yml b/.github/workflows/nightly-benchmarks.yml index 9f91107e6..af4cffc68 100644 --- a/.github/workflows/nightly-benchmarks.yml +++ b/.github/workflows/nightly-benchmarks.yml @@ -36,8 +36,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/.github/workflows/regenerate-api-diff-otel.yml b/.github/workflows/regenerate-api-diff-otel.yml index ab8eef870..c35724644 100644 --- a/.github/workflows/regenerate-api-diff-otel.yml +++ b/.github/workflows/regenerate-api-diff-otel.yml @@ -20,8 +20,8 @@ jobs: persist-credentials: false - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c713c289e..4644f8ca3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,8 +71,8 @@ jobs: - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 cache: false - name: Build release version diff --git a/.github/workflows/test-release-build.yml b/.github/workflows/test-release-build.yml index 25332df64..e8a91f98b 100644 --- a/.github/workflows/test-release-build.yml +++ b/.github/workflows/test-release-build.yml @@ -20,8 +20,8 @@ jobs: fetch-depth: 0 - uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0 with: - version: v2026.6.14 - sha256: 96ae1ef7b00a6ebbbec23ba1016d6e722f5e904966272f621d15326429e90d53 + version: v2026.7.0 + sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68 - name: Cache local Maven repository uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java index 9a7f9b7c9..c4bb1f5fe 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Histogram.java @@ -614,7 +614,7 @@ private void doubleBucketWidth(Map buckets) { } buckets.clear(); for (i = 0; i < keys.length; i++) { - int index = (keys[i] + 1) / 2; + int index = (keys[i] > 0 ? keys[i] + 1 : keys[i]) / 2; LongAdder count = buckets.computeIfAbsent(index, k -> new LongAdder()); count.add(values[i]); } diff --git a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java index 69518205d..cbfd5fade 100644 --- a/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java +++ b/prometheus-metrics-core/src/test/java/io/prometheus/metrics/core/metrics/HistogramTest.java @@ -28,7 +28,9 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.concurrent.CompletionService; import java.util.concurrent.CountDownLatch; @@ -39,6 +41,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.LongAdder; import java.util.stream.Collectors; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -836,6 +839,36 @@ void testNativeBucketIndexToUpperBound() } } + @Test + void testDoubleBucketWidthMergesNegativeIndexesCorrectly() + throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Histogram histogram = Histogram.builder().name("test").nativeOnly().build(); + Histogram.DataPoint dataPoint = histogram.newDataPoint(); + + Method doubleBucketWidth = + Histogram.DataPoint.class.getDeclaredMethod("doubleBucketWidth", Map.class); + doubleBucketWidth.setAccessible(true); + + int[] keys = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}; + int[] expectedMergedIndexes = {-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3}; + + for (int i = 0; i < keys.length; i++) { + Map buckets = new HashMap<>(); + LongAdder adder = new LongAdder(); + adder.add(7); + buckets.put(keys[i], adder); + + doubleBucketWidth.invoke(dataPoint, buckets); + + assertThat(buckets.keySet()) + .as("merged index for original key " + keys[i]) + .containsExactly(expectedMergedIndexes[i]); + assertThat(buckets.get(expectedMergedIndexes[i]).sum()) + .as("count preserved for original key " + keys[i]) + .isEqualTo(7); + } + } + /** * Test if lowerBound < value <= upperBound is true for the bucket index returned by * findBucketIndex()