Skip to content

Commit 471ca56

Browse files
committed
Track time on recent_search_load during DFSPhase
Incorporate the DFS phase timing into the recent_search_load calculation. This metric represents the cumulative time spent during the Query, Fetch, and DFS phases, and is exposed via the _stats API.
1 parent edc39be commit 471ca56

File tree

4 files changed

+106
-1
lines changed

4 files changed

+106
-1
lines changed

server/src/main/java/org/elasticsearch/index/search/stats/ShardSearchStats.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ public void onFetchPhase(SearchContext searchContext, long tookInNanos) {
117117
});
118118
}
119119

120+
@Override
121+
public void onDfsPhase(SearchContext searchContext, long tookInNanos) {
122+
computeStats(searchContext, statsHolder -> { statsHolder.recentSearchLoad.addIncrement(tookInNanos, System.nanoTime()); });
123+
}
124+
120125
private void computeStats(SearchContext searchContext, Consumer<StatsHolder> consumer) {
121126
consumer.accept(totalStats);
122127
var groupStats = searchContext.groupStats();

server/src/main/java/org/elasticsearch/index/shard/SearchOperationListener.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,28 @@ default void onFailedFetchPhase(SearchContext searchContext) {}
6565
*/
6666
default void onFetchPhase(SearchContext searchContext, long tookInNanos) {}
6767

68+
/**
69+
* Executed before the DFS phase is executed
70+
* @param searchContext the current search context
71+
*/
72+
default void onPreDfsPhase(SearchContext searchContext) {}
73+
74+
/**
75+
* Executed after the query DFS successfully finished.
76+
* Note: this is not invoked if the DFS phase execution failed.
77+
* @param searchContext the current search context
78+
* @param tookInNanos the number of nanoseconds the query execution took
79+
*
80+
* @see #onFailedQueryPhase(SearchContext)
81+
*/
82+
default void onDfsPhase(SearchContext searchContext, long tookInNanos) {}
83+
84+
/**
85+
* Executed if a dfs phased failed.
86+
* @param searchContext the current search context
87+
*/
88+
default void onFailedDfsPhase(SearchContext searchContext) {}
89+
6890
/**
6991
* Executed when a new reader context was created
7092
* @param readerContext the created context
@@ -182,6 +204,39 @@ public void onFetchPhase(SearchContext searchContext, long tookInNanos) {
182204
}
183205
}
184206

207+
@Override
208+
public void onPreDfsPhase(SearchContext searchContext) {
209+
for (SearchOperationListener listener : listeners) {
210+
try {
211+
listener.onPreDfsPhase(searchContext);
212+
} catch (Exception e) {
213+
logger.warn(() -> "onPreDfsPhase listener [" + listener + "] failed", e);
214+
}
215+
}
216+
}
217+
218+
@Override
219+
public void onFailedDfsPhase(SearchContext searchContext) {
220+
for (SearchOperationListener listener : listeners) {
221+
try {
222+
listener.onFailedDfsPhase(searchContext);
223+
} catch (Exception e) {
224+
logger.warn(() -> "onFailedDfsPhase listener [" + listener + "] failed", e);
225+
}
226+
}
227+
}
228+
229+
@Override
230+
public void onDfsPhase(SearchContext searchContext, long tookInNanos) {
231+
for (SearchOperationListener listener : listeners) {
232+
try {
233+
listener.onDfsPhase(searchContext, tookInNanos);
234+
} catch (Exception e) {
235+
logger.warn(() -> "onDfsPhase listener [" + listener + "] failed", e);
236+
}
237+
}
238+
}
239+
185240
@Override
186241
public void onNewReaderContext(ReaderContext readerContext) {
187242
for (SearchOperationListener listener : listeners) {

server/src/main/java/org/elasticsearch/search/SearchService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,18 @@ private DfsSearchResult executeDfsPhase(ShardSearchRequest request, SearchShardT
651651
Releasable ignored = readerContext.markAsUsed(getKeepAlive(request));
652652
SearchContext context = createContext(readerContext, request, task, ResultsType.DFS, false)
653653
) {
654-
DfsPhase.execute(context);
654+
final long beforeQueryTime = System.nanoTime();
655+
var opsListener = context.indexShard().getSearchOperationListener();
656+
opsListener.onPreDfsPhase(context);
657+
try {
658+
DfsPhase.execute(context);
659+
opsListener.onDfsPhase(context, System.nanoTime() - beforeQueryTime);
660+
opsListener = null;
661+
} finally {
662+
if (opsListener != null) {
663+
opsListener.onFailedDfsPhase(context);
664+
}
665+
}
655666
return context.dfsResult();
656667
} catch (Exception e) {
657668
logger.trace("Dfs phase failed", e);

server/src/test/java/org/elasticsearch/search/stats/ShardSearchStatsTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,40 @@ public void setup() {
5555
this.shardSearchStatsListener = new ShardSearchStats(searchStatsSettings);
5656
}
5757

58+
public void testDfsPhase() {
59+
try (SearchContext sc = createSearchContext(false)) {
60+
shardSearchStatsListener.onPreDfsPhase(sc);
61+
shardSearchStatsListener.onDfsPhase(sc, TimeUnit.MILLISECONDS.toNanos(TEN_MILLIS));
62+
63+
SearchStats.Stats stats = shardSearchStatsListener.stats().getTotal();
64+
assertTrue(stats.getSearchLoadRate() > 0.0);
65+
}
66+
}
67+
68+
public void testDfsPhase_withGroups() {
69+
try (SearchContext sc = createSearchContext(false)) {
70+
shardSearchStatsListener.onPreDfsPhase(sc);
71+
shardSearchStatsListener.onDfsPhase(sc, TimeUnit.MILLISECONDS.toNanos(TEN_MILLIS));
72+
73+
SearchStats searchStats = shardSearchStatsListener.stats("_all");
74+
SearchStats.Stats stats = shardSearchStatsListener.stats().getTotal();
75+
assertTrue(stats.getSearchLoadRate() > 0.0);
76+
77+
stats = Objects.requireNonNull(searchStats.getGroupStats()).get("group1");
78+
assertTrue(stats.getSearchLoadRate() > 0.0);
79+
}
80+
}
81+
82+
public void testDfsPhase_Failure() {
83+
try (SearchContext sc = createSearchContext(false)) {
84+
shardSearchStatsListener.onPreDfsPhase(sc);
85+
shardSearchStatsListener.onFailedDfsPhase(sc);
86+
87+
SearchStats.Stats stats = shardSearchStatsListener.stats().getTotal();
88+
assertEquals(0.0, stats.getSearchLoadRate(), 0);
89+
}
90+
}
91+
5892
public void testQueryPhase() {
5993
try (SearchContext sc = createSearchContext(false)) {
6094
shardSearchStatsListener.onPreQueryPhase(sc);

0 commit comments

Comments
 (0)