Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/_docs/monitoring-metrics/new-metrics.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -178,6 +179,9 @@ private static LongAdderMetricDelegate delegate(LongAdderMetric delegate) {
@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}.
Expand Down Expand Up @@ -281,6 +285,9 @@ public DataRegionMetricsImpl(
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).
Expand Down Expand Up @@ -875,4 +882,15 @@ public Collection<PagesTimestampHistogramView> pagesTimestampHistogramView() {

return list;
}

/** {@inheritDoc} */
@Override public boolean isEvictionsStarted() {
return evictionsStarted.value();
}

/** */
public void onPageEvictionsStarted() {
if (!evictionsStarted.value())
evictionsStarted.value(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -119,6 +122,7 @@ public DataRegionMetricsSnapshot(DataRegionMetrics metrics) {
replacedPage = metrics.getPagesReplaced();
offHeapSize = metrics.getOffHeapSize();
offHeapUsedSize = metrics.getOffheapUsedSize();
evictionsStarted = metrics.isEvictionsStarted();
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -235,4 +239,9 @@ public DataRegionMetricsSnapshot(DataRegionMetrics metrics) {
@Override public long getOffheapUsedSize() {
return offHeapUsedSize;
}

/** {@inheritDoc} */
@Override public boolean isEvictionsStarted() {
return evictionsStarted;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,8 @@ public void ensureFreeSpace(DataRegion memPlc) throws IgniteCheckedException {
return;

while (memPlc.evictionTracker().evictionRequired()) {
memPlc.metrics().onPageEvictionsStarted();

warnFirstEvict(memPlc.config());

memPlc.evictionTracker().evictDataPage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,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;
Expand All @@ -89,7 +92,10 @@
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";
Expand Down Expand Up @@ -137,7 +143,14 @@
.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);

Expand All @@ -148,7 +161,8 @@
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);

Expand Down Expand Up @@ -191,7 +205,7 @@
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;
Expand Down Expand Up @@ -226,7 +240,7 @@
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);
Expand Down Expand Up @@ -505,6 +519,63 @@
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);

Check warning on line 539 in modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "DataRegionMetrics"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=apache_ignite&issues=AZzWrSwPqn45uAgxdPW2&open=AZzWrSwPqn45uAgxdPW2&pullRequest=12866
DataRegionMetrics memMetrics2 = ignite.dataRegionMetrics(NO_PERSISTENCE_2);

Check warning on line 540 in modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/IgniteDataStorageMetricsSelfTest.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this use of "DataRegionMetrics"; it is deprecated.

See more on https://sonarcloud.io/project/issues?id=apache_ignite&issues=AZzWrSwPqn45uAgxdPW3&open=AZzWrSwPqn45uAgxdPW3&pullRequest=12866

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.
*
Expand Down
Loading