From 3a13164906b96d196dfdae22d0552381007ba51f Mon Sep 17 00:00:00 2001
From: Ruirui Zhang <mariazrr@amazon.com>
Date: Tue, 19 Mar 2024 10:47:24 -0700
Subject: [PATCH 1/5] add metrics to tack idle shard waking up Signed-off-by:
 Ruirui Zhang <mariazrr@amazon.com>

---
 .../index/search/stats/SearchStats.java       | 26 +++++++++++++++-
 .../index/search/stats/ShardSearchStats.java  |  9 +++++-
 .../opensearch/index/shard/IndexShard.java    |  4 +++
 .../index/shard/SearchOperationListener.java  | 16 ++++++++++
 .../index/search/stats/SearchStatsTests.java  |  7 +++--
 .../shard/SearchOperationListenerTests.java   | 31 +++++++++++++++++++
 6 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java b/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
index 576e00f8f30d1..55d196d010fbb 100644
--- a/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
+++ b/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
@@ -163,6 +163,8 @@ public static class Stats implements Writeable, ToXContentFragment {
         private long pitTimeInMillis;
         private long pitCurrent;
 
+        private long searchIdleWakenUpCount;
+
         @Nullable
         private RequestStatsLongHolder requestStatsLongHolder;
 
@@ -193,7 +195,8 @@ public Stats(
             long pitCurrent,
             long suggestCount,
             long suggestTimeInMillis,
-            long suggestCurrent
+            long suggestCurrent,
+            long searchIdleWakenUpCount
         ) {
             this.requestStatsLongHolder = new RequestStatsLongHolder();
             this.queryCount = queryCount;
@@ -220,6 +223,8 @@ public Stats(
             this.pitCount = pitCount;
             this.pitTimeInMillis = pitTimeInMillis;
             this.pitCurrent = pitCurrent;
+
+            this.searchIdleWakenUpCount = searchIdleWakenUpCount;
         }
 
         private Stats(StreamInput in) throws IOException {
@@ -255,6 +260,10 @@ private Stats(StreamInput in) throws IOException {
                 concurrentQueryCurrent = in.readVLong();
                 queryConcurrency = in.readVLong();
             }
+
+            if (in.getVersion().onOrAfter(Version.V_3_0_0)) {
+                searchIdleWakenUpCount = in.readVLong();
+            }
         }
 
         public void add(Stats stats) {
@@ -282,6 +291,8 @@ public void add(Stats stats) {
             pitCount += stats.pitCount;
             pitTimeInMillis += stats.pitTimeInMillis;
             pitCurrent += stats.pitCurrent;
+
+            searchIdleWakenUpCount += stats.searchIdleWakenUpCount;
         }
 
         public void addForClosingShard(Stats stats) {
@@ -306,6 +317,8 @@ public void addForClosingShard(Stats stats) {
             pitTimeInMillis += stats.pitTimeInMillis;
             pitCurrent += stats.pitCurrent;
             queryConcurrency += stats.queryConcurrency;
+
+            searchIdleWakenUpCount += stats.searchIdleWakenUpCount;
         }
 
         public long getQueryCount() {
@@ -412,6 +425,10 @@ public long getSuggestCurrent() {
             return suggestCurrent;
         }
 
+        public long getSearchIdleWakenUpCount() {
+            return searchIdleWakenUpCount;
+        }
+
         public static Stats readStats(StreamInput in) throws IOException {
             return new Stats(in);
         }
@@ -457,6 +474,10 @@ public void writeTo(StreamOutput out) throws IOException {
                 out.writeVLong(concurrentQueryCurrent);
                 out.writeVLong(queryConcurrency);
             }
+
+            if (out.getVersion().onOrAfter(Version.V_3_0_0)) {
+                out.writeVLong(searchIdleWakenUpCount);
+            }
         }
 
         @Override
@@ -486,6 +507,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
             builder.humanReadableField(Fields.SUGGEST_TIME_IN_MILLIS, Fields.SUGGEST_TIME, getSuggestTime());
             builder.field(Fields.SUGGEST_CURRENT, suggestCurrent);
 
+            builder.field(Fields.SEARCH_IDLE_WAKEN_UP_TOTAL, searchIdleWakenUpCount);
+
             if (requestStatsLongHolder != null) {
                 builder.startObject(Fields.REQUEST);
 
@@ -654,6 +677,7 @@ static final class Fields {
         static final String TIME = "time";
         static final String CURRENT = "current";
         static final String TOTAL = "total";
+        static final String SEARCH_IDLE_WAKEN_UP_TOTAL = "search_idle_waken_up_total";
 
     }
 
diff --git a/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java b/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
index 99e3f8465c5db..e33f1dd22cff3 100644
--- a/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
+++ b/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
@@ -213,6 +213,11 @@ public void onFreePitContext(ReaderContext readerContext) {
         totalStats.pitMetric.inc(TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - readerContext.getStartTimeInNano()));
     }
 
+    @Override
+    public void onNewSearchIdleWakenUp() {
+        totalStats.searchIdleMetric.inc();
+    }
+
     /**
      * Holder of statistics values
      *
@@ -239,6 +244,7 @@ static final class StatsHolder {
         final CounterMetric scrollCurrent = new CounterMetric();
         final CounterMetric pitCurrent = new CounterMetric();
         final CounterMetric suggestCurrent = new CounterMetric();
+        final CounterMetric searchIdleMetric = new CounterMetric();
 
         SearchStats.Stats stats() {
             return new SearchStats.Stats(
@@ -260,7 +266,8 @@ SearchStats.Stats stats() {
                 pitCurrent.count(),
                 suggestMetric.count(),
                 TimeUnit.NANOSECONDS.toMillis(suggestMetric.sum()),
-                suggestCurrent.count()
+                suggestCurrent.count(),
+                searchIdleMetric.count()
             );
         }
     }
diff --git a/server/src/main/java/org/opensearch/index/shard/IndexShard.java b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
index 977155a1cbb72..3ed42e3203bb5 100644
--- a/server/src/main/java/org/opensearch/index/shard/IndexShard.java
+++ b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
@@ -1859,6 +1859,10 @@ public Engine.Searcher acquireSearcher(String source) {
     }
 
     private void markSearcherAccessed() {
+        if (isSearchIdle()) {
+            SearchOperationListener searchOperationListener = getSearchOperationListener();
+            searchOperationListener.onNewSearchIdleWakenUp();
+        }
         lastSearcherAccess.lazySet(threadPool.relativeTimeInMillis());
     }
 
diff --git a/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java b/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
index 849a4f9c15318..dd66390661245 100644
--- a/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
+++ b/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
@@ -145,6 +145,11 @@ default void onNewPitContext(ReaderContext readerContext) {}
      */
     default void onFreePitContext(ReaderContext readerContext) {}
 
+    /**
+     * Executed when a shard goes from idle to non-idle state
+     */
+    default void onNewSearchIdleWakenUp() {}
+
     /**
      * A Composite listener that multiplexes calls to each of the listeners methods.
      */
@@ -310,5 +315,16 @@ public void onFreePitContext(ReaderContext readerContext) {
                 }
             }
         }
+
+        @Override
+        public void onNewSearchIdleWakenUp() {
+            for (SearchOperationListener listener : listeners) {
+                try {
+                    listener.onNewSearchIdleWakenUp();
+                } catch (Exception e) {
+                    logger.warn(() -> new ParameterizedMessage("onNewSearchIdleWakenUp listener [{}] failed", listener), e);
+                }
+            }
+        }
     }
 }
diff --git a/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java b/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
index 5656b77445772..089f16480caa7 100644
--- a/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
+++ b/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
@@ -57,9 +57,9 @@ public void testShardLevelSearchGroupStats() throws Exception {
         // let's create two dummy search stats with groups
         Map<String, Stats> groupStats1 = new HashMap<>();
         Map<String, Stats> groupStats2 = new HashMap<>();
-        groupStats2.put("group1", new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
-        SearchStats searchStats1 = new SearchStats(new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 0, groupStats1);
-        SearchStats searchStats2 = new SearchStats(new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 0, groupStats2);
+        groupStats2.put("group1", new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1));
+        SearchStats searchStats1 = new SearchStats(new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 0, groupStats1);
+        SearchStats searchStats2 = new SearchStats(new Stats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 0, groupStats2);
 
         // adding these two search stats and checking group stats are correct
         searchStats1.add(searchStats2);
@@ -128,6 +128,7 @@ private static void assertStats(Stats stats, long equalTo) {
         assertEquals(equalTo, stats.getSuggestCount());
         assertEquals(equalTo, stats.getSuggestTimeInMillis());
         assertEquals(equalTo, stats.getSuggestCurrent());
+        assertEquals(equalTo, stats.getSearchIdleWakenUpCount());
         // avg_concurrency is not summed up across stats
         assertEquals(1, stats.getConcurrentAvgSliceCount(), 0);
     }
diff --git a/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java b/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
index 98f86758ea2ca..543546486ee64 100644
--- a/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
+++ b/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
@@ -64,6 +64,7 @@ public void testListenersAreExecuted() {
         AtomicInteger newScrollContext = new AtomicInteger();
         AtomicInteger freeScrollContext = new AtomicInteger();
         AtomicInteger validateSearchContext = new AtomicInteger();
+        AtomicInteger searchIdleWakenUp = new AtomicInteger();
         AtomicInteger timeInNanos = new AtomicInteger(randomIntBetween(0, 10));
         SearchOperationListener listener = new SearchOperationListener() {
             @Override
@@ -133,6 +134,11 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
                 assertNotNull(readerContext);
                 validateSearchContext.incrementAndGet();
             }
+
+            @Override
+            public void onNewSearchIdleWakenUp() {
+                searchIdleWakenUp.incrementAndGet();
+            }
         };
 
         SearchOperationListener throwingListener = (SearchOperationListener) Proxy.newProxyInstance(
@@ -169,6 +175,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFetchPhase(ctx, timeInNanos.get());
@@ -182,6 +189,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onPreQueryPhase(ctx);
@@ -195,6 +203,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onPreFetchPhase(ctx);
@@ -208,6 +217,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFailedFetchPhase(ctx);
@@ -221,6 +231,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFailedQueryPhase(ctx);
@@ -234,6 +245,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onNewReaderContext(mock(ReaderContext.class));
@@ -247,6 +259,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onNewScrollContext(mock(ReaderContext.class));
@@ -260,6 +273,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(2, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFreeReaderContext(mock(ReaderContext.class));
@@ -273,6 +287,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(0, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFreeScrollContext(mock(ReaderContext.class));
@@ -286,6 +301,21 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(2, freeScrollContext.get());
+        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, validateSearchContext.get());
+
+        compositeListener.onNewSearchIdleWakenUp();
+        assertEquals(2, preFetch.get());
+        assertEquals(2, preQuery.get());
+        assertEquals(2, failedFetch.get());
+        assertEquals(2, failedQuery.get());
+        assertEquals(2, onQuery.get());
+        assertEquals(2, onFetch.get());
+        assertEquals(2, newContext.get());
+        assertEquals(2, newScrollContext.get());
+        assertEquals(2, freeContext.get());
+        assertEquals(2, freeScrollContext.get());
+        assertEquals(2, searchIdleWakenUp.get());
         assertEquals(0, validateSearchContext.get());
 
         if (throwingListeners == 0) {
@@ -311,6 +341,7 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(2, freeScrollContext.get());
+        assertEquals(2, searchIdleWakenUp.get());
         assertEquals(2, validateSearchContext.get());
     }
 }

From 8533d403c295d60d824a194d4c0d7a828fd57f49 Mon Sep 17 00:00:00 2001
From: Ruirui Zhang <mariazrr@amazon.com>
Date: Tue, 19 Mar 2024 10:52:23 -0700
Subject: [PATCH 2/5] modify CHANGELOG Signed-off-by: Ruirui Zhang
 <mariazrr@amazon.com>

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fb141e189bd3..3701a8a2c0e44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -118,6 +118,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 - [Tiered caching] Add Stale keys Management and CacheCleaner to IndicesRequestCache ([#12625](https://github.com/opensearch-project/OpenSearch/pull/12625))
 - [Tiered caching] Add serializer integration to allow ehcache disk cache to use non-primitive values ([#12709](https://github.com/opensearch-project/OpenSearch/pull/12709))
 - [Admission Control] Integrated IO Based AdmissionController to AdmissionControl Framework ([#12583](https://github.com/opensearch-project/OpenSearch/pull/12583))
+- Add a counter to node stat api to track shard going from idle to non-idle ([#12768](https://github.com/opensearch-project/OpenSearch/pull/12768))
 
 ### Dependencies
 - Bump `peter-evans/find-comment` from 2 to 3 ([#12288](https://github.com/opensearch-project/OpenSearch/pull/12288))

From c5ee63f949ab66b5952b43a6eb09dd084a45f313 Mon Sep 17 00:00:00 2001
From: Ruirui Zhang <mariazrr@amazon.com>
Date: Thu, 21 Mar 2024 16:16:29 -0700
Subject: [PATCH 3/5] add metric to cat api Signed-off-by: Ruirui Zhang
 <mariazrr@amazon.com>

---
 .../index/search/stats/SearchStats.java       | 22 ++++++-------
 .../index/search/stats/ShardSearchStats.java  |  2 +-
 .../opensearch/index/shard/IndexShard.java    |  2 +-
 .../index/shard/SearchOperationListener.java  |  8 ++---
 .../rest/action/cat/RestIndicesAction.java    | 12 +++++++
 .../rest/action/cat/RestNodesAction.java      |  5 +++
 .../rest/action/cat/RestShardsAction.java     |  5 +++
 .../index/search/stats/SearchStatsTests.java  |  2 +-
 .../shard/SearchOperationListenerTests.java   | 32 +++++++++----------
 .../action/cat/RestShardsActionTests.java     |  8 ++---
 10 files changed, 60 insertions(+), 38 deletions(-)

diff --git a/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java b/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
index 55d196d010fbb..d3a53fcc0e2d8 100644
--- a/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
+++ b/server/src/main/java/org/opensearch/index/search/stats/SearchStats.java
@@ -163,7 +163,7 @@ public static class Stats implements Writeable, ToXContentFragment {
         private long pitTimeInMillis;
         private long pitCurrent;
 
-        private long searchIdleWakenUpCount;
+        private long searchIdleReactivateCount;
 
         @Nullable
         private RequestStatsLongHolder requestStatsLongHolder;
@@ -196,7 +196,7 @@ public Stats(
             long suggestCount,
             long suggestTimeInMillis,
             long suggestCurrent,
-            long searchIdleWakenUpCount
+            long searchIdleReactivateCount
         ) {
             this.requestStatsLongHolder = new RequestStatsLongHolder();
             this.queryCount = queryCount;
@@ -224,7 +224,7 @@ public Stats(
             this.pitTimeInMillis = pitTimeInMillis;
             this.pitCurrent = pitCurrent;
 
-            this.searchIdleWakenUpCount = searchIdleWakenUpCount;
+            this.searchIdleReactivateCount = searchIdleReactivateCount;
         }
 
         private Stats(StreamInput in) throws IOException {
@@ -262,7 +262,7 @@ private Stats(StreamInput in) throws IOException {
             }
 
             if (in.getVersion().onOrAfter(Version.V_3_0_0)) {
-                searchIdleWakenUpCount = in.readVLong();
+                searchIdleReactivateCount = in.readVLong();
             }
         }
 
@@ -292,7 +292,7 @@ public void add(Stats stats) {
             pitTimeInMillis += stats.pitTimeInMillis;
             pitCurrent += stats.pitCurrent;
 
-            searchIdleWakenUpCount += stats.searchIdleWakenUpCount;
+            searchIdleReactivateCount += stats.searchIdleReactivateCount;
         }
 
         public void addForClosingShard(Stats stats) {
@@ -318,7 +318,7 @@ public void addForClosingShard(Stats stats) {
             pitCurrent += stats.pitCurrent;
             queryConcurrency += stats.queryConcurrency;
 
-            searchIdleWakenUpCount += stats.searchIdleWakenUpCount;
+            searchIdleReactivateCount += stats.searchIdleReactivateCount;
         }
 
         public long getQueryCount() {
@@ -425,8 +425,8 @@ public long getSuggestCurrent() {
             return suggestCurrent;
         }
 
-        public long getSearchIdleWakenUpCount() {
-            return searchIdleWakenUpCount;
+        public long getSearchIdleReactivateCount() {
+            return searchIdleReactivateCount;
         }
 
         public static Stats readStats(StreamInput in) throws IOException {
@@ -476,7 +476,7 @@ public void writeTo(StreamOutput out) throws IOException {
             }
 
             if (out.getVersion().onOrAfter(Version.V_3_0_0)) {
-                out.writeVLong(searchIdleWakenUpCount);
+                out.writeVLong(searchIdleReactivateCount);
             }
         }
 
@@ -507,7 +507,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
             builder.humanReadableField(Fields.SUGGEST_TIME_IN_MILLIS, Fields.SUGGEST_TIME, getSuggestTime());
             builder.field(Fields.SUGGEST_CURRENT, suggestCurrent);
 
-            builder.field(Fields.SEARCH_IDLE_WAKEN_UP_TOTAL, searchIdleWakenUpCount);
+            builder.field(Fields.SEARCH_IDLE_REACTIVATE_COUNT_TOTAL, searchIdleReactivateCount);
 
             if (requestStatsLongHolder != null) {
                 builder.startObject(Fields.REQUEST);
@@ -677,7 +677,7 @@ static final class Fields {
         static final String TIME = "time";
         static final String CURRENT = "current";
         static final String TOTAL = "total";
-        static final String SEARCH_IDLE_WAKEN_UP_TOTAL = "search_idle_waken_up_total";
+        static final String SEARCH_IDLE_REACTIVATE_COUNT_TOTAL = "search_idle_reactivate_count_total";
 
     }
 
diff --git a/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java b/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
index e33f1dd22cff3..3098986852cc1 100644
--- a/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
+++ b/server/src/main/java/org/opensearch/index/search/stats/ShardSearchStats.java
@@ -214,7 +214,7 @@ public void onFreePitContext(ReaderContext readerContext) {
     }
 
     @Override
-    public void onNewSearchIdleWakenUp() {
+    public void onSearchIdleReactivation() {
         totalStats.searchIdleMetric.inc();
     }
 
diff --git a/server/src/main/java/org/opensearch/index/shard/IndexShard.java b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
index 3ed42e3203bb5..aa7360689225a 100644
--- a/server/src/main/java/org/opensearch/index/shard/IndexShard.java
+++ b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
@@ -1861,7 +1861,7 @@ public Engine.Searcher acquireSearcher(String source) {
     private void markSearcherAccessed() {
         if (isSearchIdle()) {
             SearchOperationListener searchOperationListener = getSearchOperationListener();
-            searchOperationListener.onNewSearchIdleWakenUp();
+            searchOperationListener.onSearchIdleReactivation();
         }
         lastSearcherAccess.lazySet(threadPool.relativeTimeInMillis());
     }
diff --git a/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java b/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
index dd66390661245..94079db468f9c 100644
--- a/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
+++ b/server/src/main/java/org/opensearch/index/shard/SearchOperationListener.java
@@ -148,7 +148,7 @@ default void onFreePitContext(ReaderContext readerContext) {}
     /**
      * Executed when a shard goes from idle to non-idle state
      */
-    default void onNewSearchIdleWakenUp() {}
+    default void onSearchIdleReactivation() {}
 
     /**
      * A Composite listener that multiplexes calls to each of the listeners methods.
@@ -317,12 +317,12 @@ public void onFreePitContext(ReaderContext readerContext) {
         }
 
         @Override
-        public void onNewSearchIdleWakenUp() {
+        public void onSearchIdleReactivation() {
             for (SearchOperationListener listener : listeners) {
                 try {
-                    listener.onNewSearchIdleWakenUp();
+                    listener.onSearchIdleReactivation();
                 } catch (Exception e) {
-                    logger.warn(() -> new ParameterizedMessage("onNewSearchIdleWakenUp listener [{}] failed", listener), e);
+                    logger.warn(() -> new ParameterizedMessage("onNewSearchIdleReactivation listener [{}] failed", listener), e);
                 }
             }
         }
diff --git a/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java b/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
index 9dc711f804144..55cb1dd760d4b 100644
--- a/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
+++ b/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
@@ -641,6 +641,15 @@ protected Table getTableWithHeader(final RestRequest request) {
         );
         table.addCell("pri.search.point_in_time_total", "default:false;text-align:right;desc:completed point in time contexts");
 
+        table.addCell(
+            "search.search_idle_reactivate_count_total",
+            "sibling:pri;alias:ssirct,searchSearchIdleReactivateCountTotal;default:false;text-align:right;desc:number of times a shard reactivated"
+        );
+        table.addCell(
+            "pri.search.search_idle_reactivate_count_total",
+            "default:false;text-align:right;desc:number of times a shard reactivated"
+        );
+
         table.addCell("segments.count", "sibling:pri;alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
         table.addCell("pri.segments.count", "default:false;text-align:right;desc:number of segments");
 
@@ -943,6 +952,9 @@ Table buildTable(
             table.addCell(totalStats.getSearch() == null ? null : totalStats.getSearch().getTotal().getPitCount());
             table.addCell(primaryStats.getSearch() == null ? null : primaryStats.getSearch().getTotal().getPitCount());
 
+            table.addCell(totalStats.getSearch() == null ? null : totalStats.getSearch().getTotal().getSearchIdleReactivateCount());
+            table.addCell(primaryStats.getSearch() == null ? null : primaryStats.getSearch().getTotal().getSearchIdleReactivateCount());
+
             table.addCell(totalStats.getSegments() == null ? null : totalStats.getSegments().getCount());
             table.addCell(primaryStats.getSegments() == null ? null : primaryStats.getSegments().getCount());
 
diff --git a/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java b/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
index e11012a23fce7..96cbfba4072a9 100644
--- a/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
+++ b/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
@@ -338,6 +338,10 @@ protected Table getTableWithHeader(final RestRequest request) {
             "search.point_in_time_total",
             "alias:scto,searchPointInTimeTotal;default:false;text-align:right;desc:completed point in time contexts"
         );
+        table.addCell(
+            "search.search_idle_reactivate_count_total",
+            "alias:ssirct,searchSearchIdleReactivateCountTotal;default:false;text-align:right;desc:number of times a shard reactivated"
+        );
 
         table.addCell("segments.count", "alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
         table.addCell("segments.memory", "alias:sm,segmentsMemory;default:false;text-align:right;desc:memory used by segments");
@@ -555,6 +559,7 @@ Table buildTable(
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitCurrent());
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitTime());
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitCount());
+            table.addCell(searchStats == null ? null : searchStats.getTotal().getSearchIdleReactivateCount());
 
             SegmentsStats segmentsStats = indicesStats == null ? null : indicesStats.getSegments();
             table.addCell(segmentsStats == null ? null : segmentsStats.getCount());
diff --git a/server/src/main/java/org/opensearch/rest/action/cat/RestShardsAction.java b/server/src/main/java/org/opensearch/rest/action/cat/RestShardsAction.java
index 4cd10c6874e0a..4413c8eb370be 100644
--- a/server/src/main/java/org/opensearch/rest/action/cat/RestShardsAction.java
+++ b/server/src/main/java/org/opensearch/rest/action/cat/RestShardsAction.java
@@ -253,6 +253,10 @@ protected Table getTableWithHeader(final RestRequest request) {
             "search.point_in_time_total",
             "alias:spto,searchPointInTimeTotal;default:false;text-align:right;desc:completed point in time contexts"
         );
+        table.addCell(
+            "search.search_idle_reactivate_count_total",
+            "alias:ssirct,searchSearchIdleReactivateCountTotal;default:false;text-align:right;desc:number of times a shard reactivated"
+        );
 
         table.addCell("segments.count", "alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
         table.addCell("segments.memory", "alias:sm,segmentsMemory;default:false;text-align:right;desc:memory used by segments");
@@ -427,6 +431,7 @@ Table buildTable(RestRequest request, ClusterStateResponse state, IndicesStatsRe
             table.addCell(getOrNull(commonStats, CommonStats::getSearch, i -> i.getTotal().getPitCurrent()));
             table.addCell(getOrNull(commonStats, CommonStats::getSearch, i -> i.getTotal().getPitTime()));
             table.addCell(getOrNull(commonStats, CommonStats::getSearch, i -> i.getTotal().getPitCount()));
+            table.addCell(getOrNull(commonStats, CommonStats::getSearch, i -> i.getTotal().getSearchIdleReactivateCount()));
 
             table.addCell(getOrNull(commonStats, CommonStats::getSegments, SegmentsStats::getCount));
             table.addCell(getOrNull(commonStats, CommonStats::getSegments, SegmentsStats::getZeroMemory));
diff --git a/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java b/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
index 089f16480caa7..594700ea60b3e 100644
--- a/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
+++ b/server/src/test/java/org/opensearch/index/search/stats/SearchStatsTests.java
@@ -128,7 +128,7 @@ private static void assertStats(Stats stats, long equalTo) {
         assertEquals(equalTo, stats.getSuggestCount());
         assertEquals(equalTo, stats.getSuggestTimeInMillis());
         assertEquals(equalTo, stats.getSuggestCurrent());
-        assertEquals(equalTo, stats.getSearchIdleWakenUpCount());
+        assertEquals(equalTo, stats.getSearchIdleReactivateCount());
         // avg_concurrency is not summed up across stats
         assertEquals(1, stats.getConcurrentAvgSliceCount(), 0);
     }
diff --git a/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java b/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
index 543546486ee64..c61c13eecf2c3 100644
--- a/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
+++ b/server/src/test/java/org/opensearch/index/shard/SearchOperationListenerTests.java
@@ -64,7 +64,7 @@ public void testListenersAreExecuted() {
         AtomicInteger newScrollContext = new AtomicInteger();
         AtomicInteger freeScrollContext = new AtomicInteger();
         AtomicInteger validateSearchContext = new AtomicInteger();
-        AtomicInteger searchIdleWakenUp = new AtomicInteger();
+        AtomicInteger searchIdleReactivateCount = new AtomicInteger();
         AtomicInteger timeInNanos = new AtomicInteger(randomIntBetween(0, 10));
         SearchOperationListener listener = new SearchOperationListener() {
             @Override
@@ -136,8 +136,8 @@ public void validateReaderContext(ReaderContext readerContext, TransportRequest
             }
 
             @Override
-            public void onNewSearchIdleWakenUp() {
-                searchIdleWakenUp.incrementAndGet();
+            public void onSearchIdleReactivation() {
+                searchIdleReactivateCount.incrementAndGet();
             }
         };
 
@@ -175,7 +175,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFetchPhase(ctx, timeInNanos.get());
@@ -189,7 +189,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onPreQueryPhase(ctx);
@@ -203,7 +203,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onPreFetchPhase(ctx);
@@ -217,7 +217,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFailedFetchPhase(ctx);
@@ -231,7 +231,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFailedQueryPhase(ctx);
@@ -245,7 +245,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onNewReaderContext(mock(ReaderContext.class));
@@ -259,7 +259,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(0, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onNewScrollContext(mock(ReaderContext.class));
@@ -273,7 +273,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(2, newScrollContext.get());
         assertEquals(0, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFreeReaderContext(mock(ReaderContext.class));
@@ -287,7 +287,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(0, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         compositeListener.onFreeScrollContext(mock(ReaderContext.class));
@@ -301,10 +301,10 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(2, freeScrollContext.get());
-        assertEquals(0, searchIdleWakenUp.get());
+        assertEquals(0, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
-        compositeListener.onNewSearchIdleWakenUp();
+        compositeListener.onSearchIdleReactivation();
         assertEquals(2, preFetch.get());
         assertEquals(2, preQuery.get());
         assertEquals(2, failedFetch.get());
@@ -315,7 +315,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(2, freeScrollContext.get());
-        assertEquals(2, searchIdleWakenUp.get());
+        assertEquals(2, searchIdleReactivateCount.get());
         assertEquals(0, validateSearchContext.get());
 
         if (throwingListeners == 0) {
@@ -341,7 +341,7 @@ public void onNewSearchIdleWakenUp() {
         assertEquals(2, newScrollContext.get());
         assertEquals(2, freeContext.get());
         assertEquals(2, freeScrollContext.get());
-        assertEquals(2, searchIdleWakenUp.get());
+        assertEquals(2, searchIdleReactivateCount.get());
         assertEquals(2, validateSearchContext.get());
     }
 }
diff --git a/server/src/test/java/org/opensearch/rest/action/cat/RestShardsActionTests.java b/server/src/test/java/org/opensearch/rest/action/cat/RestShardsActionTests.java
index fa13ec2036797..883df7da5d717 100644
--- a/server/src/test/java/org/opensearch/rest/action/cat/RestShardsActionTests.java
+++ b/server/src/test/java/org/opensearch/rest/action/cat/RestShardsActionTests.java
@@ -125,7 +125,7 @@ public void testBuildTable() {
         assertThat(headers.get(6).value, equalTo("ip"));
         assertThat(headers.get(7).value, equalTo("id"));
         assertThat(headers.get(8).value, equalTo("node"));
-        assertThat(headers.get(78).value, equalTo("docs.deleted"));
+        assertThat(headers.get(79).value, equalTo("docs.deleted"));
 
         final List<List<Table.Cell>> rows = table.getRows();
         assertThat(rows.size(), equalTo(numShards));
@@ -141,9 +141,9 @@ public void testBuildTable() {
             assertThat(row.get(4).value, equalTo(shardStats.getStats().getDocs().getCount()));
             assertThat(row.get(6).value, equalTo(localNode.getHostAddress()));
             assertThat(row.get(7).value, equalTo(localNode.getId()));
-            assertThat(row.get(76).value, equalTo(shardStats.getDataPath()));
-            assertThat(row.get(77).value, equalTo(shardStats.getStatePath()));
-            assertThat(row.get(78).value, equalTo(shardStats.getStats().getDocs().getDeleted()));
+            assertThat(row.get(77).value, equalTo(shardStats.getDataPath()));
+            assertThat(row.get(78).value, equalTo(shardStats.getStatePath()));
+            assertThat(row.get(79).value, equalTo(shardStats.getStats().getDocs().getDeleted()));
         }
     }
 }

From 49ebf20731582f5fc6e0f02f25acc4a80ad1ead6 Mon Sep 17 00:00:00 2001
From: Ruirui Zhang <mariazrr@amazon.com>
Date: Mon, 25 Mar 2024 16:27:05 -0700
Subject: [PATCH 4/5] modify the counter logic Signed-off-by: Ruirui Zhang
 <mariazrr@amazon.com>

---
 .../test/cat.shards/10_basic.yml              | 99 ++++++++++++++++++-
 .../opensearch/index/shard/IndexShard.java    |  9 +-
 .../rest/action/cat/RestIndicesAction.java    | 12 ---
 .../rest/action/cat/RestNodesAction.java      |  5 -
 4 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
index 29fbf55417961..77b02bc601e86 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
@@ -1,13 +1,108 @@
 "Help":
   - skip:
-      version: " - 2.11.99"
+      version: " - 2.99.99"
+      reason:  search idle reactivate count total is only added in 3.0.0
+      features: node_selector
+  - do:
+      cat.shards:
+        help: true
+      node_selector:
+        version: "3.0.0 - "
+
+  - match:
+      $body: |
+        /^   index                            .+   \n
+             shard                            .+   \n
+             prirep                           .+   \n
+             state                            .+   \n
+             docs                             .+   \n
+             store                            .+   \n
+             ip                               .+   \n
+             id                               .+   \n
+             node                             .+   \n
+             sync_id                          .+   \n
+             unassigned.reason                .+   \n
+             unassigned.at                    .+   \n
+             unassigned.for                   .+   \n
+             unassigned.details               .+   \n
+             recoverysource.type              .+   \n
+             completion.size                  .+   \n
+             fielddata.memory_size            .+   \n
+             fielddata.evictions              .+   \n
+             query_cache.memory_size          .+   \n
+             query_cache.evictions            .+   \n
+             flush.total                      .+   \n
+             flush.total_time                 .+   \n
+             get.current                      .+   \n
+             get.time                         .+   \n
+             get.total                        .+   \n
+             get.exists_time                  .+   \n
+             get.exists_total                 .+   \n
+             get.missing_time                 .+   \n
+             get.missing_total                .+   \n
+             indexing.delete_current          .+   \n
+             indexing.delete_time             .+   \n
+             indexing.delete_total            .+   \n
+             indexing.index_current           .+   \n
+             indexing.index_time              .+   \n
+             indexing.index_total             .+   \n
+             indexing.index_failed            .+   \n
+             merges.current                   .+   \n
+             merges.current_docs              .+   \n
+             merges.current_size              .+   \n
+             merges.total                     .+   \n
+             merges.total_docs                .+   \n
+             merges.total_size                .+   \n
+             merges.total_time                .+   \n
+             refresh.total                    .+   \n
+             refresh.time                     .+   \n
+             refresh.external_total           .+   \n
+             refresh.external_time            .+   \n
+             refresh.listeners                .+   \n
+             search.fetch_current             .+   \n
+             search.fetch_time                .+   \n
+             search.fetch_total               .+   \n
+             search.open_contexts             .+   \n
+             search.query_current             .+   \n
+             search.query_time                .+   \n
+             search.query_total               .+   \n
+             search.concurrent_query_current  .+   \n
+             search.concurrent_query_time     .+   \n
+             search.concurrent_query_total    .+   \n
+             search.concurrent_avg_slice_count  .+   \n
+             search.scroll_current            .+   \n
+             search.scroll_time               .+   \n
+             search.scroll_total              .+   \n
+             search.point_in_time_current     .+   \n
+             search.point_in_time_time        .+   \n
+             search.point_in_time_total       .+   \n
+             search.search_idle_reactivate_count_total  .+   \n
+             segments.count                   .+   \n
+             segments.memory                  .+   \n
+             segments.index_writer_memory     .+   \n
+             segments.version_map_memory      .+   \n
+             segments.fixed_bitset_memory     .+   \n
+             seq_no.max                       .+   \n
+             seq_no.local_checkpoint          .+   \n
+             seq_no.global_checkpoint         .+   \n
+             warmer.current                   .+   \n
+             warmer.total                     .+   \n
+             warmer.total_time                .+   \n
+             path.data                        .+   \n
+             path.state                       .+   \n
+             docs.deleted                     .+   \n
+        $/
+---
+"Help":
+  - skip:
+      version: " - 2.11.99 , 3.0.0 - "
       reason:  deleted docs and concurrent search are added in 2.12.0
       features: node_selector
   - do:
       cat.shards:
         help: true
       node_selector:
-        version: "2.12.0 - "
+        version: "2.12.0 - 2.99.99"
 
   - match:
       $body: |
diff --git a/server/src/main/java/org/opensearch/index/shard/IndexShard.java b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
index aa7360689225a..d2ca3b3331db5 100644
--- a/server/src/main/java/org/opensearch/index/shard/IndexShard.java
+++ b/server/src/main/java/org/opensearch/index/shard/IndexShard.java
@@ -1859,10 +1859,6 @@ public Engine.Searcher acquireSearcher(String source) {
     }
 
     private void markSearcherAccessed() {
-        if (isSearchIdle()) {
-            SearchOperationListener searchOperationListener = getSearchOperationListener();
-            searchOperationListener.onSearchIdleReactivation();
-        }
         lastSearcherAccess.lazySet(threadPool.relativeTimeInMillis());
     }
 
@@ -4591,9 +4587,14 @@ public void afterRefresh(boolean didRefresh) {
      *                 <code>true</code> if the listener was registered to wait for a refresh.
      */
     public final void awaitShardSearchActive(Consumer<Boolean> listener) {
+        boolean isSearchIdle = isSearchIdle();
         markSearcherAccessed(); // move the shard into non-search idle
         final Translog.Location location = pendingRefreshLocation.get();
         if (location != null) {
+            if (isSearchIdle) {
+                SearchOperationListener searchOperationListener = getSearchOperationListener();
+                searchOperationListener.onSearchIdleReactivation();
+            }
             addRefreshListener(location, (b) -> {
                 pendingRefreshLocation.compareAndSet(location, null);
                 listener.accept(true);
diff --git a/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java b/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
index 55cb1dd760d4b..9dc711f804144 100644
--- a/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
+++ b/server/src/main/java/org/opensearch/rest/action/cat/RestIndicesAction.java
@@ -641,15 +641,6 @@ protected Table getTableWithHeader(final RestRequest request) {
         );
         table.addCell("pri.search.point_in_time_total", "default:false;text-align:right;desc:completed point in time contexts");
 
-        table.addCell(
-            "search.search_idle_reactivate_count_total",
-            "sibling:pri;alias:ssirct,searchSearchIdleReactivateCountTotal;default:false;text-align:right;desc:number of times a shard reactivated"
-        );
-        table.addCell(
-            "pri.search.search_idle_reactivate_count_total",
-            "default:false;text-align:right;desc:number of times a shard reactivated"
-        );
-
         table.addCell("segments.count", "sibling:pri;alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
         table.addCell("pri.segments.count", "default:false;text-align:right;desc:number of segments");
 
@@ -952,9 +943,6 @@ Table buildTable(
             table.addCell(totalStats.getSearch() == null ? null : totalStats.getSearch().getTotal().getPitCount());
             table.addCell(primaryStats.getSearch() == null ? null : primaryStats.getSearch().getTotal().getPitCount());
 
-            table.addCell(totalStats.getSearch() == null ? null : totalStats.getSearch().getTotal().getSearchIdleReactivateCount());
-            table.addCell(primaryStats.getSearch() == null ? null : primaryStats.getSearch().getTotal().getSearchIdleReactivateCount());
-
             table.addCell(totalStats.getSegments() == null ? null : totalStats.getSegments().getCount());
             table.addCell(primaryStats.getSegments() == null ? null : primaryStats.getSegments().getCount());
 
diff --git a/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java b/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
index 96cbfba4072a9..e11012a23fce7 100644
--- a/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
+++ b/server/src/main/java/org/opensearch/rest/action/cat/RestNodesAction.java
@@ -338,10 +338,6 @@ protected Table getTableWithHeader(final RestRequest request) {
             "search.point_in_time_total",
             "alias:scto,searchPointInTimeTotal;default:false;text-align:right;desc:completed point in time contexts"
         );
-        table.addCell(
-            "search.search_idle_reactivate_count_total",
-            "alias:ssirct,searchSearchIdleReactivateCountTotal;default:false;text-align:right;desc:number of times a shard reactivated"
-        );
 
         table.addCell("segments.count", "alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
         table.addCell("segments.memory", "alias:sm,segmentsMemory;default:false;text-align:right;desc:memory used by segments");
@@ -559,7 +555,6 @@ Table buildTable(
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitCurrent());
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitTime());
             table.addCell(searchStats == null ? null : searchStats.getTotal().getPitCount());
-            table.addCell(searchStats == null ? null : searchStats.getTotal().getSearchIdleReactivateCount());
 
             SegmentsStats segmentsStats = indicesStats == null ? null : indicesStats.getSegments();
             table.addCell(segmentsStats == null ? null : segmentsStats.getCount());

From 5172c09ce127c63a556e340dd938ae6b79242fad Mon Sep 17 00:00:00 2001
From: Ruirui Zhang <mariazrr@amazon.com>
Date: Tue, 26 Mar 2024 10:29:44 -0700
Subject: [PATCH 5/5] modify test Signed-off-by: Ruirui Zhang
 <mariazrr@amazon.com>

---
 .../main/resources/rest-api-spec/test/cat.shards/10_basic.yml   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
index 77b02bc601e86..c309f19b454e7 100644
--- a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
+++ b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml
@@ -93,7 +93,7 @@
              docs.deleted                     .+   \n
         $/
 ---
-"Help":
+"Help from 2.12.0 to 2.99.99":
   - skip:
       version: " - 2.11.99 , 3.0.0 - "
       reason:  deleted docs and concurrent search are added in 2.12.0