rpuch commented on code in PR #7422:
URL: https://github.com/apache/ignite-3/pull/7422#discussion_r2832625275


##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java:
##########


Review Comment:
   That code without `try` protection looks a bit worrying. As far as I 
remember, according to Java VM spec, an exception can happen at any line. And 
we have a memory allocation here that can throw an OOME. How about adding 
another `try` block? Its contents could be extracted to a method to make the 
code less ugly



##########
modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java:
##########
@@ -537,4 +540,83 @@ void writeIntentsCursorRespectsStorageClosure() {
             assertThrows(StorageClosedException.class, cursor::next);
         }
     }
+
+    @Test
+    void verifyRunConsistentlyMetrics() {
+        RunConsistentlyMetrics metrics = 
((PersistentPageMemoryMvPartitionStorage) storage).consistencyMetrics;
+
+        // Verify metrics start at zero
+        
assertDistributionMetricRecordsCount(metrics.runConsistentlyDuration(), 0L);
+        assertMetricValue(metrics.runConsistentlyActiveCount(), 0);
+
+        // Execute a simple operation within runConsistently
+        storage.runConsistently(locker -> {
+            // Verify active count is incremented
+            assertMetricValue(metrics.runConsistentlyActiveCount(), 1);
+
+            insert(binaryRow, txId);
+
+            return null;
+        });
+
+        // Verify duration was recorded
+        
assertDistributionMetricRecordsCount(metrics.runConsistentlyDuration(), 1L);
+
+        // Verify active count is decremented back to zero
+        assertMetricValue(metrics.runConsistentlyActiveCount(), 0);
+
+        // Execute another operation
+        storage.runConsistently(locker -> {
+            assertMetricValue(metrics.runConsistentlyActiveCount(), 1);
+
+            return null;
+        });
+
+        // Verify another duration was recorded
+        
assertDistributionMetricRecordsCount(metrics.runConsistentlyDuration(), 2L);
+        assertMetricValue(metrics.runConsistentlyActiveCount(), 0);
+    }
+
+    @Test
+    void verifyNestedRunConsistentlyDoesNotDoubleCountMetrics() {
+        RunConsistentlyMetrics metrics = 
((PersistentPageMemoryMvPartitionStorage) storage).consistencyMetrics;
+
+        storage.runConsistently(outerLocker -> {
+            assertMetricValue(metrics.runConsistentlyActiveCount(), 1);
+
+            // Nested call
+            storage.runConsistently(innerLocker -> {
+                // Active count should not increase for nested calls
+                assertMetricValue(metrics.runConsistentlyActiveCount(), 1);
+
+                return null;
+            });
+
+            return null;
+        });
+
+        // Only one duration should be recorded for the outer call
+        
assertDistributionMetricRecordsCount(metrics.runConsistentlyDuration(), 1L);
+        assertMetricValue(metrics.runConsistentlyActiveCount(), 0);
+    }
+
+    private static void assertMetricValue(AtomicIntMetric metric, int value) {
+        assertThat(metric.value(), is(value));
+    }
+
+    /**
+     * Verifies that the specified distribution metric has recorded the 
expected total number of measurements.
+     *
+     * <p>
+     * Rather than checking individual histogram buckets, this method 
aggregates all recorded measurements across every bucket
+     * and confirms that the expected interaction was captured in at least one 
of them.
+     */
+    private static void 
assertDistributionMetricRecordsCount(DistributionMetric metric, long 
expectedMeasuresCount) {

Review Comment:
   I think I saw something similar before. Could it be extracted to reduce code 
duplication?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java:
##########
@@ -208,6 +218,10 @@ public <V> V runConsistently(WriteClosure<V> closure) 
throws StorageException {
                     locker0.unlockAll();
 
                     checkpointTimeoutLock.checkpointReadUnlock();
+
+                    long duration = System.nanoTime() - startTime;
+                    consistencyMetrics.recordRunConsistentlyDuration(duration);
+                    consistencyMetrics.decrementActiveCount();

Review Comment:
   Will we still pay the toll of maintaining these values if the corresponding 
metric source is disabled? Can we avoid it?



##########
modules/storage-page-memory/src/test/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorageTest.java:
##########
@@ -537,4 +540,83 @@ void writeIntentsCursorRespectsStorageClosure() {
             assertThrows(StorageClosedException.class, cursor::next);
         }
     }
+
+    @Test
+    void verifyRunConsistentlyMetrics() {
+        RunConsistentlyMetrics metrics = 
((PersistentPageMemoryMvPartitionStorage) storage).consistencyMetrics;
+
+        // Verify metrics start at zero
+        
assertDistributionMetricRecordsCount(metrics.runConsistentlyDuration(), 0L);
+        assertMetricValue(metrics.runConsistentlyActiveCount(), 0);
+
+        // Execute a simple operation within runConsistently
+        storage.runConsistently(locker -> {
+            // Verify active count is incremented
+            assertMetricValue(metrics.runConsistentlyActiveCount(), 1);
+
+            insert(binaryRow, txId);

Review Comment:
   Do we need this insertion at all for this test?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {

Review Comment:
   This is an array of bounds, should `bounds` be included in the name?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {
+            10_000,          // 10µs
+            100_000,         // 100µs
+            1_000_000,       // 1ms
+            10_000_000,      // 10ms
+            100_000_000,     // 100ms
+            1_000_000_000,   // 1s
+            10_000_000_000L, // 10s
+    };
+
+    private final DistributionMetric runConsistentlyDuration;
+    private final AtomicIntMetric runConsistentlyActiveCount;
+
+    /**
+     * Constructor.
+     *
+     * @param metricSource Metric source to register metrics with.
+     */
+    public RunConsistentlyMetrics(CollectionMetricSource metricSource) {
+        runConsistentlyDuration = metricSource.addMetric(new 
DistributionMetric(
+                "RunConsistentlyDuration",
+                "Time spent in runConsistently closures in nanoseconds.",
+                RUN_CONSISTENTLY_NANOS
+        ));
+
+        runConsistentlyActiveCount = metricSource.addMetric(new 
AtomicIntMetric(

Review Comment:
   In this case, this metric is going to be updated under heavy contention, so 
`LongAdderMetric` seems to be preferable



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java:
##########
@@ -99,6 +99,9 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
      */
     private final Object leaseInfoLock = new Object();
 
+    /** RunConsistently metrics. */
+    final RunConsistentlyMetrics consistencyMetrics;

Review Comment:
   'Consistency metrics' doesn't seem to be the perfect term here. When I read 
it, I immediately start thinking about 'how bad the consistency is broken' or 
'how much we are paying for consistency guarantees'. But here it's just 
'metrics of runConsistently primitive'. Should it be called just 
`runConsistentlyMetrics`, like its type, to avoid confusion?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java:
##########
@@ -99,6 +99,9 @@ public class PersistentPageMemoryMvPartitionStorage extends 
AbstractPageMemoryMv
      */
     private final Object leaseInfoLock = new Object();
 
+    /** RunConsistently metrics. */
+    final RunConsistentlyMetrics consistencyMetrics;

Review Comment:
   Let's expose it via a package-local (test-only) method and not a package 
local field



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java:
##########
@@ -65,29 +66,35 @@ public class PersistentPageMemoryTableStorage extends 
AbstractPageMemoryTableSto
 
     private final FailureProcessor failureProcessor;
 
+    private final RunConsistentlyMetrics consistencyMetrics;

Review Comment:
   `runConsistentlyMetrics`



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {
+            10_000,          // 10µs
+            100_000,         // 100µs
+            1_000_000,       // 1ms
+            10_000_000,      // 10ms
+            100_000_000,     // 100ms
+            1_000_000_000,   // 1s
+            10_000_000_000L, // 10s
+    };
+
+    private final DistributionMetric runConsistentlyDuration;
+    private final AtomicIntMetric runConsistentlyActiveCount;
+
+    /**
+     * Constructor.
+     *
+     * @param metricSource Metric source to register metrics with.
+     */
+    public RunConsistentlyMetrics(CollectionMetricSource metricSource) {
+        runConsistentlyDuration = metricSource.addMetric(new 
DistributionMetric(
+                "RunConsistentlyDuration",
+                "Time spent in runConsistently closures in nanoseconds.",
+                RUN_CONSISTENTLY_NANOS
+        ));
+
+        runConsistentlyActiveCount = metricSource.addMetric(new 
AtomicIntMetric(
+                "RunConsistentlyActiveCount",
+                "Current number of active runConsistently calls."
+        ));
+    }
+
+    /**
+     * Records the duration of a runConsistently closure execution in 
nanoseconds.
+     */
+    public void recordRunConsistentlyDuration(long durationNanos) {
+        runConsistentlyDuration.add(durationNanos);
+    }
+
+    /**
+     * Increments the active count of runConsistently calls.
+     */
+    public void incrementActiveCount() {
+        runConsistentlyActiveCount.increment();
+    }
+
+    /**
+     * Decrements the active count of runConsistently calls.
+     */
+    public void decrementActiveCount() {
+        runConsistentlyActiveCount.decrement();
+    }
+
+    /** Returns the runConsistently duration metric for testing. */
+    DistributionMetric runConsistentlyDuration() {

Review Comment:
   Should it be annotated as `@TestOnly` if it's only for testing?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>

Review Comment:
   Are those comments are results of experiments or they are just guesses? If 
it's the latter, let's remove them to avoid confusion. A ladder of values each 
of them is 10 times the previous one seems to be useful by itself, even without 
those interpretations



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {
+            10_000,          // 10µs
+            100_000,         // 100µs
+            1_000_000,       // 1ms
+            10_000_000,      // 10ms
+            100_000_000,     // 100ms
+            1_000_000_000,   // 1s
+            10_000_000_000L, // 10s

Review Comment:
   Please use TimeUnit.XXX.toNanos() here to make the code more readable. The 
tail comments will become unnecessary, and it will be a lot more difficult to 
make a mistake



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {
+            10_000,          // 10µs
+            100_000,         // 100µs
+            1_000_000,       // 1ms
+            10_000_000,      // 10ms
+            100_000_000,     // 100ms
+            1_000_000_000,   // 1s
+            10_000_000_000L, // 10s
+    };
+
+    private final DistributionMetric runConsistentlyDuration;
+    private final AtomicIntMetric runConsistentlyActiveCount;
+
+    /**
+     * Constructor.
+     *
+     * @param metricSource Metric source to register metrics with.
+     */
+    public RunConsistentlyMetrics(CollectionMetricSource metricSource) {
+        runConsistentlyDuration = metricSource.addMetric(new 
DistributionMetric(
+                "RunConsistentlyDuration",
+                "Time spent in runConsistently closures in nanoseconds.",
+                RUN_CONSISTENTLY_NANOS
+        ));
+
+        runConsistentlyActiveCount = metricSource.addMetric(new 
AtomicIntMetric(
+                "RunConsistentlyActiveCount",
+                "Current number of active runConsistently calls."
+        ));
+    }
+
+    /**
+     * Records the duration of a runConsistently closure execution in 
nanoseconds.
+     */
+    public void recordRunConsistentlyDuration(long durationNanos) {
+        runConsistentlyDuration.add(durationNanos);
+    }
+
+    /**
+     * Increments the active count of runConsistently calls.
+     */
+    public void incrementActiveCount() {
+        runConsistentlyActiveCount.increment();
+    }
+
+    /**
+     * Decrements the active count of runConsistently calls.
+     */
+    public void decrementActiveCount() {
+        runConsistentlyActiveCount.decrement();
+    }
+
+    /** Returns the runConsistently duration metric for testing. */
+    DistributionMetric runConsistentlyDuration() {
+        return runConsistentlyDuration;
+    }
+
+    /** Returns the runConsistently active count metric for testing. */
+    AtomicIntMetric runConsistentlyActiveCount() {

Review Comment:
   `@TestOnly`?



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java:
##########
@@ -130,6 +131,8 @@ public class PersistentPageMemoryStorageEngine extends 
AbstractPageMemoryStorage
     /** For unspecified tasks, i.e. throttling log. */
     private final ExecutorService commonExecutorService;
 
+    private RunConsistentlyMetrics consistencyMetrics;

Review Comment:
   Same thing about field name



##########
modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/RunConsistentlyMetrics.java:
##########
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.storage.pagememory.mv;
+
+import org.apache.ignite.internal.metrics.AtomicIntMetric;
+import org.apache.ignite.internal.metrics.DistributionMetric;
+import org.apache.ignite.internal.pagememory.metrics.CollectionMetricSource;
+
+/**
+ * Metrics for runConsistently operation.
+ *
+ * <p>Tracks runConsistently closure execution performance including duration
+ * and active call count.
+ */
+public class RunConsistentlyMetrics {
+    /**
+     * Histogram buckets for runConsistently duration in nanoseconds.
+     *
+     * <p>Covers operations from fast single-row writes to slow bulk 
operations with checkpoint contention:
+     * <ul>
+     *   <li>10µs: Fast single-row operations without lock contention</li>
+     *   <li>100µs: Multi-row operations, small index operations</li>
+     *   <li>1ms: Medium-sized operations</li>
+     *   <li>10ms: Larger operations, small vacuum operations</li>
+     *   <li>100ms: Large operations, significant vacuum work</li>
+     *   <li>1s: Very slow operations, likely checkpoint write lock 
contention</li>
+     *   <li>10s: Pathological cases requiring investigation</li>
+     * </ul>
+     */
+    private static final long[] RUN_CONSISTENTLY_NANOS = {
+            10_000,          // 10µs
+            100_000,         // 100µs
+            1_000_000,       // 1ms
+            10_000_000,      // 10ms
+            100_000_000,     // 100ms
+            1_000_000_000,   // 1s
+            10_000_000_000L, // 10s
+    };
+
+    private final DistributionMetric runConsistentlyDuration;
+    private final AtomicIntMetric runConsistentlyActiveCount;
+
+    /**
+     * Constructor.
+     *
+     * @param metricSource Metric source to register metrics with.
+     */
+    public RunConsistentlyMetrics(CollectionMetricSource metricSource) {
+        runConsistentlyDuration = metricSource.addMetric(new 
DistributionMetric(
+                "RunConsistentlyDuration",
+                "Time spent in runConsistently closures in nanoseconds.",

Review Comment:
   ```suggestion
                   "Accumulated time spent in runConsistently closures in 
nanoseconds.",
   ```
   If it never goes down



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to