Skip to content

Conversation

javanna
Copy link
Member

@javanna javanna commented Sep 12, 2025

TransportSearchAction collects telemetry around CCS features used as well as took time of a search request. It does that via a action listener wrapping. The open PIT API uses TransportSearchAction for its execution, yet it does not wrap the listener in the same way, as search telemetry should not be affected by it. As a result, we have a TelemetryListener interface, with some instanceof checks in the code and a single implementation of such interface that is the action listener wrapper itself, which allows to record the telemetry on response.

This can be simplified by moving the listener wrapping to the TransportSearchAction code, and specialize a little the open PIT path so that telemetry can still be disabled for it. Along with the simplifications, this change allows us to delay the wrapping of the listener, which will allow us to grab the resolved indices in #134232 .

private class SearchResponseActionListener extends DelegatingActionListener<SearchResponse, SearchResponse>
implements
TelemetryListener {
private static class SearchTelemetryListener extends DelegatingActionListener<SearchResponse, SearchResponse> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this static, it feels much better to be able to reason about its dependencies and not have it be tied to TransportSearchAction's lifecycle.


private interface TelemetryListener {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given I moved the wrapping inside of executeSearch, this interface is no longer required. It was there for open PIT only as it provides a different type of listener.

SearchRequest original,
ActionListener<SearchResponse> originalListener,
Function<ActionListener<SearchResponse>, SearchPhaseProvider> searchPhaseProvider,
boolean collectSearchTelemetry
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't perfect, but it gets the job done. Ideally, open PIT would have its own transport action, but I am not even sure that's a change worth making given its complexity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this change this flag was not needed because the listener had all the telemetry logic encapsulated in it. The downside was that we needed to do some instanceof checks on it. Another issue I found with that is that it does not allow to store resolved indices (without carrying a reference to the search request in the listener).

@javanna javanna changed the title Delay SearchResponseActionListener wrapping to a single location Centralize telemetry listener wrapping in TransportSearchAction Sep 12, 2025
@javanna javanna marked this pull request as ready for review September 12, 2025 15:31
@elasticsearchmachine elasticsearchmachine added the needs:triage Requires assignment of a team area label label Sep 12, 2025
@@ -2069,7 +2072,7 @@ public void onResponse(SearchResponse searchResponse) {
}
searchResponseMetrics.incrementResponseCount(responseCountTotalStatus);

if (collectTelemetry()) {
if (collectCCSTelemetry()) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed this to avoid confusion, as this flag controls only whether we record CCS specific telemetry.

@javanna javanna added :Search Foundations/Search Catch all for Search Foundations >refactoring and removed needs:triage Requires assignment of a team area label labels Sep 12, 2025
@javanna javanna requested a review from smalyshev September 12, 2025 15:58
@elasticsearchmachine elasticsearchmachine added the Team:Search Foundations Meta label for the Search Foundations team in Elasticsearch label Sep 12, 2025
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-search-foundations (Team:Search Foundations)

if (ccsCheckCompatibility) {
checkCCSVersionCompatibility(rewritten);
}

final CCSUsage.Builder ccsUsageBuilder = new CCSUsage.Builder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we always create and update ccsUsageBuilder but only use it if collectSearchTelemetry is true?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I was a bit lazy here, I will iterate over this once more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not so different from how things already were: a CCS usage builder always got created despite we may not be collecting CCS telemetry. I did not like that my change made things even harder to read. I tied the creation of the listener to the telemetry collection now, so that we only create the usage builder when necessary, and the code should be easier to follow.

// We set the keep alive to -1 to indicate that we don't need the pit id in the response.
// This is needed since we delete the pit prior to sending the response so the id doesn't exist anymore.
source.pointInTimeBuilder(new PointInTimeBuilder(resp.getPointInTimeId()).setKeepAlive(TimeValue.MINUS_ONE));
var pitListener = new SearchResponseActionListener(delegate) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I notice here that SearchResponseActionListener also collects SearchResponseMetrics. But if we convert this to just ActionListener this doesn't happen anymore? Is that intended?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good observation. Yet onResponse is entirely rewritten here, hence SearchReponseActionListener in this case does not do anything anyways. Using a plain ActionListener does not cause any change in behaviour. I added a test around this though that was missing: this is triggered e.g. when a compound retriever is used, which opens a PIT under the hood and performs a search against it (executed as an async action).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also moved up the shouldOpenPIT conditional branch, as it can quickly shortcut execution as opposed to creating the rewriteListener for nothing when a PIT needs to be opened. I think this improved readability, let me know.

@smalyshev
Copy link
Contributor

The approach looks fine to me but have some question about particular details.

})
);
return;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only change in this block is no longer using SearchResponseActionListener, which was not necessary (beyond my changes - added a test to verify that). This block can shortcut execution hence I moved it up.

Copy link
Contributor

@andreidan andreidan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this Luca.

The context comments helped the review ! 🚀

@@ -85,6 +90,29 @@ public void testSimpleQuery() {
assertEquals(searchResponse.getTook().millis(), measurements.getFirst().getLong());
}

public void testCompoundRetriever() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice !

@javanna javanna merged commit 1f4abac into elastic:main Sep 15, 2025
35 checks passed
@javanna javanna deleted the enhancement/search_response_action_listener_open_pit branch September 15, 2025 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>refactoring :Search Foundations/Search Catch all for Search Foundations Team:Search Foundations Meta label for the Search Foundations team in Elasticsearch v9.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants