diff --git a/server/src/internalClusterTest/java/org/opensearch/action/admin/cluster/stats/ClusterStatsIT.java b/server/src/internalClusterTest/java/org/opensearch/action/admin/cluster/stats/ClusterStatsIT.java index 085a32593063a..b341b6dbdf7d1 100644 --- a/server/src/internalClusterTest/java/org/opensearch/action/admin/cluster/stats/ClusterStatsIT.java +++ b/server/src/internalClusterTest/java/org/opensearch/action/admin/cluster/stats/ClusterStatsIT.java @@ -288,7 +288,12 @@ public void testClusterStatusWhenStateNotRecovered() throws Exception { public void testFieldTypes() { internalCluster().startNode(); ensureGreen(); - ClusterStatsResponse response = client().admin().cluster().prepareClusterStats().get(); + ClusterStatsResponse response = client().admin() + .cluster() + .prepareClusterStats() + .includeAnalysisStats(true) + .includeMappingStats(true) + .get(); assertThat(response.getStatus(), Matchers.equalTo(ClusterHealthStatus.GREEN)); assertTrue(response.getIndicesStats().getMappings().getFieldTypeStats().isEmpty()); @@ -301,7 +306,7 @@ public void testFieldTypes() { + "\"eggplant\":{\"type\":\"integer\"}}}}}" ) .get(); - response = client().admin().cluster().prepareClusterStats().get(); + response = client().admin().cluster().prepareClusterStats().includeMappingStats(true).includeAnalysisStats(true).get(); assertThat(response.getIndicesStats().getMappings().getFieldTypeStats().size(), equalTo(3)); Set stats = response.getIndicesStats().getMappings().getFieldTypeStats(); for (IndexFeatureStats stat : stats) { diff --git a/server/src/main/java/org/opensearch/action/ActionModule.java b/server/src/main/java/org/opensearch/action/ActionModule.java index 16c15f553951c..b1a55d7a8280e 100644 --- a/server/src/main/java/org/opensearch/action/ActionModule.java +++ b/server/src/main/java/org/opensearch/action/ActionModule.java @@ -808,7 +808,7 @@ public void initRestHandlers(Supplier nodesInCluster) { registerHandler.accept(new RestNodesUsageAction()); registerHandler.accept(new RestNodesHotThreadsAction()); registerHandler.accept(new RestClusterAllocationExplainAction()); - registerHandler.accept(new RestClusterStatsAction()); + registerHandler.accept(new RestClusterStatsAction(settings, clusterSettings)); registerHandler.accept(new RestClusterStateAction(settingsFilter)); registerHandler.accept(new RestClusterHealthAction()); registerHandler.accept(new RestClusterUpdateSettingsAction()); diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequest.java b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequest.java index 6a99451c596ed..56f51bfb6be05 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequest.java @@ -47,10 +47,29 @@ @PublicApi(since = "1.0.0") public class ClusterStatsRequest extends BaseNodesRequest { + private boolean includeMappingStats; + private boolean includeAnalysisStats; + public ClusterStatsRequest(StreamInput in) throws IOException { super(in); } + public void setIncludeMappingStats(boolean bool) { + this.includeMappingStats = bool; + } + + public boolean isIncludeMappingStats() { + return includeMappingStats; + } + + public void setIncludeAnalysisStats(boolean bool) { + this.includeAnalysisStats = bool; + } + + public boolean isIncludeAnalysisStats() { + return includeAnalysisStats; + } + /** * Get stats from nodes based on the nodes ids specified. If none are passed, stats * based on all nodes will be returned. diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequestBuilder.java b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequestBuilder.java index 0dcb03dc26d0e..2d8bd216f965b 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequestBuilder.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsRequestBuilder.java @@ -50,4 +50,14 @@ public class ClusterStatsRequestBuilder extends NodesOperationRequestBuilder< public ClusterStatsRequestBuilder(OpenSearchClient client, ClusterStatsAction action) { super(client, action, new ClusterStatsRequest()); } + + public ClusterStatsRequestBuilder includeMappingStats(boolean value) { + request.setIncludeMappingStats(value); + return this; + } + + public ClusterStatsRequestBuilder includeAnalysisStats(boolean value) { + request.setIncludeAnalysisStats(value); + return this; + } } diff --git a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsResponse.java b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsResponse.java index cc002b689a2a5..cc2acea1a46a9 100644 --- a/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsResponse.java +++ b/server/src/main/java/org/opensearch/action/admin/cluster/stats/ClusterStatsResponse.java @@ -105,6 +105,35 @@ public ClusterStatsResponse( this.status = status; } + public ClusterStatsResponse( + long timestamp, + String clusterUUID, + ClusterName clusterName, + List nodes, + List failures, + ClusterState state, + ClusterStatsRequest request + ) { + super(clusterName, nodes, failures); + this.clusterUUID = clusterUUID; + this.timestamp = timestamp; + nodesStats = new ClusterStatsNodes(nodes); + indicesStats = new ClusterStatsIndices( + nodes, + request.isIncludeMappingStats() ? MappingStats.of(state) : null, + request.isIncludeAnalysisStats() ? AnalysisStats.of(state) : null + ); + ClusterHealthStatus status = null; + for (ClusterStatsNodeResponse response : nodes) { + // only the cluster-manager node populates the status + if (response.clusterStatus() != null) { + status = response.clusterStatus(); + break; + } + } + this.status = status; + } + public String getClusterUUID() { return this.clusterUUID; } 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 e4f483f796f44..1034b2690e0e5 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 @@ -129,7 +129,8 @@ protected ClusterStatsResponse newResponse( clusterService.getClusterName(), responses, failures, - state + state, + request ); } diff --git a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java index 335615a6affb7..f0e3c72abdf57 100644 --- a/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java +++ b/server/src/main/java/org/opensearch/common/settings/ClusterSettings.java @@ -149,6 +149,7 @@ import org.opensearch.ratelimitting.admissioncontrol.settings.IoBasedAdmissionControllerSettings; import org.opensearch.repositories.fs.FsRepository; import org.opensearch.rest.BaseRestHandler; +import org.opensearch.rest.action.admin.cluster.RestClusterStatsAction; import org.opensearch.script.ScriptService; import org.opensearch.search.SearchModule; import org.opensearch.search.SearchService; @@ -749,7 +750,9 @@ public void apply(Settings value, Settings current, Settings previous) { RemoteStoreSettings.CLUSTER_REMOTE_STORE_PATH_HASH_ALGORITHM_SETTING, RemoteStoreSettings.CLUSTER_REMOTE_MAX_TRANSLOG_READERS, RemoteStoreSettings.CLUSTER_REMOTE_STORE_TRANSLOG_METADATA, - SearchService.CLUSTER_ALLOW_DERIVED_FIELD_SETTING + SearchService.CLUSTER_ALLOW_DERIVED_FIELD_SETTING, + + RestClusterStatsAction.CLUSTER_STATS_LEVEL_SETTING ) ) ); diff --git a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterStatsAction.java b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterStatsAction.java index 0766e838210fa..62f4e47d73f50 100644 --- a/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterStatsAction.java +++ b/server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterStatsAction.java @@ -34,6 +34,9 @@ import org.opensearch.action.admin.cluster.stats.ClusterStatsRequest; import org.opensearch.client.node.NodeClient; +import org.opensearch.common.settings.ClusterSettings; +import org.opensearch.common.settings.Setting; +import org.opensearch.common.settings.Settings; import org.opensearch.rest.BaseRestHandler; import org.opensearch.rest.RestRequest; import org.opensearch.rest.action.RestActions.NodesResponseRestListener; @@ -52,6 +55,40 @@ */ public class RestClusterStatsAction extends BaseRestHandler { + /** + * Setting up the response in the form of levels - for experimental testings - + * level 1 excludes Mapping and Analysis Stats. + * + * This will determine the default behavior of the cluster stats call. + */ + public static final String CLUSTER_STATS_RESPONSE_LEVEL = "opensearch.experimental.optimization.cluster_stats.response_level"; + + public static final Setting CLUSTER_STATS_LEVEL_SETTING = Setting.intSetting( + CLUSTER_STATS_RESPONSE_LEVEL, + 2, + 1, + Setting.Property.NodeScope, + Setting.Property.Dynamic + ); + + public volatile boolean defaultMappingAndAnalysisStats; + + public RestClusterStatsAction(Settings settings, ClusterSettings clusterSettings) { + updateMappingAndAnalysisStatsFromLevel(CLUSTER_STATS_LEVEL_SETTING.get(settings)); + clusterSettings.addSettingsUpdateConsumer(CLUSTER_STATS_LEVEL_SETTING, this::updateMappingAndAnalysisStatsFromLevel); + } + + private void updateMappingAndAnalysisStatsFromLevel(int level) { + switch (level) { + case 1: + this.defaultMappingAndAnalysisStats = false; + break; + case 2: + this.defaultMappingAndAnalysisStats = true; + break; + } + } + @Override public List routes() { return unmodifiableList(asList(new Route(GET, "/_cluster/stats"), new Route(GET, "/_cluster/stats/nodes/{nodeId}"))); @@ -66,6 +103,10 @@ public String getName() { public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterStatsRequest clusterStatsRequest = new ClusterStatsRequest().nodesIds(request.paramAsStringArray("nodeId", null)); clusterStatsRequest.timeout(request.param("timeout")); + + clusterStatsRequest.setIncludeMappingStats(request.paramAsBoolean("include_mapping_stats", defaultMappingAndAnalysisStats)); + clusterStatsRequest.setIncludeAnalysisStats(request.paramAsBoolean("include_analysis_stats", defaultMappingAndAnalysisStats)); + return channel -> client.admin().cluster().clusterStats(clusterStatsRequest, new NodesResponseRestListener<>(channel)); }