Skip to content

Commit 79379d9

Browse files
committed
Create healthstats API for query insights
Signed-off-by: Chenyang Ji <cyji@amazon.com>
1 parent d74adb3 commit 79379d9

18 files changed

+965
-4
lines changed

src/main/java/org/opensearch/plugin/insights/QueryInsightsPlugin.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@
3030
import org.opensearch.env.NodeEnvironment;
3131
import org.opensearch.plugin.insights.core.listener.QueryInsightsListener;
3232
import org.opensearch.plugin.insights.core.service.QueryInsightsService;
33+
import org.opensearch.plugin.insights.rules.action.health_stats.HealthStatsAction;
3334
import org.opensearch.plugin.insights.rules.action.top_queries.TopQueriesAction;
35+
import org.opensearch.plugin.insights.rules.resthandler.health_stats.RestHealthStatsAction;
3436
import org.opensearch.plugin.insights.rules.resthandler.top_queries.RestTopQueriesAction;
37+
import org.opensearch.plugin.insights.rules.transport.health_stats.TransportHealthStatsAction;
3538
import org.opensearch.plugin.insights.rules.transport.top_queries.TransportTopQueriesAction;
3639
import org.opensearch.plugin.insights.settings.QueryCategorizationSettings;
3740
import org.opensearch.plugin.insights.settings.QueryInsightsSettings;
@@ -107,12 +110,15 @@ public List<RestHandler> getRestHandlers(
107110
final IndexNameExpressionResolver indexNameExpressionResolver,
108111
final Supplier<DiscoveryNodes> nodesInCluster
109112
) {
110-
return List.of(new RestTopQueriesAction());
113+
return List.of(new RestTopQueriesAction(), new RestHealthStatsAction());
111114
}
112115

113116
@Override
114117
public List<ActionHandler<? extends ActionRequest, ? extends ActionResponse>> getActions() {
115-
return List.of(new ActionPlugin.ActionHandler<>(TopQueriesAction.INSTANCE, TransportTopQueriesAction.class));
118+
return List.of(
119+
new ActionPlugin.ActionHandler<>(TopQueriesAction.INSTANCE, TransportTopQueriesAction.class),
120+
new ActionPlugin.ActionHandler<>(HealthStatsAction.INSTANCE, TransportHealthStatsAction.class)
121+
);
116122
}
117123

118124
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.plugin.insights.rules.action.health_stats;
10+
11+
import org.opensearch.action.ActionType;
12+
13+
/**
14+
* Transport action for cluster/node level query insights plugin health stats.
15+
*/
16+
public class HealthStatsAction extends ActionType<HealthStatsResponse> {
17+
18+
/**
19+
* The HealthStatsAction Instance.
20+
*/
21+
public static final HealthStatsAction INSTANCE = new HealthStatsAction();
22+
/**
23+
* The name of this Action
24+
*/
25+
public static final String NAME = "cluster:admin/opensearch/insights/health_stats";
26+
27+
private HealthStatsAction() {
28+
super(NAME, HealthStatsResponse::new);
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.plugin.insights.rules.action.health_stats;
10+
11+
import java.io.IOException;
12+
import org.opensearch.action.support.nodes.BaseNodeResponse;
13+
import org.opensearch.cluster.node.DiscoveryNode;
14+
import org.opensearch.core.common.io.stream.StreamInput;
15+
import org.opensearch.core.common.io.stream.StreamOutput;
16+
import org.opensearch.core.xcontent.ToXContentObject;
17+
import org.opensearch.core.xcontent.XContentBuilder;
18+
import org.opensearch.plugin.insights.rules.model.healthStats.QueryInsightsHealthStats;
19+
20+
/**
21+
* Holds the health stats retrieved from a node
22+
*/
23+
public class HealthStatsNodeResponse extends BaseNodeResponse implements ToXContentObject {
24+
/** The health stats retrieved from one node */
25+
private final QueryInsightsHealthStats healthStats;
26+
27+
/**
28+
* Create the HealthStatsNodeResponse Object from StreamInput
29+
* @param in A {@link StreamInput} object.
30+
* @throws IOException IOException
31+
*/
32+
public HealthStatsNodeResponse(final StreamInput in) throws IOException {
33+
super(in);
34+
healthStats = new QueryInsightsHealthStats(in);
35+
}
36+
37+
/**
38+
* Create the HealthStatsNodeResponse Object
39+
* @param node A node that is part of the cluster.
40+
* @param healthStats A list of HealthStats from nodes.
41+
*/
42+
public HealthStatsNodeResponse(final DiscoveryNode node, final QueryInsightsHealthStats healthStats) {
43+
super(node);
44+
this.healthStats = healthStats;
45+
}
46+
47+
@Override
48+
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
49+
builder.startObject(this.getNode().getId());
50+
healthStats.toXContent(builder, params);
51+
return builder.endObject();
52+
}
53+
54+
@Override
55+
public void writeTo(final StreamOutput out) throws IOException {
56+
super.writeTo(out);
57+
healthStats.writeTo(out);
58+
59+
}
60+
61+
/**
62+
* Get health stats
63+
*
64+
* @return the health stats records in this node response
65+
*/
66+
public QueryInsightsHealthStats getHealthStats() {
67+
return healthStats;
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.plugin.insights.rules.action.health_stats;
10+
11+
import java.io.IOException;
12+
import org.opensearch.action.support.nodes.BaseNodesRequest;
13+
import org.opensearch.core.common.io.stream.StreamInput;
14+
import org.opensearch.core.common.io.stream.StreamOutput;
15+
16+
/**
17+
* A request to get cluster/node level health stats information.
18+
*/
19+
public class HealthStatsRequest extends BaseNodesRequest<HealthStatsRequest> {
20+
/**
21+
* Constructor for HealthStatsRequest
22+
*
23+
* @param in A {@link StreamInput} object.
24+
* @throws IOException if the stream cannot be deserialized.
25+
*/
26+
public HealthStatsRequest(final StreamInput in) throws IOException {
27+
super(in);
28+
}
29+
30+
/**
31+
* Get health stats from nodes based on the nodes ids specified.
32+
* If none are passed, cluster level health stats will be returned.
33+
*
34+
* @param nodesIds the nodeIds specified in the request
35+
*/
36+
public HealthStatsRequest(final String... nodesIds) {
37+
super(nodesIds);
38+
}
39+
40+
@Override
41+
public void writeTo(final StreamOutput out) throws IOException {
42+
super.writeTo(out);
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.plugin.insights.rules.action.health_stats;
10+
11+
import java.io.IOException;
12+
import java.util.List;
13+
import org.opensearch.action.FailedNodeException;
14+
import org.opensearch.action.support.nodes.BaseNodesResponse;
15+
import org.opensearch.cluster.ClusterName;
16+
import org.opensearch.common.xcontent.XContentFactory;
17+
import org.opensearch.core.common.io.stream.StreamInput;
18+
import org.opensearch.core.common.io.stream.StreamOutput;
19+
import org.opensearch.core.xcontent.ToXContentFragment;
20+
import org.opensearch.core.xcontent.XContentBuilder;
21+
22+
/**
23+
* Transport response for cluster/node level health stats
24+
*/
25+
public class HealthStatsResponse extends BaseNodesResponse<HealthStatsNodeResponse> implements ToXContentFragment {
26+
/**
27+
* Constructor for HealthStatsNodeResponseResponse.
28+
*
29+
* @param in A {@link StreamInput} object.
30+
* @throws IOException if the stream cannot be deserialized.
31+
*/
32+
public HealthStatsResponse(final StreamInput in) throws IOException {
33+
super(in);
34+
}
35+
36+
/**
37+
* Constructor for HealthStatsResponse
38+
*
39+
* @param clusterName The current cluster name
40+
* @param nodes A list that contains health stats from all nodes
41+
* @param failures A list that contains FailedNodeException
42+
*/
43+
public HealthStatsResponse(
44+
final ClusterName clusterName,
45+
final List<HealthStatsNodeResponse> nodes,
46+
final List<FailedNodeException> failures
47+
) {
48+
super(clusterName, nodes, failures);
49+
}
50+
51+
@Override
52+
protected List<HealthStatsNodeResponse> readNodesFrom(final StreamInput in) throws IOException {
53+
return in.readList(HealthStatsNodeResponse::new);
54+
}
55+
56+
@Override
57+
protected void writeNodesTo(final StreamOutput out, final List<HealthStatsNodeResponse> nodes) throws IOException {
58+
out.writeList(nodes);
59+
}
60+
61+
@Override
62+
public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException {
63+
final List<HealthStatsNodeResponse> results = getNodes();
64+
builder.startObject();
65+
for (HealthStatsNodeResponse nodeResponse : results) {
66+
nodeResponse.toXContent(builder, params);
67+
}
68+
return builder.endObject();
69+
}
70+
71+
@Override
72+
public String toString() {
73+
try {
74+
final XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
75+
builder.startObject();
76+
this.toXContent(builder, EMPTY_PARAMS);
77+
builder.endObject();
78+
return builder.toString();
79+
} catch (IOException e) {
80+
return "{ \"error\" : \"" + e.getMessage() + "\"}";
81+
}
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
/**
10+
* Transport Actions, Requests and Responses for Query Insights Health Stats
11+
*/
12+
package org.opensearch.plugin.insights.rules.action.health_stats;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.plugin.insights.rules.resthandler.health_stats;
10+
11+
import static org.opensearch.plugin.insights.settings.QueryInsightsSettings.QUERY_INSIGHTS_HEALTH_STATS_URI;
12+
import static org.opensearch.rest.RestRequest.Method.GET;
13+
14+
import java.util.List;
15+
import java.util.Set;
16+
import org.opensearch.client.node.NodeClient;
17+
import org.opensearch.common.settings.Settings;
18+
import org.opensearch.core.common.Strings;
19+
import org.opensearch.core.rest.RestStatus;
20+
import org.opensearch.core.xcontent.ToXContent;
21+
import org.opensearch.plugin.insights.rules.action.health_stats.HealthStatsAction;
22+
import org.opensearch.plugin.insights.rules.action.health_stats.HealthStatsRequest;
23+
import org.opensearch.plugin.insights.rules.action.health_stats.HealthStatsResponse;
24+
import org.opensearch.rest.BaseRestHandler;
25+
import org.opensearch.rest.BytesRestResponse;
26+
import org.opensearch.rest.RestChannel;
27+
import org.opensearch.rest.RestRequest;
28+
import org.opensearch.rest.RestResponse;
29+
import org.opensearch.rest.action.RestResponseListener;
30+
31+
/**
32+
* Rest action to get operational health stats of the query insights plugin
33+
*/
34+
public class RestHealthStatsAction extends BaseRestHandler {
35+
/**
36+
* Constructor for RestHealthStatsAction
37+
*/
38+
public RestHealthStatsAction() {}
39+
40+
@Override
41+
public List<Route> routes() {
42+
return List.of(new Route(GET, QUERY_INSIGHTS_HEALTH_STATS_URI));
43+
}
44+
45+
@Override
46+
public String getName() {
47+
return "query_insights_health_stats_action";
48+
}
49+
50+
@Override
51+
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) {
52+
final HealthStatsRequest healthStatsRequest = prepareRequest(request);
53+
healthStatsRequest.timeout(request.param("timeout"));
54+
55+
return channel -> client.execute(HealthStatsAction.INSTANCE, healthStatsRequest, healthStatsResponse(channel));
56+
}
57+
58+
static HealthStatsRequest prepareRequest(final RestRequest request) {
59+
final String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodeId"));
60+
return new HealthStatsRequest(nodesIds);
61+
}
62+
63+
@Override
64+
protected Set<String> responseParams() {
65+
return Settings.FORMAT_PARAMS;
66+
}
67+
68+
@Override
69+
public boolean canTripCircuitBreaker() {
70+
return false;
71+
}
72+
73+
RestResponseListener<HealthStatsResponse> healthStatsResponse(final RestChannel channel) {
74+
return new RestResponseListener<>(channel) {
75+
@Override
76+
public RestResponse buildResponse(final HealthStatsResponse response) throws Exception {
77+
return new BytesRestResponse(RestStatus.OK, response.toXContent(channel.newBuilder(), ToXContent.EMPTY_PARAMS));
78+
}
79+
};
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
/**
10+
* Rest Handlers for Query Insights Health Stats
11+
*/
12+
package org.opensearch.plugin.insights.rules.resthandler.health_stats;

0 commit comments

Comments
 (0)