This is an automated email from the ASF dual-hosted git repository.

tkalkirill pushed a commit to branch ignite-26594
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 6c5ea5ff124670be4c8a2d2722ab6817de5afdd3
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Fri Oct 3 13:03:32 2025 +0300

    IGNITE-26594 wip
---
 modules/page-memory/build.gradle                   |   1 +
 .../persistence/PersistentPageMemory.java          |  35 +++----
 .../PersistentPageMemoryMetricSource.java          |   4 +-
 .../persistence/PersistentPageMemoryMetrics.java   |  75 ++++++++++++++
 .../PersistentPageMemoryMetricsTest.java           | 114 +++++++++++++++++++++
 5 files changed, 206 insertions(+), 23 deletions(-)

diff --git a/modules/page-memory/build.gradle b/modules/page-memory/build.gradle
index a20830959e7..7189f055c56 100644
--- a/modules/page-memory/build.gradle
+++ b/modules/page-memory/build.gradle
@@ -41,6 +41,7 @@ dependencies {
     testImplementation project(':ignite-failure-handler')
     testImplementation testFixtures(project(':ignite-core'))
     testImplementation testFixtures(project(':ignite-configuration'))
+    testImplementation testFixtures(project(':ignite-metrics'))
     testImplementation libs.auto.service.annotations
 
     testFixturesAnnotationProcessor libs.auto.service
diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
index 80741dc7d0f..2c1d0e637a4 100644
--- 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java
@@ -82,8 +82,6 @@ import 
org.apache.ignite.internal.lang.IgniteInternalCheckedException;
 import org.apache.ignite.internal.lang.IgniteInternalException;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
-import org.apache.ignite.internal.metrics.IntGauge;
-import org.apache.ignite.internal.metrics.LongGauge;
 import org.apache.ignite.internal.pagememory.FullPageId;
 import org.apache.ignite.internal.pagememory.PageMemory;
 import 
org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration;
@@ -155,8 +153,6 @@ public class PersistentPageMemory implements PageMemory {
     /** Data region configuration. */
     private final PersistentDataRegionConfiguration dataRegionConfiguration;
 
-    private final PersistentPageMemoryMetricSource metricSource;
-
     /** Page IO registry. */
     private final PageIoRegistry ioRegistry;
 
@@ -213,6 +209,8 @@ public class PersistentPageMemory implements PageMemory {
     /** Checkpoint timeout lock. */
     private final CheckpointTimeoutLock checkpointTimeoutLock;
 
+    private final PersistentPageMemoryMetrics metrics;
+
     /**
      * Constructor.
      *
@@ -240,8 +238,6 @@ public class PersistentPageMemory implements PageMemory {
             PartitionDestructionLockManager partitionDestructionLockManager
     ) {
         this.dataRegionConfiguration = dataRegionConfiguration;
-        this.metricSource = metricSource;
-        initMetrics();
 
         this.ioRegistry = ioRegistry;
         this.sizes = concat(segmentSizes, checkpointBufferSize);
@@ -274,9 +270,15 @@ public class PersistentPageMemory implements PageMemory {
                 throw new IgniteInternalException("Unexpected page replacement 
mode: " + replacementMode);
         }
 
+        metrics = new PersistentPageMemoryMetrics(metricSource, this, 
dataRegionConfiguration);
+
         delayedPageReplacementTracker = new DelayedPageReplacementTracker(
                 pageSize,
-                flushDirtyPageForReplacement,
+                (pageMemory, fullPageId, buffer) -> {
+                    metrics.incrementWriteToDiskMetric();
+
+                    flushDirtyPageForReplacement.write(pageMemory, fullPageId, 
buffer);
+                },
                 LOG,
                 sizes.length - 1,
                 partitionDestructionLockManager
@@ -285,21 +287,6 @@ public class PersistentPageMemory implements PageMemory {
         this.writeThrottle = null;
     }
 
-    private void initMetrics() {
-        metricSource.addMetric(new IntGauge(
-                "UsedCheckpointBufferPages", "Number of currently used pages 
in checkpoint buffer.", this::usedCheckpointBufferPages
-        ));
-        metricSource.addMetric(new IntGauge(
-                "MaxCheckpointBufferPages", "The capacity of checkpoint buffer 
in pages.", this::maxCheckpointBufferPages
-        ));
-        // TODO: IGNITE-25702 Fix the concept of "region"
-        metricSource.addMetric(new LongGauge(
-                "MaxSize",
-                "Maximum in-memory region size in bytes.",
-                dataRegionConfiguration::sizeBytes
-        ));
-    }
-
     /**
      * Temporary method to enable throttling in tests.
      *
@@ -850,6 +837,8 @@ public class PersistentPageMemory implements PageMemory {
                     pageStoreManager.read(grpId, pageId, buf, false);
 
                     actualPageId = getPageId(buf);
+
+                    metrics.incrementReadFromDiskMetric();
                 } finally {
                     rwLock.writeUnlock(lockedPageAbsPtr + PAGE_LOCK_OFFSET, 
actualPageId == 0 ? TAG_LOCK_ALWAYS : tag(actualPageId));
                 }
@@ -2055,6 +2044,8 @@ public class PersistentPageMemory implements PageMemory {
                 pageStoreWriter.writePage(fullId, buf, partitionGeneration);
 
                 buf.rewind();
+
+                metrics.incrementWriteToDiskMetric();
             }
 
             // We pinned the page either when allocated the temp buffer, or 
when resolved abs pointer.
diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java
index 56bcf99c0ab..50f007bd8d6 100644
--- 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java
@@ -58,10 +58,12 @@ public class PersistentPageMemoryMetricSource implements 
MetricSource {
     /**
      * Adds metric to the source.
      */
-    public synchronized void addMetric(Metric metric) {
+    public synchronized <T extends Metric> T addMetric(T metric) {
         assert !enabled : "Cannot add metrics when source is enabled";
 
         metrics.put(metric.name(), metric);
+
+        return metric;
     }
 
     @Override
diff --git 
a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java
 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java
new file mode 100644
index 00000000000..c3594ee6cf8
--- /dev/null
+++ 
b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java
@@ -0,0 +1,75 @@
+/*
+ * 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.pagememory.persistence;
+
+import org.apache.ignite.internal.metrics.IntGauge;
+import org.apache.ignite.internal.metrics.LongAdderMetric;
+import org.apache.ignite.internal.metrics.LongGauge;
+import 
org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration;
+
+/** Persistent page memory metrics. */
+class PersistentPageMemoryMetrics {
+    private final LongAdderMetric readPagesFromDisk;
+
+    private final LongAdderMetric writePagesToDisk;
+
+    PersistentPageMemoryMetrics(
+            PersistentPageMemoryMetricSource source,
+            PersistentPageMemory pageMemory,
+            PersistentDataRegionConfiguration dataRegionConfiguration
+    ) {
+        source.addMetric(new IntGauge(
+                "UsedCheckpointBufferPages",
+                "Number of currently used pages in checkpoint buffer.",
+                pageMemory::usedCheckpointBufferPages
+        ));
+
+        source.addMetric(new IntGauge(
+                "MaxCheckpointBufferPages",
+                "The capacity of checkpoint buffer in pages.",
+                pageMemory::maxCheckpointBufferPages
+        ));
+
+        // TODO: IGNITE-25702 Fix the concept of "region"
+        source.addMetric(new LongGauge(
+                "MaxSize",
+                "Maximum in-memory region size in bytes.",
+                dataRegionConfiguration::sizeBytes
+        ));
+
+        readPagesFromDisk = source.addMetric(new LongAdderMetric(
+                "PagesRead",
+                "Number of pages read from disk since the last restart."
+        ));
+
+        writePagesToDisk = source.addMetric(new LongAdderMetric(
+                "PagesWritten",
+                "Number of pages written to disk since the last restart."
+        ));
+    }
+
+    /** Increases the disk page read metric by one. */
+    public void incrementReadFromDiskMetric() {
+        readPagesFromDisk.increment();
+    }
+
+    /** Increases the page writes to disk metric by one. */
+    public void incrementWriteToDiskMetric() {
+        writePagesToDisk.increment();
+    }
+}
diff --git 
a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java
 
b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java
new file mode 100644
index 00000000000..e0be64dbe76
--- /dev/null
+++ 
b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.pagememory.persistence;
+
+import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.ignite.internal.manager.ComponentContext;
+import org.apache.ignite.internal.metrics.Metric;
+import org.apache.ignite.internal.metrics.MetricManager;
+import org.apache.ignite.internal.metrics.MetricSet;
+import org.apache.ignite.internal.metrics.TestMetricManager;
+import 
org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/** For {@link PersistentPageMemoryMetrics} testing. */
+public class PersistentPageMemoryMetricsTest extends BaseIgniteAbstractTest {
+    private final PersistentPageMemoryMetricSource metricSource = new 
PersistentPageMemoryMetricSource("test");
+
+    private final PersistentPageMemory pageMemory = 
mock(PersistentPageMemory.class);
+
+    private final PersistentDataRegionConfiguration dataRegionConfig = 
PersistentDataRegionConfiguration.builder().size(100).build();
+
+    private final PersistentPageMemoryMetrics metrics = new 
PersistentPageMemoryMetrics(metricSource, pageMemory, dataRegionConfig);
+
+    private final MetricManager metricManager = new TestMetricManager();
+
+    @BeforeEach
+    void setUp() {
+        metricManager.registerSource(metricSource);
+        metricManager.enable(metricSource);
+
+        assertThat(metricManager.startAsync(new ComponentContext()), 
willCompleteSuccessfully());
+    }
+
+    @AfterEach
+    void tearDown() {
+        metricManager.beforeNodeStop();
+
+        assertThat(metricManager.stopAsync(new ComponentContext()), 
willCompleteSuccessfully());
+    }
+
+    @Test
+    void testMaxSize() {
+        checkMetricValue("MaxSize", 
Long.toString(dataRegionConfig.sizeBytes()));
+    }
+
+    @Test
+    void testUsedCheckpointBufferPages() {
+        when(pageMemory.usedCheckpointBufferPages()).thenReturn(42);
+
+        checkMetricValue("UsedCheckpointBufferPages", "42");
+    }
+
+    @Test
+    void testMaxCheckpointBufferPages() {
+        when(pageMemory.maxCheckpointBufferPages()).thenReturn(84);
+
+        checkMetricValue("MaxCheckpointBufferPages", "84");
+    }
+
+    @Test
+    void testPagesRead() {
+        checkMetricValue("PagesRead", "0");
+
+        metrics.incrementReadFromDiskMetric();
+        metrics.incrementReadFromDiskMetric();
+
+        checkMetricValue("PagesRead", "2");
+    }
+
+    @Test
+    void testPagesWritten() {
+        checkMetricValue("PagesWritten", "0");
+
+        metrics.incrementWriteToDiskMetric();
+        metrics.incrementWriteToDiskMetric();
+        metrics.incrementWriteToDiskMetric();
+
+        checkMetricValue("PagesWritten", "3");
+    }
+
+    private void checkMetricValue(String metricName, String exp) {
+        MetricSet metricsSet = 
metricManager.metricSnapshot().metrics().get(metricSource.name());
+
+        Metric metric = metricsSet.get(metricName);
+
+        assertNotNull(metric, metricName);
+
+        assertEquals(exp, metric.getValueAsString(), metricName);
+    }
+}

Reply via email to