From 992d82a2f8d6ad9d231295a912ff8a698f126c06 Mon Sep 17 00:00:00 2001 From: "Valuyskiy.O.Y" Date: Fri, 6 Mar 2026 10:06:59 +1000 Subject: [PATCH] IGNITE-28085 Add the EvictionsStarted metric to DataStorageMetricsImpl --- .../persistence/DataStorageMetricsImpl.java | 20 ++++++++++ .../IgniteCacheDatabaseSharedManager.java | 10 +++++ .../IgniteDataStorageMetricsSelfTest.java | 38 ++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStorageMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStorageMetricsImpl.java index 0ba6e04a99343..7eff728782f48 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStorageMetricsImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataStorageMetricsImpl.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.processors.cache.persistence; import java.util.Collection; +import java.util.function.BooleanSupplier; import org.apache.ignite.DataRegionMetrics; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord; @@ -173,6 +174,9 @@ public class DataStorageMetricsImpl { /** Total size of the compressed segments in bytes. */ private final LongAdderMetric walCompressedBytes; + /** Supplier for the eviction-started flag. */ + private volatile BooleanSupplier evictionsStartedSupplier = () -> false; + /** * @param mmgr Metrics manager. * @param metricsEnabled Metrics enabled flag. @@ -372,6 +376,12 @@ public DataStorageMetricsImpl( "Used checkpoint buffer size in bytes."); mreg.register("CheckpointBufferSize", this::checkpointBufferSize, "Checkpoint buffer size in bytes."); + + mreg.register( + "EvictionsStarted", + this::evictionsStarted, + "True if page eviction was triggered due to data region memory pressure." + ); } /** @return Current number of WAL segments in the WAL archive. */ @@ -810,4 +820,14 @@ public void onWalSegmentCompressed(long size) { walCompressedBytes.add(size); } + + /** @param supplier Supplier for the eviction-started flag. */ + public void setEvictionsStartedSupplier(BooleanSupplier supplier) { + evictionsStartedSupplier = (supplier == null) ? () -> false : supplier; + } + + /** @return {@code true} if page eviction was triggered due to data region memory pressure. */ + private boolean evictionsStarted() { + return evictionsStartedSupplier.getAsBoolean(); + } } 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 d8b14ce718a1f..2e6d0c065ceca 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 @@ -198,6 +198,8 @@ public IgniteCacheDatabaseSharedManager(GridKernalContext ctx) { DFLT_SUB_INTERVALS ); } + + dsMetrics.setEvictionsStartedSupplier(this::evictionsStarted); } /** {@inheritDoc} */ @@ -1660,4 +1662,12 @@ private void checkRegionWarmUpConfiguration( public void onWalTruncated(WALPointer highBound) throws IgniteCheckedException { // No-op. } + + /** + * @return Value of the {@link IgniteCacheDatabaseSharedManager#firstEvictWarn} flag, where {@code true} indicates + * that the eviction process has started. + */ + public boolean evictionsStarted() { + return firstEvictWarn; + } } 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 9cff28d988252..ffc0fa1755492 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 @@ -52,6 +52,7 @@ import org.apache.ignite.internal.processors.cache.persistence.wal.FileDescriptor; import org.apache.ignite.internal.processors.cache.persistence.wal.FileWriteAheadLogManager; import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric; +import org.apache.ignite.internal.processors.metric.impl.BooleanGauge; import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric; import org.apache.ignite.internal.processors.metric.impl.LongGauge; import org.apache.ignite.internal.util.tostring.GridToStringInclude; @@ -63,14 +64,17 @@ 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; @@ -137,7 +141,8 @@ public class IgniteDataStorageMetricsSelfTest extends GridCommonAbstractTest { .setMaxSize(maxRegionSize) .setPersistenceEnabled(false) .setMetricsEnabled(true) - .setName(NO_PERSISTENCE)) + .setName(NO_PERSISTENCE) + .setPageEvictionMode(RANDOM_LRU)) .setWalMode(WALMode.LOG_ONLY) .setMetricsEnabled(true); @@ -505,6 +510,37 @@ public void testWalTotalSizeWithArchiveTurnedOff() throws Exception { checkWalArchiveAndTotalSize(n, false); } + /** Verifies that the 'EvictionsStarted' metric becomes {@code true} after page eviction is triggered. */ + @Test + public void testEvicstionsStartedMetric() throws Exception { + IgniteEx ignite = startGrid(0); + + ignite.cluster().state(ClusterState.ACTIVE); + + String msg = "Page-based evictions started. Consider increasing 'maxSize' on Data Region configuration"; + + LogListener lsnr = LogListener.matches(msg).build(); + + listeningLog.registerListener(lsnr); + + IgniteCache cacheNp = ignite.cache("cache-np"); + + String big = repeat('X', 256 * 1024); + + for (int i = 0; i < 1_000_000 && !lsnr.check(); i++) + cacheNp.put(i, new Person("first-" + i + "-" + big, "last-" + i + "-" + big)); + + assertTrue(lsnr.check()); + + MetricRegistry metrics = ignite.context().metric().registry(DATASTORAGE_METRIC_PREFIX); + assertNotNull(metrics); + + BooleanGauge evictStarted = metrics.findMetric("EvictionsStarted"); + assertNotNull(evictStarted); + + assertTrue(evictStarted.value()); + } + /** * Populates a cache w/32 KB of data. *