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

sergeychugunov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 3df1cab8922 IGNITE-28085 Add the EvictionsStarted metric to 
DataRegionMetrics (#12866)
3df1cab8922 is described below

commit 3df1cab8922b921af977577e7e63febf92a2b0b6
Author: oleg-vlsk <[email protected]>
AuthorDate: Fri Mar 13 17:32:48 2026 +1000

    IGNITE-28085 Add the EvictionsStarted metric to DataRegionMetrics (#12866)
---
 docs/_docs/monitoring-metrics/new-metrics.adoc     |  1 +
 .../java/org/apache/ignite/DataRegionMetrics.java  |  7 ++
 .../cache/persistence/DataRegionMetricsImpl.java   | 18 +++++
 .../persistence/DataRegionMetricsSnapshot.java     |  9 +++
 .../IgniteCacheDatabaseSharedManager.java          |  2 +
 .../IgniteDataStorageMetricsSelfTest.java          | 81 ++++++++++++++++++++--
 6 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/docs/_docs/monitoring-metrics/new-metrics.adoc 
b/docs/_docs/monitoring-metrics/new-metrics.adoc
index 19a2ca3121e..0850d9ae331 100644
--- a/docs/_docs/monitoring-metrics/new-metrics.adoc
+++ b/docs/_docs/monitoring-metrics/new-metrics.adoc
@@ -394,6 +394,7 @@ Register name: `io.dataregion.{data_region_name}`
 |DirtyPages |  long|    Number of pages in memory not yet synchronized with 
persistent storage.
 |EmptyDataPages|  long|    Calculates empty data pages count for region. It 
counts only totally free pages that can be reused (e. g. pages that are 
contained in reuse bucket of free list).
 |EvictionRate|    hitrate|    Eviction rate (pages per second).
+|EvictionsStarted | boolean |   True if page eviction was triggered due to 
data region memory pressure.
 |LargeEntriesPagesCount|  long|    Count of pages that fully ocupied by large 
entries that go beyond page size
 |OffHeapSize| long|    Offheap size in bytes.
 |OffheapUsedSize| long|    Offheap used size in bytes.
diff --git 
a/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java 
b/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
index a1539e1e8b7..28d7c4004bf 100644
--- a/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
+++ b/modules/core/src/main/java/org/apache/ignite/DataRegionMetrics.java
@@ -241,4 +241,11 @@ public interface DataRegionMetrics {
      * @return Total used offheap size in bytes.
      */
     public long getOffheapUsedSize();
+
+    /**
+     * Data region eviction-started flag.
+     *
+     * @return {@code true} if page eviction was triggered due to data region 
memory pressure.
+     */
+    public boolean isEvictionsStarted();
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
index 549ffc399f7..1e962331f11 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
@@ -30,6 +30,7 @@ import 
org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMetri
 import 
org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMetricsImpl;
 import org.apache.ignite.internal.processors.metric.MetricRegistryImpl;
 import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric;
+import org.apache.ignite.internal.processors.metric.impl.BooleanMetricImpl;
 import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
 import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
 import 
org.apache.ignite.internal.processors.metric.impl.LongAdderWithDelegateMetric;
@@ -178,6 +179,9 @@ public class DataRegionMetricsImpl implements 
DataRegionMetrics {
     @Nullable
     private final PeriodicHistogramMetricImpl pageTsHistogram;
 
+    /** Metric indicating whether page eviction has started. */
+    private final BooleanMetricImpl evictionsStarted;
+
     /**
      * Same as {@link #DataRegionMetricsImpl(DataRegionConfiguration, 
GridKernalContext, DataRegionMetricsProvider)}
      * but uses a no-op implementation for the {@link 
DataRegionMetricsProvider}.
@@ -281,6 +285,9 @@ public class DataRegionMetricsImpl implements 
DataRegionMetrics {
         mreg.longMetric("MaxSize", "Maximum memory region size in bytes 
defined by its data region.")
             .value(dataRegionCfg.getMaxSize());
 
+        evictionsStarted = mreg.booleanMetric("EvictionsStarted",
+            "True if page eviction was triggered due to data region memory 
pressure.");
+
         if (persistenceEnabled) {
             // Reserve 1 sec, page ts can be slightly lower than 
currentTimeMillis, due to applied to ts mask. This
             // reservation mainly affects only tests (we can check buckets 
more predictevely).
@@ -875,4 +882,15 @@ public class DataRegionMetricsImpl implements 
DataRegionMetrics {
 
         return list;
     }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEvictionsStarted() {
+        return evictionsStarted.value();
+    }
+
+    /** */
+    public void onPageEvictionsStarted() {
+        if (!evictionsStarted.value())
+            evictionsStarted.value(true);
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
index 316f98fe875..b56b9a9baf8 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsSnapshot.java
@@ -92,6 +92,9 @@ public class DataRegionMetricsSnapshot implements 
DataRegionMetrics {
     /** */
     private final long offHeapUsedSize;
 
+    /** */
+    private final boolean evictionsStarted;
+
     /**
      * @param metrics Metrics instance to take a copy.
      */
@@ -119,6 +122,7 @@ public class DataRegionMetricsSnapshot implements 
DataRegionMetrics {
         replacedPage = metrics.getPagesReplaced();
         offHeapSize = metrics.getOffHeapSize();
         offHeapUsedSize = metrics.getOffheapUsedSize();
+        evictionsStarted = metrics.isEvictionsStarted();
     }
 
     /** {@inheritDoc} */
@@ -235,4 +239,9 @@ public class DataRegionMetricsSnapshot implements 
DataRegionMetrics {
     @Override public long getOffheapUsedSize() {
         return offHeapUsedSize;
     }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEvictionsStarted() {
+        return evictionsStarted;
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index d8b14ce718a..a20a38e7093 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -1246,6 +1246,8 @@ public class IgniteCacheDatabaseSharedManager extends 
GridCacheSharedManagerAdap
             return;
 
         while (memPlc.evictionTracker().evictionRequired()) {
+            memPlc.metrics().onPageEvictionsStarted();
+
             warnFirstEvict(memPlc.config());
 
             memPlc.evictionTracker().evictDataPage();
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java
index 9cff28d9882..dffaf8a29a9 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java
@@ -63,14 +63,17 @@ import org.apache.ignite.metric.MetricRegistry;
 import org.apache.ignite.spi.metric.HistogramMetric;
 import org.apache.ignite.spi.metric.LongMetric;
 import org.apache.ignite.testframework.ListeningTestLogger;
+import org.apache.ignite.testframework.LogListener;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
 
 import static java.util.Collections.emptyList;
+import static org.apache.commons.lang3.StringUtils.repeat;
 import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static org.apache.ignite.cluster.ClusterState.ACTIVE;
+import static org.apache.ignite.configuration.DataPageEvictionMode.RANDOM_LRU;
 import static 
org.apache.ignite.internal.processors.cache.CacheGroupMetricsImpl.CACHE_GROUP_METRICS_PREFIX;
 import static 
org.apache.ignite.internal.processors.cache.persistence.DataStorageMetricsImpl.DATASTORAGE_METRIC_PREFIX;
 import static 
org.apache.ignite.internal.processors.cache.persistence.wal.serializer.RecordV1Serializer.HEADER_RECORD_SIZE;
@@ -89,7 +92,10 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
     private static final String GROUP2 = "grp2";
 
     /** */
-    private static final String NO_PERSISTENCE = "no-persistence";
+    private static final String NO_PERSISTENCE_1 = "no-persistence-1";
+
+    /** */
+    private static final String NO_PERSISTENCE_2 = "no-persistence-2";
 
     /** */
     private static final String PERSISTENCE_REGION_1 = "persistence-1";
@@ -137,7 +143,14 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
                     .setMaxSize(maxRegionSize)
                     .setPersistenceEnabled(false)
                     .setMetricsEnabled(true)
-                    .setName(NO_PERSISTENCE))
+                    .setName(NO_PERSISTENCE_1)
+                    .setPageEvictionMode(RANDOM_LRU),
+                new DataRegionConfiguration()
+                    .setMaxSize(maxRegionSize)
+                    .setPersistenceEnabled(false)
+                    .setMetricsEnabled(true)
+                    .setName(NO_PERSISTENCE_2)
+                    .setPageEvictionMode(RANDOM_LRU))
             .setWalMode(WALMode.LOG_ONLY)
             .setMetricsEnabled(true);
 
@@ -148,7 +161,8 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
         cfg.setCacheConfiguration(
             cacheConfiguration(GROUP1, "cache", PARTITIONED, ATOMIC, 1, null),
             cacheConfiguration(GROUP2, "cache2", PARTITIONED, ATOMIC, 1, 
PERSISTENCE_REGION_2),
-            cacheConfiguration(null, "cache-np", PARTITIONED, ATOMIC, 1, 
NO_PERSISTENCE));
+            cacheConfiguration(null, "cache-np", PARTITIONED, ATOMIC, 1, 
NO_PERSISTENCE_1),
+            cacheConfiguration(null, "cache-np2", PARTITIONED, ATOMIC, 1, 
NO_PERSISTENCE_2));
 
         cfg.setGridLogger(listeningLog);
 
@@ -191,7 +205,7 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
         ccfg.setDataRegionName(dataRegName);
         ccfg.setAffinity(new RendezvousAffinityFunction(false, 32));
 
-        if (NO_PERSISTENCE.equals(dataRegName))
+        if (NO_PERSISTENCE_1.equals(dataRegName))
             ccfg.setDiskPageCompression(null);
 
         return ccfg;
@@ -226,7 +240,7 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
             assertTrue(memMetrics.getDirtyPages() > 0);
             assertTrue(memMetrics.getPagesFillFactor() > 0);
 
-            memMetrics = ig.dataRegionMetrics("no-persistence");
+            memMetrics = ig.dataRegionMetrics(NO_PERSISTENCE_1);
 
             assertNotNull(memMetrics);
             assertTrue(memMetrics.getTotalAllocatedPages() > 0);
@@ -505,6 +519,63 @@ public class IgniteDataStorageMetricsSelfTest extends 
GridCommonAbstractTest {
         checkWalArchiveAndTotalSize(n, false);
     }
 
+    /**
+     * Verifies that the 'EvictionsStarted' metric is tracked per data region 
and becomes {@code true} only for the
+     * region where page eviction is triggered, remaining unaffected by 
evictions in other regions. If eviction starts
+     * in multiple regions, the metric becomes {@code true} independently for 
each of them.
+     */
+    @Test
+    public void testEvictionsStartedMetric() throws Exception {
+        IgniteEx ignite = startGrid(0);
+
+        ignite.cluster().state(ClusterState.ACTIVE);
+
+        String template = "Page-based evictions started. Consider increasing 
'maxSize' on Data Region configuration: ";
+
+        LogListener lsnr = LogListener.matches(template + 
NO_PERSISTENCE_1).build();
+
+        listeningLog.registerListener(lsnr);
+
+        DataRegionMetrics memMetrics1 = 
ignite.dataRegionMetrics(NO_PERSISTENCE_1);
+        DataRegionMetrics memMetrics2 = 
ignite.dataRegionMetrics(NO_PERSISTENCE_2);
+
+        assertNotNull(memMetrics1);
+        assertNotNull(memMetrics2);
+
+        assertFalse(memMetrics1.isEvictionsStarted());
+        assertFalse(memMetrics2.isEvictionsStarted());
+
+        IgniteCache<Object, Object> cacheNp1 = ignite.cache("cache-np");
+        IgniteCache<Object, Object> cacheNp2 = ignite.cache("cache-np2");
+
+        String big = repeat('X', 256 * 1024);
+
+        int entryCnt = 0;
+
+        for (int i = 0; i < 1_000_000 && !lsnr.check(); i++) {
+            cacheNp1.put(i, new Person("first-" + i + "-" + big, "last-" + i + 
"-" + big));
+
+            entryCnt++;
+        }
+
+        assertTrue(lsnr.check());
+
+        memMetrics1 = ignite.dataRegionMetrics(NO_PERSISTENCE_1);
+        memMetrics2 = ignite.dataRegionMetrics(NO_PERSISTENCE_2);
+
+        assertTrue(memMetrics1.isEvictionsStarted());
+        assertFalse(memMetrics2.isEvictionsStarted());
+
+        for (int i = 0; i < entryCnt + 10; i++)
+            cacheNp2.put(i, new Person("first-" + i + "-" + big, "last-" + i + 
"-" + big));
+
+        memMetrics1 = ignite.dataRegionMetrics(NO_PERSISTENCE_1);
+        memMetrics2 = ignite.dataRegionMetrics(NO_PERSISTENCE_2);
+
+        assertTrue(memMetrics1.isEvictionsStarted());
+        assertTrue(memMetrics2.isEvictionsStarted());
+    }
+
     /**
      * Populates a cache w/32 KB of data.
      *

Reply via email to