From 0f3b8705a982ac8cce43d57e235cc4e13fb3ae6f Mon Sep 17 00:00:00 2001 From: Rabi Panda Date: Thu, 23 Feb 2023 15:01:03 -0800 Subject: [PATCH] Include file cache stats in node stats response (#6333) This change exposes the file cache stats as part the node stats API response. Signed-off-by: Rabi Panda --- .../snapshots/SearchableSnapshotIT.java | 48 +++++ .../admin/cluster/node/stats/NodeStats.java | 24 ++- .../cluster/node/stats/NodesStatsRequest.java | 3 +- .../node/stats/TransportNodesStatsAction.java | 3 +- .../stats/TransportClusterStatsAction.java | 1 + .../remote/filecache/FileCacheStats.java | 171 ++++++++++++++++++ .../opensearch/indices/IndicesService.java | 30 ++- .../main/java/org/opensearch/node/Node.java | 7 +- .../java/org/opensearch/node/NodeService.java | 6 +- .../cluster/node/stats/NodeStatsTests.java | 3 +- .../opensearch/cluster/DiskUsageTests.java | 6 + .../remote/filecache/FileCacheStatsTests.java | 83 +++++++++ .../snapshots/SnapshotResiliencyTests.java | 6 +- .../MockInternalClusterInfoService.java | 3 +- .../opensearch/test/InternalTestCluster.java | 1 + 15 files changed, 382 insertions(+), 13 deletions(-) create mode 100644 server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java create mode 100644 server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java diff --git a/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java b/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java index 823609e57fca0..4eb9d8f4dc66e 100644 --- a/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/snapshots/SearchableSnapshotIT.java @@ -7,6 +7,8 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; import com.carrotsearch.randomizedtesting.generators.RandomPicks; import org.hamcrest.MatcherAssert; +import org.opensearch.action.admin.cluster.node.stats.NodeStats; +import org.opensearch.action.admin.cluster.node.stats.NodesStatsRequest; import org.opensearch.action.admin.cluster.node.stats.NodesStatsResponse; import org.opensearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse; import org.opensearch.action.admin.cluster.snapshots.delete.DeleteSnapshotRequest; @@ -29,6 +31,7 @@ import org.opensearch.index.Index; import org.opensearch.index.IndexNotFoundException; import org.opensearch.index.store.remote.file.CleanerDaemonThreadLeakFilter; +import org.opensearch.index.store.remote.filecache.FileCacheStats; import org.opensearch.monitor.fs.FsInfo; import org.opensearch.repositories.fs.FsRepository; @@ -413,4 +416,49 @@ private void assertIndexDirectoryDoesNotExist(String... indexNames) { } } } + + public void testFileCacheStats() throws Exception { + final String snapshotName = "test-snap"; + final String repoName = "test-repo"; + final String indexName1 = "test-idx-1"; + final Client client = client(); + final int numNodes = 2; + + internalCluster().ensureAtLeastNumSearchNodes(numNodes); + createIndexWithDocsAndEnsureGreen(1, 100, indexName1); + + createRepositoryWithSettings(null, repoName); + takeSnapshot(client, snapshotName, repoName, indexName1); + deleteIndicesAndEnsureGreen(client, indexName1); + assertAllNodesFileCacheEmpty(); + + restoreSnapshotAndEnsureGreen(client, snapshotName, repoName); + assertNodesFileCacheNonEmpty(numNodes); + } + + private void assertAllNodesFileCacheEmpty() { + NodesStatsResponse response = client().admin().cluster().nodesStats(new NodesStatsRequest().all()).actionGet(); + for (NodeStats stats : response.getNodes()) { + FileCacheStats fcstats = stats.getFileCacheStats(); + assertNotNull(fcstats); + assertTrue(isFileCacheEmpty(fcstats)); + } + } + + private void assertNodesFileCacheNonEmpty(int numNodes) { + NodesStatsResponse response = client().admin().cluster().nodesStats(new NodesStatsRequest().all()).actionGet(); + int nonEmptyFileCacheNodes = 0; + for (NodeStats stats : response.getNodes()) { + FileCacheStats fcstats = stats.getFileCacheStats(); + assertNotNull(fcstats); + if (!isFileCacheEmpty(fcstats)) { + nonEmptyFileCacheNodes++; + } + } + assertEquals(numNodes, nonEmptyFileCacheNodes); + } + + private boolean isFileCacheEmpty(FileCacheStats stats) { + return stats.getUsed().getBytes() == 0L && stats.getActive().getBytes() == 0L; + } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodeStats.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodeStats.java index 75e3afed6dc31..6d151843219bd 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodeStats.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodeStats.java @@ -41,12 +41,14 @@ import org.opensearch.common.Nullable; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.util.FeatureFlags; import org.opensearch.core.xcontent.ToXContentFragment; import org.opensearch.core.xcontent.XContentBuilder; import org.opensearch.discovery.DiscoveryStats; import org.opensearch.http.HttpStats; import org.opensearch.index.stats.IndexingPressureStats; import org.opensearch.index.stats.ShardIndexingPressureStats; +import org.opensearch.index.store.remote.filecache.FileCacheStats; import org.opensearch.indices.NodeIndicesStats; import org.opensearch.indices.breaker.AllCircuitBreakerStats; import org.opensearch.ingest.IngestStats; @@ -130,6 +132,9 @@ public class NodeStats extends BaseNodeResponse implements ToXContentFragment { @Nullable private WeightedRoutingStats weightedRoutingStats; + @Nullable + private FileCacheStats fileCacheStats; + public NodeStats(StreamInput in) throws IOException { super(in); timestamp = in.readVLong(); @@ -171,6 +176,11 @@ public NodeStats(StreamInput in) throws IOException { } else { weightedRoutingStats = null; } + if (in.getVersion().onOrAfter(Version.V_3_0_0) && FeatureFlags.isEnabled(FeatureFlags.SEARCHABLE_SNAPSHOT)) { + fileCacheStats = in.readOptionalWriteable(FileCacheStats::new); + } else { + fileCacheStats = null; + } } public NodeStats( @@ -194,7 +204,8 @@ public NodeStats( @Nullable ShardIndexingPressureStats shardIndexingPressureStats, @Nullable SearchBackpressureStats searchBackpressureStats, @Nullable ClusterManagerThrottlingStats clusterManagerThrottlingStats, - @Nullable WeightedRoutingStats weightedRoutingStats + @Nullable WeightedRoutingStats weightedRoutingStats, + @Nullable FileCacheStats fileCacheStats ) { super(node); this.timestamp = timestamp; @@ -217,6 +228,7 @@ public NodeStats( this.searchBackpressureStats = searchBackpressureStats; this.clusterManagerThrottlingStats = clusterManagerThrottlingStats; this.weightedRoutingStats = weightedRoutingStats; + this.fileCacheStats = fileCacheStats; } public long getTimestamp() { @@ -340,6 +352,10 @@ public WeightedRoutingStats getWeightedRoutingStats() { return weightedRoutingStats; } + public FileCacheStats getFileCacheStats() { + return fileCacheStats; + } + @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); @@ -374,6 +390,9 @@ public void writeTo(StreamOutput out) throws IOException { if (out.getVersion().onOrAfter(Version.V_2_6_0)) { out.writeOptionalWriteable(weightedRoutingStats); } + if (out.getVersion().onOrAfter(Version.V_3_0_0) && FeatureFlags.isEnabled(FeatureFlags.SEARCHABLE_SNAPSHOT)) { + out.writeOptionalWriteable(fileCacheStats); + } } @Override @@ -455,6 +474,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (getWeightedRoutingStats() != null) { getWeightedRoutingStats().toXContent(builder, params); } + if (getFileCacheStats() != null && FeatureFlags.isEnabled(FeatureFlags.SEARCHABLE_SNAPSHOT)) { + getFileCacheStats().toXContent(builder, params); + } return builder; } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodesStatsRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodesStatsRequest.java index be9a416c979c6..a9c58ac803590 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodesStatsRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/NodesStatsRequest.java @@ -209,7 +209,8 @@ public enum Metric { SHARD_INDEXING_PRESSURE("shard_indexing_pressure"), SEARCH_BACKPRESSURE("search_backpressure"), CLUSTER_MANAGER_THROTTLING("cluster_manager_throttling"), - WEIGHTED_ROUTING_STATS("weighted_routing"); + WEIGHTED_ROUTING_STATS("weighted_routing"), + FILE_CACHE_STATS("file_cache"); private String metricName; diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java index 08d46df723e2e..02b5ceef2c7e4 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java @@ -121,7 +121,8 @@ protected NodeStats nodeOperation(NodeStatsRequest nodeStatsRequest) { NodesStatsRequest.Metric.SHARD_INDEXING_PRESSURE.containedIn(metrics), NodesStatsRequest.Metric.SEARCH_BACKPRESSURE.containedIn(metrics), NodesStatsRequest.Metric.CLUSTER_MANAGER_THROTTLING.containedIn(metrics), - NodesStatsRequest.Metric.WEIGHTED_ROUTING_STATS.containedIn(metrics) + NodesStatsRequest.Metric.WEIGHTED_ROUTING_STATS.containedIn(metrics), + NodesStatsRequest.Metric.FILE_CACHE_STATS.containedIn(metrics) ); } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/stats/TransportClusterStatsAction.java b/server/src/main/java/org/opensearch/action/admin/cluster/stats/TransportClusterStatsAction.java index fc599efa13e68..2fdaa46de01bc 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/stats/TransportClusterStatsAction.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/stats/TransportClusterStatsAction.java @@ -165,6 +165,7 @@ protected ClusterStatsNodeResponse nodeOperation(ClusterStatsNodeRequest nodeReq false, false, false, + false, false ); List shardsStats = new ArrayList<>(); diff --git a/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java new file mode 100644 index 0000000000000..50c0411d00106 --- /dev/null +++ b/server/src/main/java/org/opensearch/index/store/remote/filecache/FileCacheStats.java @@ -0,0 +1,171 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.index.store.remote.filecache; + +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.io.stream.Writeable; +import org.opensearch.common.unit.ByteSizeValue; +import org.opensearch.core.xcontent.ToXContentFragment; +import org.opensearch.core.xcontent.XContentBuilder; + +import java.io.IOException; + +/** + * Statistics on file cache + * + * @opensearch.internal + */ +public class FileCacheStats implements Writeable, ToXContentFragment { + + private final long timestamp; + private final long active; + private final long total; + private final long used; + private final long evicted; + private final long removed; + private final long replaced; + private final long hits; + private final long miss; + + public FileCacheStats( + final long timestamp, + final long active, + final long total, + final long used, + final long evicted, + final long removed, + final long replaced, + final long hits, + final long miss + ) { + this.timestamp = timestamp; + this.active = active; + this.total = total; + this.used = used; + this.evicted = evicted; + this.removed = removed; + this.replaced = replaced; + this.hits = hits; + this.miss = miss; + } + + public FileCacheStats(final StreamInput in) throws IOException { + this.timestamp = in.readLong(); + this.active = in.readLong(); + this.total = in.readLong(); + this.used = in.readLong(); + this.evicted = in.readLong(); + this.removed = in.readLong(); + this.replaced = in.readLong(); + this.hits = in.readLong(); + this.miss = in.readLong(); + } + + public static short calculatePercentage(long used, long max) { + return max <= 0 ? 0 : (short) (Math.round((100d * used) / max)); + } + + @Override + public void writeTo(final StreamOutput out) throws IOException { + out.writeLong(timestamp); + out.writeLong(active); + out.writeLong(total); + out.writeLong(used); + out.writeLong(evicted); + out.writeLong(removed); + out.writeLong(replaced); + out.writeLong(hits); + out.writeLong(miss); + } + + public long getTimestamp() { + return timestamp; + } + + public ByteSizeValue getTotal() { + return new ByteSizeValue(total); + } + + public ByteSizeValue getActive() { + return new ByteSizeValue(active); + } + + public short getActivePercent() { + return calculatePercentage(active, used); + } + + public ByteSizeValue getUsed() { + return new ByteSizeValue(used); + } + + public short getUsedPercent() { + return calculatePercentage(getUsed().getBytes(), total); + } + + public ByteSizeValue getEvicted() { + return new ByteSizeValue(evicted); + } + + public ByteSizeValue getRemoved() { + return new ByteSizeValue(removed); + } + + public long getReplacedCount() { + return replaced; + } + + public long getCacheHits() { + return hits; + } + + public long getCacheMiss() { + return miss; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(Fields.FILE_CACHE); + builder.field(Fields.TIMESTAMP, getTimestamp()); + builder.humanReadableField(Fields.ACTIVE_IN_BYTES, Fields.ACTIVE, getActive()); + builder.humanReadableField(Fields.TOTAL_IN_BYTES, Fields.TOTAL, getTotal()); + builder.humanReadableField(Fields.USED_IN_BYTES, Fields.USED, getUsed()); + builder.humanReadableField(Fields.EVICTED_IN_BYTES, Fields.EVICTED, getEvicted()); + builder.humanReadableField(Fields.REMOVED_IN_BYTES, Fields.REMOVED, getRemoved()); + builder.field(Fields.REPLACED_COUNT, getReplacedCount()); + builder.field(Fields.ACTIVE_PERCENT, getActivePercent()); + builder.field(Fields.USED_PERCENT, getUsedPercent()); + builder.field(Fields.CACHE_HITS, getCacheHits()); + builder.field(Fields.CACHE_MISS, getCacheMiss()); + builder.endObject(); + return builder; + } + + static final class Fields { + static final String FILE_CACHE = "file_cache"; + static final String TIMESTAMP = "timestamp"; + static final String ACTIVE = "active"; + static final String ACTIVE_IN_BYTES = "active_in_bytes"; + static final String USED = "used"; + static final String USED_IN_BYTES = "used_in_bytes"; + static final String EVICTED = "evicted"; + static final String EVICTED_IN_BYTES = "evicted_in_bytes"; + static final String REMOVED = "removed"; + static final String REMOVED_IN_BYTES = "removed_in_bytes"; + static final String REPLACED_COUNT = "replaced_count"; + static final String TOTAL = "total"; + static final String TOTAL_IN_BYTES = "total_in_bytes"; + + static final String ACTIVE_PERCENT = "active_percent"; + static final String USED_PERCENT = "used_percent"; + + static final String CACHE_HITS = "cache_hits"; + static final String CACHE_MISS = "cache_miss"; + } +} diff --git a/server/src/main/java/org/opensearch/indices/IndicesService.java b/server/src/main/java/org/opensearch/indices/IndicesService.java index 0c6007db2f74e..bedd81b609751 100644 --- a/server/src/main/java/org/opensearch/indices/IndicesService.java +++ b/server/src/main/java/org/opensearch/indices/IndicesService.java @@ -132,6 +132,10 @@ import org.opensearch.index.shard.IndexingOperationListener; import org.opensearch.index.shard.IndexingStats; import org.opensearch.index.shard.ShardId; +import org.opensearch.index.store.remote.filecache.FileCache; +import org.opensearch.index.store.remote.filecache.FileCacheStats; +import org.opensearch.index.store.remote.utils.cache.CacheUsage; +import org.opensearch.index.store.remote.utils.cache.stats.CacheStats; import org.opensearch.index.translog.InternalTranslogFactory; import org.opensearch.index.translog.RemoteBlobStoreInternalTranslogFactory; import org.opensearch.index.translog.TranslogFactory; @@ -259,6 +263,8 @@ public class IndicesService extends AbstractLifecycleComponent private final TimeValue cleanInterval; final IndicesRequestCache indicesRequestCache; // pkg-private for testing private final IndicesQueryCache indicesQueryCache; + + private final FileCache remoteStoreFileCache; private final MetaStateService metaStateService; private final Collection>> engineFactoryProviders; private final Map directoryFactories; @@ -304,7 +310,8 @@ public IndicesService( ValuesSourceRegistry valuesSourceRegistry, Map recoveryStateFactories, IndexStorePlugin.RemoteDirectoryFactory remoteDirectoryFactory, - Supplier repositoriesServiceSupplier + Supplier repositoriesServiceSupplier, + FileCache remoteStoreFileCache ) { this.settings = settings; this.threadPool = threadPool; @@ -318,6 +325,7 @@ public IndicesService( this.indexNameExpressionResolver = indexNameExpressionResolver; this.indicesRequestCache = new IndicesRequestCache(settings); this.indicesQueryCache = new IndicesQueryCache(settings); + this.remoteStoreFileCache = remoteStoreFileCache; this.mapperRegistry = mapperRegistry; this.namedWriteableRegistry = namedWriteableRegistry; indexingMemoryController = new IndexingMemoryController( @@ -419,7 +427,8 @@ public IndicesService( ValuesSourceRegistry valuesSourceRegistry, Map recoveryStateFactories, IndexStorePlugin.RemoteDirectoryFactory remoteDirectoryFactory, - Supplier repositoriesServiceSupplier + Supplier repositoriesServiceSupplier, + FileCache remoteStoreFileCache ) { this.settings = settings; this.threadPool = threadPool; @@ -427,6 +436,7 @@ public IndicesService( this.extensionsManager = extensionsManager; this.nodeEnv = nodeEnv; this.xContentRegistry = xContentRegistry; + this.remoteStoreFileCache = remoteStoreFileCache; this.valuesSourceRegistry = valuesSourceRegistry; this.shardsClosedTimeout = settings.getAsTime(INDICES_SHARDS_CLOSED_TIMEOUT, new TimeValue(1, TimeUnit.DAYS)); this.analysisRegistry = analysisRegistry; @@ -1923,4 +1933,20 @@ public boolean allPendingDanglingIndicesWritten() { return nodeWriteDanglingIndicesInfo == false || (danglingIndicesToWrite.isEmpty() && danglingIndicesThreadPoolExecutor.getActiveCount() == 0); } + + public FileCacheStats getFileCacheStats() { + CacheStats stats = remoteStoreFileCache.stats(); + CacheUsage usage = remoteStoreFileCache.usage(); + return new FileCacheStats( + System.currentTimeMillis(), + usage.activeUsage(), + remoteStoreFileCache.capacity(), + usage.usage(), + stats.evictionWeight(), + stats.removeWeight(), + stats.replaceCount(), + stats.hitCount(), + stats.missCount() + ); + } } diff --git a/server/src/main/java/org/opensearch/node/Node.java b/server/src/main/java/org/opensearch/node/Node.java index cdc31d8016f2a..41b24c01aef33 100644 --- a/server/src/main/java/org/opensearch/node/Node.java +++ b/server/src/main/java/org/opensearch/node/Node.java @@ -632,6 +632,7 @@ protected Node( threadPool, remoteStoreFileCache ); + final Map directoryFactories = new HashMap<>(); pluginsService.filterPlugins(IndexStorePlugin.class) .stream() @@ -697,7 +698,8 @@ protected Node( searchModule.getValuesSourceRegistry(), recoveryStateFactories, remoteDirectoryFactory, - repositoriesServiceReference::get + repositoriesServiceReference::get, + remoteStoreFileCache ); } else { indicesService = new IndicesService( @@ -722,7 +724,8 @@ protected Node( searchModule.getValuesSourceRegistry(), recoveryStateFactories, remoteDirectoryFactory, - repositoriesServiceReference::get + repositoriesServiceReference::get, + remoteStoreFileCache ); } diff --git a/server/src/main/java/org/opensearch/node/NodeService.java b/server/src/main/java/org/opensearch/node/NodeService.java index ebceb175380e5..8d15c69d2c428 100644 --- a/server/src/main/java/org/opensearch/node/NodeService.java +++ b/server/src/main/java/org/opensearch/node/NodeService.java @@ -179,7 +179,8 @@ public NodeStats stats( boolean shardIndexingPressure, boolean searchBackpressure, boolean clusterManagerThrottling, - boolean weightedRoutingStats + boolean weightedRoutingStats, + boolean fileCacheStats ) { // for indices stats we want to include previous allocated shards stats as well (it will // only be applied to the sensible ones to use, like refresh/merge/flush/indexing stats) @@ -204,7 +205,8 @@ public NodeStats stats( shardIndexingPressure ? this.indexingPressureService.shardStats(indices) : null, searchBackpressure ? this.searchBackpressureService.nodeStats() : null, clusterManagerThrottling ? this.clusterService.getClusterManagerService().getThrottlingStats() : null, - weightedRoutingStats ? WeightedRoutingStats.getInstance() : null + weightedRoutingStats ? WeightedRoutingStats.getInstance() : null, + fileCacheStats ? indicesService.getFileCacheStats() : null ); } diff --git a/server/src/test/java/org/opensearch/action/admin/cluster/node/stats/NodeStatsTests.java b/server/src/test/java/org/opensearch/action/admin/cluster/node/stats/NodeStatsTests.java index a726a522e547b..473ab3d26a05c 100644 --- a/server/src/test/java/org/opensearch/action/admin/cluster/node/stats/NodeStatsTests.java +++ b/server/src/test/java/org/opensearch/action/admin/cluster/node/stats/NodeStatsTests.java @@ -748,7 +748,8 @@ public static NodeStats createNodeStats() { null, null, clusterManagerThrottlingStats, - weightedRoutingStats + weightedRoutingStats, + null ); } diff --git a/server/src/test/java/org/opensearch/cluster/DiskUsageTests.java b/server/src/test/java/org/opensearch/cluster/DiskUsageTests.java index c2c563d177dc7..3e69ec105e93b 100644 --- a/server/src/test/java/org/opensearch/cluster/DiskUsageTests.java +++ b/server/src/test/java/org/opensearch/cluster/DiskUsageTests.java @@ -188,6 +188,7 @@ public void testFillDiskUsage() { null, null, null, + null, null ), new NodeStats( @@ -211,6 +212,7 @@ public void testFillDiskUsage() { null, null, null, + null, null ), new NodeStats( @@ -234,6 +236,7 @@ public void testFillDiskUsage() { null, null, null, + null, null ) ); @@ -288,6 +291,7 @@ public void testFillDiskUsageSomeInvalidValues() { null, null, null, + null, null ), new NodeStats( @@ -311,6 +315,7 @@ public void testFillDiskUsageSomeInvalidValues() { null, null, null, + null, null ), new NodeStats( @@ -334,6 +339,7 @@ public void testFillDiskUsageSomeInvalidValues() { null, null, null, + null, null ) ); diff --git a/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java b/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java new file mode 100644 index 0000000000000..eeb88b672db2d --- /dev/null +++ b/server/src/test/java/org/opensearch/index/store/remote/filecache/FileCacheStatsTests.java @@ -0,0 +1,83 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.index.store.remote.filecache; + +import org.opensearch.common.io.stream.BytesStreamOutput; +import org.opensearch.common.io.stream.StreamInput; +import org.opensearch.index.store.remote.utils.cache.CacheUsage; +import org.opensearch.index.store.remote.utils.cache.stats.CacheStats; +import org.opensearch.test.OpenSearchTestCase; + +import java.io.IOException; + +public class FileCacheStatsTests extends OpenSearchTestCase { + private static final long BYTES_IN_GB = 1024 * 1024 * 1024; + + public static CacheStats getMockCacheStats() { + final long evicted = randomLongBetween(10000, BYTES_IN_GB); + final long removed = randomLongBetween(10000, BYTES_IN_GB); + final long replaced = randomLongBetween(0, 10000); + final long hits = randomLongBetween(0, 10000); + final long miss = randomLongBetween(0, 10000); + return new CacheStats(hits, miss, 0, removed, replaced, 0, evicted); + } + + public static CacheUsage getMockCacheUsage(long total) { + final long used = randomLongBetween(100, total); + final long active = randomLongBetween(10, used); + return new CacheUsage(used, active); + } + + public static long getMockCacheCapacity() { + return randomLongBetween(10 * BYTES_IN_GB, 1000 * BYTES_IN_GB); + } + + public static FileCacheStats getFileCacheStats(final long fileCacheCapacity, final CacheStats stats, final CacheUsage usage) { + return new FileCacheStats( + System.currentTimeMillis(), + usage.activeUsage(), + fileCacheCapacity, + usage.usage(), + stats.evictionWeight(), + stats.removeWeight(), + stats.replaceCount(), + stats.hitCount(), + stats.missCount() + ); + } + + public static FileCacheStats getMockFileCacheStats() { + final long fcSize = getMockCacheCapacity(); + return getFileCacheStats(fcSize, getMockCacheStats(), getMockCacheUsage(fcSize)); + } + + public static void validateFileCacheStats(FileCacheStats original, FileCacheStats deserialized) { + assertEquals(original.getTotal(), deserialized.getTotal()); + assertEquals(original.getUsed(), deserialized.getUsed()); + assertEquals(original.getUsedPercent(), deserialized.getUsedPercent()); + assertEquals(original.getActive(), deserialized.getActive()); + assertEquals(original.getActivePercent(), deserialized.getActivePercent()); + assertEquals(original.getEvicted(), deserialized.getEvicted()); + assertEquals(original.getRemoved(), deserialized.getRemoved()); + assertEquals(original.getReplacedCount(), deserialized.getReplacedCount()); + assertEquals(original.getCacheHits(), deserialized.getCacheHits()); + assertEquals(original.getCacheMiss(), deserialized.getCacheMiss()); + } + + public void testFileCacheStatsSerialization() throws IOException { + final FileCacheStats fileCacheStats = getMockFileCacheStats(); + try (BytesStreamOutput out = new BytesStreamOutput()) { + fileCacheStats.writeTo(out); + try (StreamInput in = out.bytes().streamInput()) { + // Validate original object against deserialized values + validateFileCacheStats(fileCacheStats, new FileCacheStats(in)); + } + } + } +} diff --git a/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java b/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java index 33b7e74ad7b51..5939ca0919342 100644 --- a/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java +++ b/server/src/test/java/org/opensearch/snapshots/SnapshotResiliencyTests.java @@ -1834,7 +1834,8 @@ public void onFailure(final Exception e) { null, emptyMap(), new RemoteSegmentStoreDirectoryFactory(() -> repositoriesService), - repositoriesServiceReference::get + repositoriesServiceReference::get, + null ); } else { indicesService = new IndicesService( @@ -1870,7 +1871,8 @@ public void onFailure(final Exception e) { null, emptyMap(), new RemoteSegmentStoreDirectoryFactory(() -> repositoriesService), - repositoriesServiceReference::get + repositoriesServiceReference::get, + null ); } final RecoverySettings recoverySettings = new RecoverySettings(settings, clusterSettings); diff --git a/test/framework/src/main/java/org/opensearch/cluster/MockInternalClusterInfoService.java b/test/framework/src/main/java/org/opensearch/cluster/MockInternalClusterInfoService.java index c47c090714383..007e717149a62 100644 --- a/test/framework/src/main/java/org/opensearch/cluster/MockInternalClusterInfoService.java +++ b/test/framework/src/main/java/org/opensearch/cluster/MockInternalClusterInfoService.java @@ -117,7 +117,8 @@ List adjustNodesStats(List nodesStats) { nodeStats.getShardIndexingPressureStats(), nodeStats.getSearchBackpressureStats(), nodeStats.getClusterManagerThrottlingStats(), - nodeStats.getWeightedRoutingStats() + nodeStats.getWeightedRoutingStats(), + nodeStats.getFileCacheStats() ); }).collect(Collectors.toList()); } diff --git a/test/framework/src/main/java/org/opensearch/test/InternalTestCluster.java b/test/framework/src/main/java/org/opensearch/test/InternalTestCluster.java index 346657b03c511..126e9357a15ca 100644 --- a/test/framework/src/main/java/org/opensearch/test/InternalTestCluster.java +++ b/test/framework/src/main/java/org/opensearch/test/InternalTestCluster.java @@ -2688,6 +2688,7 @@ public void ensureEstimatedStats() { false, false, false, + false, false ); assertThat(