diff --git a/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/bulk/RestNoopBulkAction.java b/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/bulk/RestNoopBulkAction.java index d8a5e4fa0ea47..6673e49d61007 100644 --- a/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/bulk/RestNoopBulkAction.java +++ b/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/bulk/RestNoopBulkAction.java @@ -57,6 +57,11 @@ public RestNoopBulkAction(Settings settings, RestController controller) { controller.registerHandler(PUT, "/{index}/{type}/_noop_bulk", this); } + @Override + public String getName() { + return "noop_bulk_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { BulkRequest bulkRequest = Requests.bulkRequest(); diff --git a/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/search/RestNoopSearchAction.java b/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/search/RestNoopSearchAction.java index 48a453c372507..39c9510b8a231 100644 --- a/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/search/RestNoopSearchAction.java +++ b/client/client-benchmark-noop-api-plugin/src/main/java/org/elasticsearch/plugin/noop/action/search/RestNoopSearchAction.java @@ -42,6 +42,11 @@ public RestNoopSearchAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_noop_search", this); } + @Override + public String getName() { + return "noop_search_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { SearchRequest searchRequest = new SearchRequest(); diff --git a/core/src/main/java/org/elasticsearch/action/ActionModule.java b/core/src/main/java/org/elasticsearch/action/ActionModule.java index d52175c9eb4e5..618b97fbac2d9 100644 --- a/core/src/main/java/org/elasticsearch/action/ActionModule.java +++ b/core/src/main/java/org/elasticsearch/action/ActionModule.java @@ -37,6 +37,8 @@ import org.elasticsearch.action.admin.cluster.node.tasks.get.TransportGetTaskAction; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksAction; import org.elasticsearch.action.admin.cluster.node.tasks.list.TransportListTasksAction; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageAction; +import org.elasticsearch.action.admin.cluster.node.usage.TransportNodesUsageAction; import org.elasticsearch.action.admin.cluster.remote.RemoteInfoAction; import org.elasticsearch.action.admin.cluster.remote.TransportRemoteInfoAction; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryAction; @@ -234,6 +236,7 @@ import org.elasticsearch.rest.action.admin.cluster.RestNodesHotThreadsAction; import org.elasticsearch.rest.action.admin.cluster.RestNodesInfoAction; import org.elasticsearch.rest.action.admin.cluster.RestNodesStatsAction; +import org.elasticsearch.rest.action.admin.cluster.RestNodesUsageAction; import org.elasticsearch.rest.action.admin.cluster.RestPendingClusterTasksAction; import org.elasticsearch.rest.action.admin.cluster.RestPutRepositoryAction; import org.elasticsearch.rest.action.admin.cluster.RestPutStoredScriptAction; @@ -310,6 +313,7 @@ import org.elasticsearch.rest.action.search.RestSearchAction; import org.elasticsearch.rest.action.search.RestSearchScrollAction; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.usage.UsageService; import java.util.ArrayList; import java.util.List; @@ -346,7 +350,7 @@ public class ActionModule extends AbstractModule { public ActionModule(boolean transportClient, Settings settings, IndexNameExpressionResolver indexNameExpressionResolver, IndexScopedSettings indexScopedSettings, ClusterSettings clusterSettings, SettingsFilter settingsFilter, ThreadPool threadPool, List actionPlugins, NodeClient nodeClient, - CircuitBreakerService circuitBreakerService) { + CircuitBreakerService circuitBreakerService, UsageService usageService) { this.transportClient = transportClient; this.settings = settings; this.indexNameExpressionResolver = indexNameExpressionResolver; @@ -373,7 +377,7 @@ public ActionModule(boolean transportClient, Settings settings, IndexNameExpress if (transportClient) { restController = null; } else { - restController = new RestController(settings, headers, restWrapper, nodeClient, circuitBreakerService); + restController = new RestController(settings, headers, restWrapper, nodeClient, circuitBreakerService, usageService); } } @@ -405,6 +409,7 @@ public void reg actions.register(NodesInfoAction.INSTANCE, TransportNodesInfoAction.class); actions.register(RemoteInfoAction.INSTANCE, TransportRemoteInfoAction.class); actions.register(NodesStatsAction.INSTANCE, TransportNodesStatsAction.class); + actions.register(NodesUsageAction.INSTANCE, TransportNodesUsageAction.class); actions.register(NodesHotThreadsAction.INSTANCE, TransportNodesHotThreadsAction.class); actions.register(ListTasksAction.INSTANCE, TransportListTasksAction.class); actions.register(GetTaskAction.INSTANCE, TransportGetTaskAction.class); @@ -515,6 +520,7 @@ public void initRestHandlers(Supplier nodesInCluster) { registerHandler.accept(new RestNodesInfoAction(settings, restController, settingsFilter)); registerHandler.accept(new RestRemoteClusterInfoAction(settings, restController)); registerHandler.accept(new RestNodesStatsAction(settings, restController)); + registerHandler.accept(new RestNodesUsageAction(settings, restController)); registerHandler.accept(new RestNodesHotThreadsAction(settings, restController)); registerHandler.accept(new RestClusterAllocationExplainAction(settings, restController)); registerHandler.accept(new RestClusterStatsAction(settings, restController)); diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodeUsage.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodeUsage.java new file mode 100644 index 0000000000000..954e64e8caf33 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodeUsage.java @@ -0,0 +1,115 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.support.nodes.BaseNodeResponse; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Map; + +public class NodeUsage extends BaseNodeResponse implements ToXContent { + + private long timestamp; + private long sinceTime; + private Map restUsage; + + NodeUsage() { + } + + public static NodeUsage readNodeStats(StreamInput in) throws IOException { + NodeUsage nodeInfo = new NodeUsage(); + nodeInfo.readFrom(in); + return nodeInfo; + } + + /** + * @param node + * the node these statistics were collected from + * @param timestamp + * the timestamp for when these statistics were collected + * @param sinceTime + * the timestamp for when the collection of these statistics + * started + * @param restUsage + * a map containing the counts of the number of times each REST + * endpoint has been called + */ + public NodeUsage(DiscoveryNode node, long timestamp, long sinceTime, Map restUsage) { + super(node); + this.timestamp = timestamp; + this.sinceTime = sinceTime; + this.restUsage = restUsage; + } + + /** + * @return the timestamp for when these statistics were collected + */ + public long getTimestamp() { + return timestamp; + } + + /** + * @return the timestamp for when the collection of these statistics started + */ + public long getSinceTime() { + return sinceTime; + } + + /** + * @return a map containing the counts of the number of times each REST + * endpoint has been called + */ + public Map getRestUsage() { + return restUsage; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("since", sinceTime); + if (restUsage != null) { + builder.field("rest_actions"); + builder.map(restUsage); + } + return builder; + } + + @SuppressWarnings("unchecked") + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + timestamp = in.readLong(); + sinceTime = in.readLong(); + restUsage = (Map) in.readGenericValue(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeLong(timestamp); + out.writeLong(sinceTime); + out.writeGenericValue(restUsage); + } + +} diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageAction.java new file mode 100644 index 0000000000000..358659e5f61f7 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageAction.java @@ -0,0 +1,44 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.Action; +import org.elasticsearch.client.ElasticsearchClient; + +public class NodesUsageAction extends Action { + + public static final NodesUsageAction INSTANCE = new NodesUsageAction(); + public static final String NAME = "cluster:monitor/nodes/usage"; + + protected NodesUsageAction() { + super(NAME); + } + + @Override + public NodesUsageRequestBuilder newRequestBuilder(ElasticsearchClient client) { + return new NodesUsageRequestBuilder(client, this); + } + + @Override + public NodesUsageResponse newResponse() { + return new NodesUsageResponse(); + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequest.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequest.java new file mode 100644 index 0000000000000..c4e80494aed5c --- /dev/null +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequest.java @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.support.nodes.BaseNodesRequest; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; + +public class NodesUsageRequest extends BaseNodesRequest { + + private boolean restActions; + + public NodesUsageRequest() { + super(); + } + + /** + * Get usage from nodes based on the nodes ids specified. If none are + * passed, usage for all nodes will be returned. + */ + public NodesUsageRequest(String... nodesIds) { + super(nodesIds); + } + + /** + * Sets all the request flags. + */ + public NodesUsageRequest all() { + this.restActions = true; + return this; + } + + /** + * Clears all the request flags. + */ + public NodesUsageRequest clear() { + this.restActions = false; + return this; + } + + /** + * Should the node rest actions usage statistics be returned. + */ + public boolean restActions() { + return this.restActions; + } + + /** + * Should the node rest actions usage statistics be returned. + */ + public NodesUsageRequest restActions(boolean restActions) { + this.restActions = restActions; + return this; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + this.restActions = in.readBoolean(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeBoolean(restActions); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/index/reindex/package-info.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequestBuilder.java similarity index 56% rename from core/src/main/java/org/elasticsearch/index/reindex/package-info.java rename to core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequestBuilder.java index 00cb5106770d1..76d14556b9c4a 100644 --- a/core/src/main/java/org/elasticsearch/index/reindex/package-info.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageRequestBuilder.java @@ -17,8 +17,18 @@ * under the License. */ -/** - * Infrastructure for actions that modify documents based on the results of a scrolling query - * like reindex, update by query or delete by query. - */ -package org.elasticsearch.index.reindex; +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.Action; +import org.elasticsearch.action.support.nodes.NodesOperationRequestBuilder; +import org.elasticsearch.client.ElasticsearchClient; + +public class NodesUsageRequestBuilder + extends NodesOperationRequestBuilder { + + public NodesUsageRequestBuilder(ElasticsearchClient client, + Action action) { + super(client, action, new NodesUsageRequest()); + } + +} diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageResponse.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageResponse.java new file mode 100644 index 0000000000000..ff88145021c73 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/NodesUsageResponse.java @@ -0,0 +1,85 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.FailedNodeException; +import org.elasticsearch.action.support.nodes.BaseNodesResponse; +import org.elasticsearch.cluster.ClusterName; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; + +import java.io.IOException; +import java.util.List; + +/** + * The response for the nodes usage api which contains the individual usage + * statistics for all nodes queried. + */ +public class NodesUsageResponse extends BaseNodesResponse implements ToXContent { + + NodesUsageResponse() { + } + + public NodesUsageResponse(ClusterName clusterName, List nodes, List failures) { + super(clusterName, nodes, failures); + } + + @Override + protected List readNodesFrom(StreamInput in) throws IOException { + return in.readList(NodeUsage::readNodeStats); + } + + @Override + protected void writeNodesTo(StreamOutput out, List nodes) throws IOException { + out.writeStreamableList(nodes); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject("nodes"); + for (NodeUsage nodeUsage : getNodes()) { + builder.startObject(nodeUsage.getNode().getId()); + builder.field("timestamp", nodeUsage.getTimestamp()); + nodeUsage.toXContent(builder, params); + + builder.endObject(); + } + builder.endObject(); + + return builder; + } + + @Override + public String toString() { + try { + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + toXContent(builder, EMPTY_PARAMS); + builder.endObject(); + return builder.string(); + } catch (IOException e) { + return "{ \"error\" : \"" + e.getMessage() + "\"}"; + } + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/TransportNodesUsageAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/TransportNodesUsageAction.java new file mode 100644 index 0000000000000..25483d84807d8 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/usage/TransportNodesUsageAction.java @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.action.admin.cluster.node.usage; + +import org.elasticsearch.action.FailedNodeException; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.nodes.BaseNodeRequest; +import org.elasticsearch.action.support.nodes.TransportNodesAction; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; +import org.elasticsearch.usage.UsageService; + +import java.io.IOException; +import java.util.List; + +public class TransportNodesUsageAction + extends TransportNodesAction { + + private UsageService usageService; + + @Inject + public TransportNodesUsageAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, + TransportService transportService, ActionFilters actionFilters, + IndexNameExpressionResolver indexNameExpressionResolver, UsageService usageService) { + super(settings, NodesUsageAction.NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, + NodesUsageRequest::new, NodeUsageRequest::new, ThreadPool.Names.MANAGEMENT, NodeUsage.class); + this.usageService = usageService; + } + + @Override + protected NodesUsageResponse newResponse(NodesUsageRequest request, List responses, List failures) { + return new NodesUsageResponse(clusterService.getClusterName(), responses, failures); + } + + @Override + protected NodeUsageRequest newNodeRequest(String nodeId, NodesUsageRequest request) { + return new NodeUsageRequest(nodeId, request); + } + + @Override + protected NodeUsage newNodeResponse() { + return new NodeUsage(); + } + + @Override + protected NodeUsage nodeOperation(NodeUsageRequest nodeUsageRequest) { + NodesUsageRequest request = nodeUsageRequest.request; + return usageService.getUsageStats(clusterService.localNode(), request.restActions()); + } + + @Override + protected boolean accumulateExceptions() { + return false; + } + + public static class NodeUsageRequest extends BaseNodeRequest { + + NodesUsageRequest request; + + public NodeUsageRequest() { + } + + NodeUsageRequest(String nodeId, NodesUsageRequest request) { + super(nodeId); + this.request = request; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + request = new NodesUsageRequest(); + request.readFrom(in); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + request.writeTo(out); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/client/ClusterAdminClient.java b/core/src/main/java/org/elasticsearch/client/ClusterAdminClient.java index de8205211dd21..942d9e50560e2 100644 --- a/core/src/main/java/org/elasticsearch/client/ClusterAdminClient.java +++ b/core/src/main/java/org/elasticsearch/client/ClusterAdminClient.java @@ -45,6 +45,9 @@ import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequestBuilder; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequest; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequestBuilder; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageResponse; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequestBuilder; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryResponse; @@ -265,8 +268,37 @@ public interface ClusterAdminClient extends ElasticsearchClient { NodesStatsRequestBuilder prepareNodesStats(String... nodesIds); /** - * Returns top N hot-threads samples per node. The hot-threads are only sampled - * for the node ids specified in the request. + * Returns top N hot-threads samples per node. The hot-threads are only + * sampled for the node ids specified in the request. Nodes usage of the + * cluster. + * + * @param request + * The nodes usage request + * @return The result future + * @see org.elasticsearch.client.Requests#nodesUsageRequest(String...) + */ + ActionFuture nodesUsage(NodesUsageRequest request); + + /** + * Nodes usage of the cluster. + * + * @param request + * The nodes usage request + * @param listener + * A listener to be notified with a result + * @see org.elasticsearch.client.Requests#nodesUsageRequest(String...) + */ + void nodesUsage(NodesUsageRequest request, ActionListener listener); + + /** + * Nodes usage of the cluster. + */ + NodesUsageRequestBuilder prepareNodesUsage(String... nodesIds); + + /** + * Returns top N hot-threads samples per node. The hot-threads are only + * sampled for the node ids specified in the request. + * */ ActionFuture nodesHotThreads(NodesHotThreadsRequest request); diff --git a/core/src/main/java/org/elasticsearch/client/Requests.java b/core/src/main/java/org/elasticsearch/client/Requests.java index 6d652bf39d0a9..74f83452e51ab 100644 --- a/core/src/main/java/org/elasticsearch/client/Requests.java +++ b/core/src/main/java/org/elasticsearch/client/Requests.java @@ -25,6 +25,7 @@ import org.elasticsearch.action.admin.cluster.node.tasks.cancel.CancelTasksRequest; import org.elasticsearch.action.admin.cluster.node.tasks.get.GetTaskRequest; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequest; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest; import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest; @@ -387,6 +388,19 @@ public static NodesStatsRequest nodesStatsRequest(String... nodesIds) { return new NodesStatsRequest(nodesIds); } + /** + * Creates a nodes usage request against one or more nodes. Pass + * null or an empty array for all nodes. + * + * @param nodesIds + * The nodes ids to get the usage for + * @return The nodes usage request + * @see org.elasticsearch.client.ClusterAdminClient#nodesUsage(org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequest) + */ + public static NodesUsageRequest nodesUsageRequest(String... nodesIds) { + return new NodesUsageRequest(nodesIds); + } + /** * Creates a cluster stats request. * diff --git a/core/src/main/java/org/elasticsearch/client/support/AbstractClient.java b/core/src/main/java/org/elasticsearch/client/support/AbstractClient.java index 726875a6d5c20..e350727e425f9 100644 --- a/core/src/main/java/org/elasticsearch/client/support/AbstractClient.java +++ b/core/src/main/java/org/elasticsearch/client/support/AbstractClient.java @@ -57,6 +57,10 @@ import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequestBuilder; import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksResponse; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageAction; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequest; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequestBuilder; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageResponse; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryAction; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequest; import org.elasticsearch.action.admin.cluster.repositories.delete.DeleteRepositoryRequestBuilder; @@ -828,6 +832,21 @@ public NodesStatsRequestBuilder prepareNodesStats(String... nodesIds) { return new NodesStatsRequestBuilder(this, NodesStatsAction.INSTANCE).setNodesIds(nodesIds); } + @Override + public ActionFuture nodesUsage(final NodesUsageRequest request) { + return execute(NodesUsageAction.INSTANCE, request); + } + + @Override + public void nodesUsage(final NodesUsageRequest request, final ActionListener listener) { + execute(NodesUsageAction.INSTANCE, request, listener); + } + + @Override + public NodesUsageRequestBuilder prepareNodesUsage(String... nodesIds) { + return new NodesUsageRequestBuilder(this, NodesUsageAction.INSTANCE).setNodesIds(nodesIds); + } + @Override public ActionFuture clusterStats(ClusterStatsRequest request) { return execute(ClusterStatsAction.INSTANCE, request); diff --git a/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java b/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java index 4942edfc6448f..5879f1e3579b0 100644 --- a/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java +++ b/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java @@ -45,8 +45,8 @@ import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.indices.breaker.CircuitBreakerService; -import org.elasticsearch.node.Node; import org.elasticsearch.node.InternalSettingsPreparer; +import org.elasticsearch.node.Node; import org.elasticsearch.plugins.ActionPlugin; import org.elasticsearch.plugins.NetworkPlugin; import org.elasticsearch.plugins.Plugin; @@ -159,7 +159,7 @@ private static ClientTemplate buildTemplate(Settings providedSettings, Settings modules.add(b -> b.bind(ThreadPool.class).toInstance(threadPool)); ActionModule actionModule = new ActionModule(true, settings, null, settingsModule.getIndexScopedSettings(), settingsModule.getClusterSettings(), settingsModule.getSettingsFilter(), threadPool, - pluginsService.filterPlugins(ActionPlugin.class), null, null); + pluginsService.filterPlugins(ActionPlugin.class), null, null, null); modules.add(actionModule); CircuitBreakerService circuitBreakerService = Node.createCircuitBreakerService(settingsModule.getSettings(), diff --git a/core/src/main/java/org/elasticsearch/node/Node.java b/core/src/main/java/org/elasticsearch/node/Node.java index dd50b0526ee4f..13c829844e197 100644 --- a/core/src/main/java/org/elasticsearch/node/Node.java +++ b/core/src/main/java/org/elasticsearch/node/Node.java @@ -132,6 +132,7 @@ import org.elasticsearch.transport.TransportInterceptor; import org.elasticsearch.transport.TransportService; import org.elasticsearch.tribe.TribeService; +import org.elasticsearch.usage.UsageService; import org.elasticsearch.watcher.ResourceWatcherService; import java.io.BufferedWriter; @@ -340,6 +341,7 @@ protected Node(final Environment environment, Collection final IngestService ingestService = new IngestService(clusterService.getClusterSettings(), settings, threadPool, this.environment, scriptModule.getScriptService(), analysisModule.getAnalysisRegistry(), pluginsService.filterPlugins(IngestPlugin.class)); final ClusterInfoService clusterInfoService = newClusterInfoService(settings, clusterService, threadPool, client); + final UsageService usageService = new UsageService(settings); ModulesBuilder modules = new ModulesBuilder(); // plugin modules must be added here, before others or we can get crazy injection errors... @@ -360,7 +362,7 @@ protected Node(final Environment environment, Collection resourcesToClose.add(circuitBreakerService); ActionModule actionModule = new ActionModule(false, settings, clusterModule.getIndexNameExpressionResolver(), settingsModule.getIndexScopedSettings(), settingsModule.getClusterSettings(), settingsModule.getSettingsFilter(), - threadPool, pluginsService.filterPlugins(ActionPlugin.class), client, circuitBreakerService); + threadPool, pluginsService.filterPlugins(ActionPlugin.class), client, circuitBreakerService, usageService); modules.add(actionModule); modules.add(new GatewayModule()); @@ -455,6 +457,7 @@ protected Node(final Environment environment, Collection b.bind(ScriptService.class).toInstance(scriptModule.getScriptService()); b.bind(AnalysisRegistry.class).toInstance(analysisModule.getAnalysisRegistry()); b.bind(IngestService.class).toInstance(ingestService); + b.bind(UsageService.class).toInstance(usageService); b.bind(NamedWriteableRegistry.class).toInstance(namedWriteableRegistry); b.bind(MetaDataUpgrader.class).toInstance(metaDataUpgrader); b.bind(MetaStateService.class).toInstance(metaStateService); diff --git a/core/src/main/java/org/elasticsearch/rest/BaseRestHandler.java b/core/src/main/java/org/elasticsearch/rest/BaseRestHandler.java index 3db635b044ca5..585713b641f5e 100644 --- a/core/src/main/java/org/elasticsearch/rest/BaseRestHandler.java +++ b/core/src/main/java/org/elasticsearch/rest/BaseRestHandler.java @@ -29,6 +29,7 @@ import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.ActionPlugin; +import org.elasticsearch.rest.action.admin.cluster.RestNodesUsageAction; import java.io.IOException; import java.util.ArrayList; @@ -39,6 +40,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.atomic.LongAdder; import java.util.stream.Collectors; /** @@ -54,10 +56,24 @@ public abstract class BaseRestHandler extends AbstractComponent implements RestH public static final Setting MULTI_ALLOW_EXPLICIT_INDEX = Setting.boolSetting("rest.action.multi.allow_explicit_index", true, Property.NodeScope); + private final LongAdder usageCount = new LongAdder(); + protected BaseRestHandler(Settings settings) { super(settings); } + public final long getUsageCount() { + return usageCount.sum(); + } + + /** + * @return the name of this handler. The name should be human readable and + * should describe the action that will performed when this API is + * called. This name is used in the response to the + * {@link RestNodesUsageAction}. + */ + public abstract String getName(); + @Override public final void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception { // prepare the request for execution; has the side effect of touching the request parameters @@ -76,6 +92,7 @@ public final void handleRequest(RestRequest request, RestChannel channel, NodeCl throw new IllegalArgumentException(unrecognized(request, unconsumedParams, candidateParams, "parameter")); } + usageCount.increment(); // execute the action action.accept(channel); } diff --git a/core/src/main/java/org/elasticsearch/rest/RestController.java b/core/src/main/java/org/elasticsearch/rest/RestController.java index a3d8a4b7db5f2..addc6bec51ca1 100644 --- a/core/src/main/java/org/elasticsearch/rest/RestController.java +++ b/core/src/main/java/org/elasticsearch/rest/RestController.java @@ -37,6 +37,7 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.indices.breaker.CircuitBreakerService; +import org.elasticsearch.usage.UsageService; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -72,11 +73,13 @@ public class RestController extends AbstractComponent implements HttpServerTrans /** Rest headers that are copied to internal requests made during a rest request. */ private final Set headersToCopy; + private UsageService usageService; public RestController(Settings settings, Set headersToCopy, UnaryOperator handlerWrapper, - NodeClient client, CircuitBreakerService circuitBreakerService) { + NodeClient client, CircuitBreakerService circuitBreakerService, UsageService usageService) { super(settings); this.headersToCopy = headersToCopy; + this.usageService = usageService; if (handlerWrapper == null) { handlerWrapper = h -> h; // passthrough if no wrapper set } @@ -148,6 +151,9 @@ public void registerHandler(RestRequest.Method method, String path, RestHandler PathTrie handlers = getHandlersForMethod(method); if (handlers != null) { handlers.insert(path, handler); + if (handler instanceof BaseRestHandler) { + usageService.addRestHandler((BaseRestHandler) handler); + } } else { throw new IllegalArgumentException("Can't handle [" + method + "] for path [" + path + "]"); } diff --git a/core/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java b/core/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java index e983bdc182a01..470f98a1e639a 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java @@ -38,7 +38,6 @@ import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; -import static org.elasticsearch.rest.RestStatus.NOT_FOUND; import static org.elasticsearch.rest.RestStatus.OK; public class RestFieldCapabilitiesAction extends BaseRestHandler { @@ -50,6 +49,11 @@ public RestFieldCapabilitiesAction(Settings settings, RestController controller) controller.registerHandler(POST, "/{index}/_field_caps", this); } + @Override + public String getName() { + return "field_capabilities_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/RestFieldStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/RestFieldStatsAction.java index 34e7b636aeb09..e087a5fb5eda9 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/RestFieldStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/RestFieldStatsAction.java @@ -60,6 +60,11 @@ static String deprecationMessage() { "run a min/max aggregations on the desired fields."; } + @Override + public String getName() { + return "field_stats_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java b/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java index 006b6d71db4f3..c155b76cb810f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/RestMainAction.java @@ -44,6 +44,11 @@ public RestMainAction(Settings settings, RestController controller) { controller.registerHandler(HEAD, "/", this); } + @Override + public String getName() { + return "main_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { return channel -> client.execute(MainAction.INSTANCE, new MainRequest(), new RestBuilderListener(channel) { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCancelTasksAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCancelTasksAction.java index 28631501b7fd2..bd94e7351ebf5 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCancelTasksAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCancelTasksAction.java @@ -46,6 +46,11 @@ public RestCancelTasksAction(Settings settings, RestController controller, Suppl controller.registerHandler(POST, "/_tasks/{task_id}/_cancel", this); } + @Override + public String getName() { + return "cancel_tasks_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodes")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterAllocationExplainAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterAllocationExplainAction.java index 8855e65f976aa..504c8f365d70a 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterAllocationExplainAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterAllocationExplainAction.java @@ -46,6 +46,11 @@ public RestClusterAllocationExplainAction(Settings settings, RestController cont controller.registerHandler(RestRequest.Method.POST, "/_cluster/allocation/explain", this); } + @Override + public String getName() { + return "cluster_allocation_explain_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterAllocationExplainRequest req; diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java index 5c3be8f4347f2..f9716d8d1bade 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterGetSettingsAction.java @@ -53,6 +53,11 @@ public RestClusterGetSettingsAction(Settings settings, RestController controller this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "cluster_get_settings_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterStateRequest clusterStateRequest = Requests.clusterStateRequest() diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterHealthAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterHealthAction.java index d8dd34d4a2897..f3dd274e040e6 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterHealthAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterHealthAction.java @@ -46,6 +46,11 @@ public RestClusterHealthAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.GET, "/_cluster/health/{index}", this); } + @Override + public String getName() { + return "cluster_health_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterHealthRequest clusterHealthRequest = clusterHealthRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java index 08ed23c7fb448..1eafe29cfe7fb 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterRerouteAction.java @@ -63,6 +63,11 @@ public RestClusterRerouteAction(Settings settings, RestController controller, Se controller.registerHandler(RestRequest.Method.POST, "/_cluster/reroute", this); } + @Override + public String getName() { + return "cluster_reroute_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterRerouteRequest clusterRerouteRequest = createRequest(request); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterSearchShardsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterSearchShardsAction.java index 90673dccd680a..e761e8480236e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterSearchShardsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterSearchShardsAction.java @@ -44,6 +44,11 @@ public RestClusterSearchShardsAction(Settings settings, RestController controlle controller.registerHandler(POST, "/{index}/_search_shards", this); } + @Override + public String getName() { + return "cluster_search_shards_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStateAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStateAction.java index c25b612d78e4e..5e3743637178e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStateAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStateAction.java @@ -56,6 +56,11 @@ public RestClusterStateAction(Settings settings, RestController controller, Sett this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "cluster_state_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final ClusterStateRequest clusterStateRequest = Requests.clusterStateRequest(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStatsAction.java index e58cf72ffca20..830fc3041f910 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterStatsAction.java @@ -36,6 +36,11 @@ public RestClusterStatsAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.GET, "/_cluster/stats/nodes/{nodeId}", this); } + @Override + public String getName() { + return "cluster_stats_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClusterStatsRequest clusterStatsRequest = new ClusterStatsRequest().nodesIds(request.paramAsStringArray("nodeId", null)); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterUpdateSettingsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterUpdateSettingsAction.java index 02b62b8e4bf9e..88e8ada55976d 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterUpdateSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestClusterUpdateSettingsAction.java @@ -41,6 +41,11 @@ public RestClusterUpdateSettingsAction(Settings settings, RestController control controller.registerHandler(RestRequest.Method.PUT, "/_cluster/settings", this); } + @Override + public String getName() { + return "cluster_update_settings_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final ClusterUpdateSettingsRequest clusterUpdateSettingsRequest = Requests.clusterUpdateSettingsRequest(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCreateSnapshotAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCreateSnapshotAction.java index bd0d7e2a9d73f..bf2866b57713e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCreateSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestCreateSnapshotAction.java @@ -43,6 +43,11 @@ public RestCreateSnapshotAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_snapshot/{repository}/{snapshot}", this); } + @Override + public String getName() { + return "create_snapshot_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { CreateSnapshotRequest createSnapshotRequest = createSnapshotRequest(request.param("repository"), request.param("snapshot")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteRepositoryAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteRepositoryAction.java index 2019e04be5597..33455365dcccc 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteRepositoryAction.java @@ -41,6 +41,11 @@ public RestDeleteRepositoryAction(Settings settings, RestController controller) controller.registerHandler(DELETE, "/_snapshot/{repository}", this); } + @Override + public String getName() { + return "delete_repository_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { DeleteRepositoryRequest deleteRepositoryRequest = deleteRepositoryRequest(request.param("repository")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteSnapshotAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteSnapshotAction.java index a11d47278a8e8..fbd8822a84ea4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteSnapshotAction.java @@ -41,6 +41,11 @@ public RestDeleteSnapshotAction(Settings settings, RestController controller) { controller.registerHandler(DELETE, "/_snapshot/{repository}/{snapshot}", this); } + @Override + public String getName() { + return "delete_snapshot_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { DeleteSnapshotRequest deleteSnapshotRequest = deleteSnapshotRequest(request.param("repository"), request.param("snapshot")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteStoredScriptAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteStoredScriptAction.java index 102ae6bd571a2..8aadba3adf43c 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteStoredScriptAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestDeleteStoredScriptAction.java @@ -42,6 +42,11 @@ public RestDeleteStoredScriptAction(Settings settings, RestController controller controller.registerHandler(DELETE, "/_scripts/{lang}/{id}", this); } + @Override + public String getName() { + return "delete_stored_script_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String id = request.param("id"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetRepositoriesAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetRepositoriesAction.java index 1af138400e310..ed6fe2f95f4fb 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetRepositoriesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetRepositoriesAction.java @@ -56,6 +56,11 @@ public RestGetRepositoriesAction(Settings settings, RestController controller, S this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "get_respositories_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] repositories = request.paramAsStringArray("repository", Strings.EMPTY_ARRAY); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetSnapshotsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetSnapshotsAction.java index 7348cb5896cb4..f42180b5029b8 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetSnapshotsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetSnapshotsAction.java @@ -42,6 +42,11 @@ public RestGetSnapshotsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_snapshot/{repository}/{snapshot}", this); } + @Override + public String getName() { + return "get_snapshots_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String repository = request.param("repository"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java index 0c3857ffb58ed..c0ea3c6ff8bdd 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetStoredScriptAction.java @@ -53,6 +53,11 @@ public RestGetStoredScriptAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_scripts/{lang}/{id}", this); } + @Override + public String getName() { + return "get_stored_scripts_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, NodeClient client) throws IOException { String id; diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetTaskAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetTaskAction.java index e013970553fd3..8ff823ea9e433 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetTaskAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestGetTaskAction.java @@ -39,6 +39,11 @@ public RestGetTaskAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_tasks/{taskId}", this); } + @Override + public String getName() { + return "get_task_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { TaskId taskId = new TaskId(request.param("taskId")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestListTasksAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestListTasksAction.java index 4177386eff996..6ef5d5a2de2bf 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestListTasksAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestListTasksAction.java @@ -55,6 +55,11 @@ public RestListTasksAction(Settings settings, RestController controller, Supplie controller.registerHandler(GET, "/_tasks", this); } + @Override + public String getName() { + return "list_tasks_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final ListTasksRequest listTasksRequest = generateListTasksRequest(request); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java index 48ad588688d60..be163d0431a03 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java @@ -51,6 +51,11 @@ public RestNodesHotThreadsAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/hot_threads", this); } + @Override + public String getName() { + return "nodes_hot_threads_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodeId")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesInfoAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesInfoAction.java index dfe3b08697c97..256693fc392ea 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesInfoAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesInfoAction.java @@ -62,6 +62,11 @@ public RestNodesInfoAction(Settings settings, RestController controller, Setting this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "nodes_info_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] nodeIds; diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsAction.java index f42a8fcf07739..28f8163760fc9 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsAction.java @@ -84,6 +84,11 @@ public RestNodesStatsAction(Settings settings, RestController controller) { FLAGS = Collections.unmodifiableMap(flags); } + @Override + public String getName() { + return "nodes_stats_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodeId")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesUsageAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesUsageAction.java new file mode 100644 index 0000000000000..b22f63ca78dc8 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesUsageAction.java @@ -0,0 +1,98 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.rest.action.admin.cluster; + +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageRequest; +import org.elasticsearch.action.admin.cluster.node.usage.NodesUsageResponse; +import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.rest.BytesRestResponse; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.RestResponse; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.rest.action.RestActions; +import org.elasticsearch.rest.action.RestBuilderListener; + +import java.io.IOException; +import java.util.Locale; +import java.util.Set; + +import static org.elasticsearch.rest.RestRequest.Method.GET; + +public class RestNodesUsageAction extends BaseRestHandler { + + @Inject + public RestNodesUsageAction(Settings settings, RestController controller) { + super(settings); + controller.registerHandler(GET, "/_nodes/usage", this); + controller.registerHandler(GET, "/_nodes/{nodeId}/usage", this); + + controller.registerHandler(GET, "/_nodes/usage/{metric}", this); + controller.registerHandler(GET, "/_nodes/{nodeId}/usage/{metric}", this); + } + + @Override + protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodeId")); + Set metrics = Strings.splitStringByCommaToSet(request.param("metric", "_all")); + + NodesUsageRequest nodesUsageRequest = new NodesUsageRequest(nodesIds); + nodesUsageRequest.timeout(request.param("timeout")); + + if (metrics.size() == 1 && metrics.contains("_all")) { + nodesUsageRequest.all(); + } else if (metrics.contains("_all")) { + throw new IllegalArgumentException(String.format(Locale.ROOT, "request [%s] contains _all and individual metrics [%s]", + request.path(), request.param("metric"))); + } else { + nodesUsageRequest.clear(); + nodesUsageRequest.restActions(metrics.contains("rest_actions")); + } + + return channel -> client.admin().cluster().nodesUsage(nodesUsageRequest, new RestBuilderListener(channel) { + + @Override + public RestResponse buildResponse(NodesUsageResponse response, XContentBuilder builder) throws Exception { + builder.startObject(); + RestActions.buildNodesHeader(builder, channel.request(), response); + builder.field("cluster_name", response.getClusterName().value()); + response.toXContent(builder, channel.request()); + builder.endObject(); + + return new BytesRestResponse(RestStatus.OK, builder); + } + }); + } + + @Override + public String getName() { + return "nodes_usage_action"; + } + + @Override + public boolean canTripCircuitBreaker() { + return false; + } +} diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPendingClusterTasksAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPendingClusterTasksAction.java index 29b2b72895bb9..ab2beda1d036f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPendingClusterTasksAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPendingClusterTasksAction.java @@ -35,6 +35,11 @@ public RestPendingClusterTasksAction(Settings settings, RestController controlle controller.registerHandler(RestRequest.Method.GET, "/_cluster/pending_tasks", this); } + @Override + public String getName() { + return "pending_cluster_tasks_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { PendingClusterTasksRequest pendingClusterTasksRequest = new PendingClusterTasksRequest(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutRepositoryAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutRepositoryAction.java index afd2fd851aead..b87871e064e3a 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutRepositoryAction.java @@ -44,6 +44,10 @@ public RestPutRepositoryAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_snapshot/{repository}", this); } + @Override + public String getName() { + return "put_repository_action"; + } @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutStoredScriptAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutStoredScriptAction.java index 358c3656ceddf..767aaf843f4a4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutStoredScriptAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestPutStoredScriptAction.java @@ -46,6 +46,11 @@ public RestPutStoredScriptAction(Settings settings, RestController controller) { controller.registerHandler(PUT, "/_scripts/{lang}/{id}", this); } + @Override + public String getName() { + return "put_stored_script_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String id = request.param("id"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRemoteClusterInfoAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRemoteClusterInfoAction.java index c15b2553e5de6..75baf8cecaaa5 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRemoteClusterInfoAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRemoteClusterInfoAction.java @@ -44,6 +44,11 @@ public RestRemoteClusterInfoAction(Settings settings, RestController controller) controller.registerHandler(GET, "_remote/info", this); } + @Override + public String getName() { + return "remote_cluster_info_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRestoreSnapshotAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRestoreSnapshotAction.java index 3948921c12da3..2bd077037ecb0 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRestoreSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestRestoreSnapshotAction.java @@ -41,6 +41,11 @@ public RestRestoreSnapshotAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_snapshot/{repository}/{snapshot}/_restore", this); } + @Override + public String getName() { + return "restore_snapshot_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { RestoreSnapshotRequest restoreSnapshotRequest = restoreSnapshotRequest(request.param("repository"), request.param("snapshot")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestSnapshotsStatusAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestSnapshotsStatusAction.java index c5122641c1a15..a06a916420e1f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestSnapshotsStatusAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestSnapshotsStatusAction.java @@ -44,6 +44,11 @@ public RestSnapshotsStatusAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_snapshot/_status", this); } + @Override + public String getName() { + return "snapshot_status_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String repository = request.param("repository", "_all"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestVerifyRepositoryAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestVerifyRepositoryAction.java index a9fb44eae645b..92debec6bf8aa 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestVerifyRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestVerifyRepositoryAction.java @@ -38,6 +38,11 @@ public RestVerifyRepositoryAction(Settings settings, RestController controller) controller.registerHandler(POST, "/_snapshot/{repository}/_verify", this); } + @Override + public String getName() { + return "verify_repository_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { VerifyRepositoryRequest verifyRepositoryRequest = verifyRepositoryRequest(request.param("repository")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestAnalyzeAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestAnalyzeAction.java index 52ba58e4c38c2..44ff79c4d9fa0 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestAnalyzeAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestAnalyzeAction.java @@ -56,6 +56,11 @@ public RestAnalyzeAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/_analyze", this); } + @Override + public String getName() { + return "analyze_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestClearIndicesCacheAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestClearIndicesCacheAction.java index 1544a01f9f09b..6e38b867edc9f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestClearIndicesCacheAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestClearIndicesCacheAction.java @@ -52,6 +52,11 @@ public RestClearIndicesCacheAction(Settings settings, RestController controller) controller.registerHandler(GET, "/{index}/_cache/clear", this); } + @Override + public String getName() { + return "clear_indices_cache_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ClearIndicesCacheRequest clearIndicesCacheRequest = new ClearIndicesCacheRequest( diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCloseIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCloseIndexAction.java index 2e0a46747ca77..d750dedd4b8d0 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCloseIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCloseIndexAction.java @@ -38,6 +38,11 @@ public RestCloseIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.POST, "/{index}/_close", this); } + @Override + public String getName() { + return "close_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { CloseIndexRequest closeIndexRequest = new CloseIndexRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java index 8c314efee634a..6a741fd3951d3 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestCreateIndexAction.java @@ -38,6 +38,11 @@ public RestCreateIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.PUT, "/{index}", this); } + @Override + public String getName() { + return "create_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { CreateIndexRequest createIndexRequest = new CreateIndexRequest(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java index 6ca806bcffe01..d3f2566026151 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexAction.java @@ -38,6 +38,11 @@ public RestDeleteIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.DELETE, "/{index}", this); } + @Override + public String getName() { + return "delete_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexTemplateAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexTemplateAction.java index e9f315e8aee0f..c3fad98087755 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexTemplateAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestDeleteIndexTemplateAction.java @@ -34,6 +34,11 @@ public RestDeleteIndexTemplateAction(Settings settings, RestController controlle controller.registerHandler(RestRequest.Method.DELETE, "/_template/{name}", this); } + @Override + public String getName() { + return "delete_index_template_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { DeleteIndexTemplateRequest deleteIndexTemplateRequest = new DeleteIndexTemplateRequest(request.param("name")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestFlushAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestFlushAction.java index ff084e023a8f7..be64b6557581e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestFlushAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestFlushAction.java @@ -50,6 +50,11 @@ public RestFlushAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_flush", this); } + @Override + public String getName() { + return "flush_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { FlushRequest flushRequest = new FlushRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestForceMergeAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestForceMergeAction.java index 32820edda0d0f..79beb66d40b1b 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestForceMergeAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestForceMergeAction.java @@ -46,6 +46,11 @@ public RestForceMergeAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/_forcemerge", this); } + @Override + public String getName() { + return "force_merge_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ForceMergeRequest mergeRequest = new ForceMergeRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetAliasesAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetAliasesAction.java index e7b53961b989f..41408fdcf6c61 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetAliasesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetAliasesAction.java @@ -20,6 +20,7 @@ package org.elasticsearch.rest.action.admin.indices; import com.carrotsearch.hppc.cursors.ObjectObjectCursor; + import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse; import org.elasticsearch.action.support.IndicesOptions; @@ -60,6 +61,11 @@ public RestGetAliasesAction(final Settings settings, final RestController contro controller.registerHandler(HEAD, "/{index}/_alias/{name}", this); } + @Override + public String getName() { + return "get_aliases_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] aliases = request.paramAsStringArrayOrEmptyIfAll("name"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetFieldMappingAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetFieldMappingAction.java index fe6eb9a552f32..ea68d9cc3c04f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetFieldMappingAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetFieldMappingAction.java @@ -52,6 +52,11 @@ public RestGetFieldMappingAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_mapping/{type}/field/{fields}", this); } + @Override + public String getName() { + return "get_field_mapping_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndexTemplateAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndexTemplateAction.java index 1814894636f77..38c1cb76611f4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndexTemplateAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndexTemplateAction.java @@ -50,6 +50,11 @@ public RestGetIndexTemplateAction(final Settings settings, final RestController controller.registerHandler(HEAD, "/_template/{name}", this); } + @Override + public String getName() { + return "get_index_template_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] names = Strings.splitStringByCommaToArray(request.param("name")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java index fc6682347fd42..3a9ba2a20ed22 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetIndicesAction.java @@ -71,6 +71,11 @@ public RestGetIndicesAction( this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "get_indices_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java index 66e23fd5f47b8..47a6cdfc8cd1b 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetMappingAction.java @@ -53,6 +53,11 @@ public RestGetMappingAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_mapping/{type}", this); } + @Override + public String getName() { + return "get_mapping_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetSettingsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetSettingsAction.java index fcad131a3599a..7e988c49428ba 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetSettingsAction.java @@ -57,6 +57,11 @@ public RestGetSettingsAction(Settings settings, RestController controller, Index this.settingsFilter = settingsFilter; } + @Override + public String getName() { + return "get_settings_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] names = request.paramAsStringArrayOrEmptyIfAll("name"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexDeleteAliasesAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexDeleteAliasesAction.java index 2068faa83e7d8..696b7768404b4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexDeleteAliasesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexDeleteAliasesAction.java @@ -39,6 +39,11 @@ public RestIndexDeleteAliasesAction(Settings settings, RestController controller controller.registerHandler(DELETE, "/{index}/_aliases/{name}", this); } + @Override + public String getName() { + return "index_delete_aliases_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexPutAliasAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexPutAliasAction.java index 2c68c4886103b..dc95e15802e88 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexPutAliasAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndexPutAliasAction.java @@ -53,6 +53,11 @@ public RestIndexPutAliasAction(Settings settings, RestController controller) { //we cannot add POST for "/_aliases" because this is the _aliases api already defined in RestIndicesAliasesAction } + @Override + public String getName() { + return "index_put_alias_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesAliasesAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesAliasesAction.java index 58add2b4ea841..b0c8122d4dfa4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesAliasesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesAliasesAction.java @@ -45,6 +45,11 @@ public class RestIndicesAliasesAction extends BaseRestHandler { }, AliasActions.PARSER, new ParseField("actions")); } + @Override + public String getName() { + return "indices_aliases_action"; + } + public RestIndicesAliasesAction(Settings settings, RestController controller) { super(settings); controller.registerHandler(POST, "/_aliases", this); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesSegmentsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesSegmentsAction.java index 6852b8527c754..a57a404baf2ef 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesSegmentsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesSegmentsAction.java @@ -46,6 +46,11 @@ public RestIndicesSegmentsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_segments", this); } + @Override + public String getName() { + return "indices_segments_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { IndicesSegmentsRequest indicesSegmentsRequest = new IndicesSegmentsRequest( diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesShardStoresAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesShardStoresAction.java index c00e6efffb032..a498557ab3751 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesShardStoresAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesShardStoresAction.java @@ -49,6 +49,11 @@ public RestIndicesShardStoresAction(Settings settings, RestController controller controller.registerHandler(GET, "/{index}/_shard_stores", this); } + @Override + public String getName() { + return "indices_shard_stores_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { IndicesShardStoresRequest indicesShardStoresRequest = new IndicesShardStoresRequest( diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsAction.java index ef91ad6accd64..5458a60e141ca 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsAction.java @@ -55,6 +55,11 @@ public RestIndicesStatsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_stats/{metric}", this); } + @Override + public String getName() { + return "indices_stats_action"; + } + static final Map> METRICS; static { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java index 4bde6fdb7224f..0e6ca47dd1ab5 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestOpenIndexAction.java @@ -39,6 +39,11 @@ public RestOpenIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.POST, "/{index}/_open", this); } + @Override + public String getName() { + return "open_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { OpenIndexRequest openIndexRequest = new OpenIndexRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutIndexTemplateAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutIndexTemplateAction.java index b376f3dab30a2..c3c369838bfc0 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutIndexTemplateAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutIndexTemplateAction.java @@ -44,6 +44,11 @@ public RestPutIndexTemplateAction(Settings settings, RestController controller) controller.registerHandler(RestRequest.Method.POST, "/_template/{name}", this); } + @Override + public String getName() { + return "put_index_template_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest(request.param("name")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutMappingAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutMappingAction.java index 06fe67926455f..0eddb9d67bc48 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutMappingAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestPutMappingAction.java @@ -60,6 +60,11 @@ public RestPutMappingAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_mappings/{type}", this); } + @Override + public String getName() { + return "put_mapping_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { PutMappingRequest putMappingRequest = putMappingRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRecoveryAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRecoveryAction.java index ab1295e9c6015..4516ebeeb565d 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRecoveryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRecoveryAction.java @@ -48,6 +48,11 @@ public RestRecoveryAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_recovery", this); } + @Override + public String getName() { + return "recovery_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRefreshAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRefreshAction.java index 7b317ab404e48..46dadf9040cd5 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRefreshAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRefreshAction.java @@ -37,7 +37,6 @@ import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; -import static org.elasticsearch.rest.RestStatus.OK; import static org.elasticsearch.rest.action.RestActions.buildBroadcastShardsHeader; public class RestRefreshAction extends BaseRestHandler { @@ -50,6 +49,11 @@ public RestRefreshAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_refresh", this); } + @Override + public String getName() { + return "refresh_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { RefreshRequest refreshRequest = new RefreshRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java index 59068f277d633..bd31ec3a70cc9 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestRolloverIndexAction.java @@ -37,6 +37,11 @@ public RestRolloverIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.POST, "/{index}/_rollover/{new_index}", this); } + @Override + public String getName() { + return "rollover_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { RolloverRequest rolloverIndexRequest = new RolloverRequest(request.param("index"), request.param("new_index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java index 1b63eb7f6d3ab..10b46be6760bb 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestShrinkIndexAction.java @@ -39,6 +39,11 @@ public RestShrinkIndexAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.POST, "/{index}/_shrink/{target}", this); } + @Override + public String getName() { + return "shrink_index_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { if (request.param("target") == null) { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSyncedFlushAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSyncedFlushAction.java index 8a3113317294b..4824fe4a84231 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSyncedFlushAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestSyncedFlushAction.java @@ -48,6 +48,11 @@ public RestSyncedFlushAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_flush/synced", this); } + @Override + public String getName() { + return "synced_flush_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, IndicesOptions.lenientExpandOpen()); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestTypesExistsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestTypesExistsAction.java index dcded02eb0d43..b270fed30ce41 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestTypesExistsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestTypesExistsAction.java @@ -49,6 +49,11 @@ public RestTypesExistsAction(Settings settings, RestController controller) { HEAD, "/{index}/{type}", deprecationLogger); } + @Override + public String getName() { + return "types_exists_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { TypesExistsRequest typesExistsRequest = new TypesExistsRequest( diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpdateSettingsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpdateSettingsAction.java index 9a168e84dd683..7eee3c8408edd 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpdateSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpdateSettingsAction.java @@ -45,6 +45,11 @@ public RestUpdateSettingsAction(Settings settings, RestController controller) { controller.registerHandler(RestRequest.Method.PUT, "/_settings", this); } + @Override + public String getName() { + return "update_settings_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { UpdateSettingsRequest updateSettingsRequest = updateSettingsRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpgradeAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpgradeAction.java index 9437ad5eada93..1d32c14655ade 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpgradeAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestUpgradeAction.java @@ -55,6 +55,11 @@ public RestUpgradeAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/{index}/_upgrade", this); } + @Override + public String getName() { + return "upgrade_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { if (request.method().equals(RestRequest.Method.GET)) { diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestValidateQueryAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestValidateQueryAction.java index 0c2374045dd9b..df1c14c480650 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestValidateQueryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/RestValidateQueryAction.java @@ -55,6 +55,11 @@ public RestValidateQueryAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_validate/query", this); } + @Override + public String getName() { + return "validate_query_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { ValidateQueryRequest validateQueryRequest = new ValidateQueryRequest(Strings.splitStringByCommaToArray(request.param("index"))); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestAliasAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestAliasAction.java index a783a9c2a8215..774a603cb4b7f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestAliasAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestAliasAction.java @@ -43,6 +43,11 @@ public RestAliasAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/aliases/{alias}", this); } + @Override + public String getName() { + return "cat_alias_action"; + } + @Override protected RestChannelConsumer doCatRequest(final RestRequest request, final NodeClient client) { final GetAliasesRequest getAliasesRequest = request.hasParam("alias") ? diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestAllocationAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestAllocationAction.java index 0077297cbf3c9..60b76269ebc37 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestAllocationAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestAllocationAction.java @@ -50,6 +50,11 @@ public RestAllocationAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/allocation/{nodes}", this); } + @Override + public String getName() { + return "cat_allocation_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/allocation\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestCatAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestCatAction.java index 7442a7d85ee6b..d52449ea66f4a 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestCatAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestCatAction.java @@ -51,6 +51,11 @@ public RestCatAction(Settings settings, RestController controller, List channel.sendResponse(new BytesRestResponse(RestStatus.OK, HELP)); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestCountAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestCountAction.java index bbc7ffa250c9b..840f4de5ea7b7 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestCountAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestCountAction.java @@ -45,6 +45,11 @@ public RestCountAction(Settings settings, RestController restController) { restController.registerHandler(GET, "/_cat/count/{index}", this); } + @Override + public String getName() { + return "cat_count_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/count\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestFielddataAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestFielddataAction.java index 4156ea4619273..120ea60327158 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestFielddataAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestFielddataAction.java @@ -45,6 +45,11 @@ public RestFielddataAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/fielddata/{fields}", this); } + @Override + public String getName() { + return "cat_fielddata_action"; + } + @Override protected RestChannelConsumer doCatRequest(final RestRequest request, final NodeClient client) { final NodesStatsRequest nodesStatsRequest = new NodesStatsRequest("data:true"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestHealthAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestHealthAction.java index 2bc1c11b9a1d0..d7e72f207ffe8 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestHealthAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestHealthAction.java @@ -39,6 +39,11 @@ public RestHealthAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/health", this); } + @Override + public String getName() { + return "cat_health_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/health\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java index 46bbc4652cf9b..6bcb073d1106e 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java @@ -66,6 +66,11 @@ public RestIndicesAction(Settings settings, RestController controller, IndexName controller.registerHandler(GET, "/_cat/indices/{index}", this); } + @Override + public String getName() { + return "cat_indices_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/indices\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestMasterAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestMasterAction.java index db5c1149cc0ad..d1753aa868fd7 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestMasterAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestMasterAction.java @@ -39,6 +39,11 @@ public RestMasterAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/master", this); } + @Override + public String getName() { + return "cat_master_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/master\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodeAttrsAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodeAttrsAction.java index 6d9c5bd57e5b1..2e396ac59b7cc 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodeAttrsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodeAttrsAction.java @@ -46,6 +46,11 @@ public RestNodeAttrsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/nodeattrs", this); } + @Override + public String getName() { + return "cat_node_attrs_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/nodeattrs\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java index faa07e7ddaad8..104ffe420abde 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java @@ -71,6 +71,11 @@ public RestNodesAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/nodes", this); } + @Override + public String getName() { + return "cat_nodes_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/nodes\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestPendingClusterTasksAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestPendingClusterTasksAction.java index a9f044c144642..21a3c0c3c82de 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestPendingClusterTasksAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestPendingClusterTasksAction.java @@ -38,6 +38,11 @@ public RestPendingClusterTasksAction(Settings settings, RestController controlle controller.registerHandler(GET, "/_cat/pending_tasks", this); } + @Override + public String getName() { + return "cat_pending_cluster_tasks_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/pending_tasks\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java index 7851c15b32f76..f61a5fdeb7e23 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestPluginsAction.java @@ -44,6 +44,11 @@ public RestPluginsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/plugins", this); } + @Override + public String getName() { + return "cat_plugins_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/plugins\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestRecoveryAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestRecoveryAction.java index e2e831f890d99..a66741c2d9411 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestRecoveryAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestRecoveryAction.java @@ -54,6 +54,11 @@ public RestRecoveryAction(Settings settings, RestController restController) { restController.registerHandler(GET, "/_cat/recovery/{index}", this); } + @Override + public String getName() { + return "cat_recovery_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/recovery\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestRepositoriesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestRepositoriesAction.java index 631c03050492d..42cb904f2f0ef 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestRepositoriesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestRepositoriesAction.java @@ -58,6 +58,11 @@ public RestResponse buildResponse(GetRepositoriesResponse getRepositoriesRespons }); } + @Override + public String getName() { + return "cat_repositories_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/repositories\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java index 48983ab836b7a..0d84549f145b0 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestSegmentsAction.java @@ -50,6 +50,11 @@ public RestSegmentsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/segments/{index}", this); } + @Override + public String getName() { + return "cat_segments_action"; + } + @Override protected RestChannelConsumer doCatRequest(final RestRequest request, final NodeClient client) { final String[] indices = Strings.splitStringByCommaToArray(request.param("index")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java index e74510012383e..d985c86d9b3b9 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java @@ -52,6 +52,11 @@ public RestShardsAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/shards/{index}", this); } + @Override + public String getName() { + return "cat_shards_action"; + } + @Override protected void documentation(StringBuilder sb) { sb.append("/_cat/shards\n"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestSnapshotAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestSnapshotAction.java index 54337e5e14369..6d44e9aa856bd 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestSnapshotAction.java @@ -49,6 +49,11 @@ public RestSnapshotAction(Settings settings, RestController controller) { controller.registerHandler(GET, "/_cat/snapshots/{repository}", this); } + @Override + public String getName() { + return "cat_snapshot_action"; + } + @Override protected RestChannelConsumer doCatRequest(final RestRequest request, NodeClient client) { GetSnapshotsRequest getSnapshotsRequest = new GetSnapshotsRequest() diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestTasksAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestTasksAction.java index 5a49feb9c4b1f..c0ebddc2908d1 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestTasksAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestTasksAction.java @@ -55,6 +55,11 @@ public RestTasksAction(Settings settings, RestController controller, Supplier sourceTuple = restRequest.contentOrSourceParam(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/ingest/RestSimulatePipelineAction.java b/core/src/main/java/org/elasticsearch/rest/action/ingest/RestSimulatePipelineAction.java index 9dbe1808a8c59..c5f01e25a9cbf 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/ingest/RestSimulatePipelineAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/ingest/RestSimulatePipelineAction.java @@ -41,6 +41,11 @@ public RestSimulatePipelineAction(Settings settings, RestController controller) controller.registerHandler(RestRequest.Method.GET, "/_ingest/pipeline/_simulate", this); } + @Override + public String getName() { + return "ingest_simulate_pipeline_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException { Tuple sourceTuple = restRequest.contentOrSourceParam(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestClearScrollAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestClearScrollAction.java index 80d833ed3118a..dc2474c653315 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestClearScrollAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestClearScrollAction.java @@ -41,6 +41,11 @@ public RestClearScrollAction(Settings settings, RestController controller) { controller.registerHandler(DELETE, "/_search/scroll/{scroll_id}", this); } + @Override + public String getName() { + return "clear_scroll_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String scrollIds = request.param("scroll_id"); diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestExplainAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestExplainAction.java index 7339718c28b0b..b0adc27f447f5 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestExplainAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestExplainAction.java @@ -54,6 +54,11 @@ public RestExplainAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/{id}/_explain", this); } + @Override + public String getName() { + return "explain_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { final ExplainRequest explainRequest = new ExplainRequest(request.param("index"), request.param("type"), request.param("id")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java index f27ba5018e428..3857a4c5b4212 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java @@ -69,6 +69,11 @@ public RestMultiSearchAction(Settings settings, RestController controller) { this.allowExplicitIndex = MULTI_ALLOW_EXPLICIT_INDEX.get(settings); } + @Override + public String getName() { + return "msearch_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { MultiSearchRequest multiSearchRequest = parseRequest(request, allowExplicitIndex); diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java index 89e2f23861c98..291f37ea12e67 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java @@ -66,6 +66,11 @@ public RestSearchAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_search", this); } + @Override + public String getName() { + return "search_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { SearchRequest searchRequest = new SearchRequest(); diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchScrollAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchScrollAction.java index 59b7c660fa163..bc3b0ccb56ac3 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchScrollAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchScrollAction.java @@ -44,6 +44,11 @@ public RestSearchScrollAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_search/scroll/{scroll_id}", this); } + @Override + public String getName() { + return "search_scroll_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { String scrollId = request.param("scroll_id"); diff --git a/core/src/main/java/org/elasticsearch/usage/UsageService.java b/core/src/main/java/org/elasticsearch/usage/UsageService.java new file mode 100644 index 0000000000000..9f742cca9d94a --- /dev/null +++ b/core/src/main/java/org/elasticsearch/usage/UsageService.java @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.usage; + +import org.elasticsearch.action.admin.cluster.node.usage.NodeUsage; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.rest.BaseRestHandler; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A service to monitor usage of Elasticsearch features. + */ +public class UsageService extends AbstractComponent { + + private final List handlers; + private final long sinceTime; + + @Inject + public UsageService(Settings settings) { + super(settings); + this.handlers = new ArrayList<>(); + this.sinceTime = System.currentTimeMillis(); + } + + /** + * Add a REST handler to this service. + * + * @param handler + * the {@link BaseRestHandler} to add to the usage service. + */ + public void addRestHandler(BaseRestHandler handler) { + handlers.add(handler); + } + + /** + * Get the current usage statistics for this node. + * + * @param localNode + * the {@link DiscoveryNode} for this node + * @param restActions + * whether to include rest action usage in the returned + * statistics + * @return the {@link NodeUsage} representing the usage statistics for this + * node + */ + public NodeUsage getUsageStats(DiscoveryNode localNode, boolean restActions) { + Map restUsageMap; + if (restActions) { + restUsageMap = new HashMap<>(); + handlers.forEach(handler -> { + long usageCount = handler.getUsageCount(); + if (usageCount > 0) { + restUsageMap.put(handler.getName(), usageCount); + } + }); + } else { + restUsageMap = null; + } + return new NodeUsage(localNode, System.currentTimeMillis(), sinceTime, restUsageMap); + } + +} diff --git a/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java b/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java index 7c9d54434644a..44c22c9e412d2 100644 --- a/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java +++ b/core/src/test/java/org/elasticsearch/action/ActionModuleTests.java @@ -43,6 +43,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.usage.UsageService; import java.io.IOException; import java.util.List; @@ -110,9 +111,10 @@ public ActionResponse newResponse() { public void testSetupRestHandlerContainsKnownBuiltin() { SettingsModule settings = new SettingsModule(Settings.EMPTY); + UsageService usageService = new UsageService(settings.getSettings()); ActionModule actionModule = new ActionModule(false, settings.getSettings(), new IndexNameExpressionResolver(Settings.EMPTY), settings.getIndexScopedSettings(), settings.getClusterSettings(), settings.getSettingsFilter(), null, emptyList(), null, - null); + null, usageService); actionModule.initRestHandlers(null); // At this point the easiest way to confirm that a handler is loaded is to try to register another one on top of it and to fail Exception e = expectThrows(IllegalArgumentException.class, () -> @@ -132,9 +134,10 @@ public List getRestHandlers(Settings settings, RestController restC SettingsModule settings = new SettingsModule(Settings.EMPTY); ThreadPool threadPool = new TestThreadPool(getTestName()); try { + UsageService usageService = new UsageService(settings.getSettings()); ActionModule actionModule = new ActionModule(false, settings.getSettings(), new IndexNameExpressionResolver(Settings.EMPTY), settings.getIndexScopedSettings(), settings.getClusterSettings(), settings.getSettingsFilter(), threadPool, - singletonList(dupsMainAction), null, null); + singletonList(dupsMainAction), null, null, usageService); Exception e = expectThrows(IllegalArgumentException.class, () -> actionModule.initRestHandlers(null)); assertThat(e.getMessage(), startsWith("Path [/] already has a value [" + RestMainAction.class.getName())); } finally { @@ -163,9 +166,10 @@ public List getRestHandlers(Settings settings, RestController restC SettingsModule settings = new SettingsModule(Settings.EMPTY); ThreadPool threadPool = new TestThreadPool(getTestName()); try { + UsageService usageService = new UsageService(settings.getSettings()); ActionModule actionModule = new ActionModule(false, settings.getSettings(), new IndexNameExpressionResolver(Settings.EMPTY), settings.getIndexScopedSettings(), settings.getClusterSettings(), settings.getSettingsFilter(), threadPool, - singletonList(registersFakeHandler), null, null); + singletonList(registersFakeHandler), null, null, usageService); actionModule.initRestHandlers(null); // At this point the easiest way to confirm that a handler is loaded is to try to register another one on top of it and to fail Exception e = expectThrows(IllegalArgumentException.class, () -> diff --git a/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java b/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java index e393fee4f23ed..81e685e68529e 100644 --- a/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java +++ b/core/src/test/java/org/elasticsearch/common/network/NetworkModuleTests.java @@ -101,6 +101,10 @@ static class FakeRestHandler extends BaseRestHandler { } @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return channel -> {}; } + @Override + public String getName() { + return "FakeRestHandler"; + } } static class FakeCatRestHandler extends AbstractCatAction { @@ -115,6 +119,10 @@ protected void documentation(StringBuilder sb) {} protected Table getTableWithHeader(RestRequest request) { return null; } + @Override + public String getName() { + return "FakeCatRestHandler"; + } } public void testRegisterTransport() { diff --git a/core/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java b/core/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java index 732614112bd99..835dd7cd9fab0 100644 --- a/core/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java +++ b/core/src/test/java/org/elasticsearch/rest/BaseRestHandlerTests.java @@ -47,6 +47,11 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli request.param("consumed"); return channel -> executed.set(true); } + + @Override + public String getName() { + return "test_one_unconsumed_response_action"; + } }; final HashMap params = new HashMap<>(); @@ -68,6 +73,11 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli request.param("consumed"); return channel -> executed.set(true); } + + @Override + public String getName() { + return "test_multiple_unconsumed_response_action"; + } }; final HashMap params = new HashMap<>(); @@ -99,6 +109,11 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli protected Set responseParams() { return Collections.singleton("response_param"); } + + @Override + public String getName() { + return "test_unconsumed_did_you_mean_response_action"; + } }; final HashMap params = new HashMap<>(); @@ -137,6 +152,11 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli protected Set responseParams() { return Collections.singleton("response_param"); } + + @Override + public String getName() { + return "test_unconsumed_response_action"; + } }; final HashMap params = new HashMap<>(); @@ -155,6 +175,11 @@ public void testDefaultResponseParameters() throws Exception { protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return channel -> executed.set(true); } + + @Override + public String getName() { + return "test_default_response_action"; + } }; final HashMap params = new HashMap<>(); @@ -185,6 +210,11 @@ protected void documentation(StringBuilder sb) { protected Table getTableWithHeader(RestRequest request) { return null; } + + @Override + public String getName() { + return "test_cat_response_action"; + } }; final HashMap params = new HashMap<>(); diff --git a/core/src/test/java/org/elasticsearch/rest/RestControllerTests.java b/core/src/test/java/org/elasticsearch/rest/RestControllerTests.java index 102cfe5e3ac53..589a3edbe1dda 100644 --- a/core/src/test/java/org/elasticsearch/rest/RestControllerTests.java +++ b/core/src/test/java/org/elasticsearch/rest/RestControllerTests.java @@ -41,6 +41,7 @@ import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.usage.UsageService; import org.junit.Before; import java.io.IOException; @@ -68,6 +69,7 @@ public class RestControllerTests extends ESTestCase { private CircuitBreaker inFlightRequestsBreaker; private RestController restController; private HierarchyCircuitBreakerService circuitBreakerService; + private UsageService usageService; @Before public void setup() { @@ -77,11 +79,12 @@ public void setup() { .put(HierarchyCircuitBreakerService.IN_FLIGHT_REQUESTS_CIRCUIT_BREAKER_LIMIT_SETTING.getKey(), BREAKER_LIMIT) .build(), new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS)); + usageService = new UsageService(settings); // we can do this here only because we know that we don't adjust breaker settings dynamically in the test inFlightRequestsBreaker = circuitBreakerService.getBreaker(CircuitBreaker.IN_FLIGHT_REQUESTS); HttpServerTransport httpServerTransport = new TestHttpServerTransport(); - restController = new RestController(settings, Collections.emptySet(), null, null, circuitBreakerService); + restController = new RestController(settings, Collections.emptySet(), null, null, circuitBreakerService, usageService); restController.registerHandler(RestRequest.Method.GET, "/", (request, channel, client) -> channel.sendResponse( new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY))); @@ -96,7 +99,7 @@ public void setup() { public void testApplyRelevantHeaders() throws Exception { final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); Set headers = new HashSet<>(Arrays.asList("header.1", "header.2")); - final RestController restController = new RestController(Settings.EMPTY, headers, null, null, circuitBreakerService); + final RestController restController = new RestController(Settings.EMPTY, headers, null, null, circuitBreakerService, usageService); Map> restHeaders = new HashMap<>(); restHeaders.put("header.1", Collections.singletonList("true")); restHeaders.put("header.2", Collections.singletonList("true")); @@ -115,7 +118,8 @@ public void testApplyRelevantHeaders() throws Exception { } public void testCanTripCircuitBreaker() throws Exception { - RestController controller = new RestController(Settings.EMPTY, Collections.emptySet(), null, null, circuitBreakerService); + RestController controller = new RestController(Settings.EMPTY, Collections.emptySet(), null, null, circuitBreakerService, + usageService); // trip circuit breaker by default controller.registerHandler(RestRequest.Method.GET, "/trip", new FakeRestHandler(true)); controller.registerHandler(RestRequest.Method.GET, "/do-not-trip", new FakeRestHandler(false)); @@ -176,7 +180,7 @@ public void testRestHandlerWrapper() throws Exception { return (RestRequest request, RestChannel channel, NodeClient client) -> wrapperCalled.set(true); }; final RestController restController = new RestController(Settings.EMPTY, Collections.emptySet(), wrapper, null, - circuitBreakerService); + circuitBreakerService, usageService); final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); restController.dispatchRequest(new FakeRestRequest.Builder(xContentRegistry()).build(), null, null, threadContext, handler); assertTrue(wrapperCalled.get()); @@ -259,7 +263,7 @@ public void testDispatchRequiresContentTypeForRequestsWithContent() { AssertingChannel channel = new AssertingChannel(request, true, RestStatus.NOT_ACCEPTABLE); restController = new RestController( Settings.builder().put(HttpTransportSettings.SETTING_HTTP_CONTENT_TYPE_REQUIRED.getKey(), true).build(), - Collections.emptySet(), null, null, circuitBreakerService); + Collections.emptySet(), null, null, circuitBreakerService, usageService); restController.registerHandler(RestRequest.Method.GET, "/", (r, c, client) -> c.sendResponse( new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, BytesArray.EMPTY))); diff --git a/core/src/test/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsActionTests.java b/core/src/test/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsActionTests.java index 7ece6934a21a0..640b97605af15 100644 --- a/core/src/test/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsActionTests.java +++ b/core/src/test/java/org/elasticsearch/rest/action/admin/cluster/RestNodesStatsActionTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.rest.RestRequest; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.usage.UsageService; import java.io.IOException; import java.util.Collections; @@ -43,7 +44,9 @@ public class RestNodesStatsActionTests extends ESTestCase { @Override public void setUp() throws Exception { super.setUp(); - action = new RestNodesStatsAction(Settings.EMPTY, new RestController(Settings.EMPTY, Collections.emptySet(), null, null, null)); + UsageService usageService = new UsageService(Settings.EMPTY); + action = new RestNodesStatsAction(Settings.EMPTY, + new RestController(Settings.EMPTY, Collections.emptySet(), null, null, null, usageService)); } public void testUnrecognizedMetric() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsActionTests.java b/core/src/test/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsActionTests.java index 12fcdaa2f55bb..26c1e1fa17779 100644 --- a/core/src/test/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsActionTests.java +++ b/core/src/test/java/org/elasticsearch/rest/action/admin/indices/RestIndicesStatsActionTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.rest.RestRequest; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.usage.UsageService; import java.io.IOException; import java.util.Collections; @@ -41,7 +42,9 @@ public class RestIndicesStatsActionTests extends ESTestCase { @Override public void setUp() throws Exception { super.setUp(); - action = new RestIndicesStatsAction(Settings.EMPTY, new RestController(Settings.EMPTY, Collections.emptySet(), null, null, null)); + UsageService usageService = new UsageService(Settings.EMPTY); + action = new RestIndicesStatsAction(Settings.EMPTY, + new RestController(Settings.EMPTY, Collections.emptySet(), null, null, null, usageService)); } public void testUnrecognizedMetric() throws IOException { diff --git a/core/src/test/java/org/elasticsearch/rest/action/cat/RestIndicesActionTests.java b/core/src/test/java/org/elasticsearch/rest/action/cat/RestIndicesActionTests.java index 7ee15adae3316..998020cbd2659 100644 --- a/core/src/test/java/org/elasticsearch/rest/action/cat/RestIndicesActionTests.java +++ b/core/src/test/java/org/elasticsearch/rest/action/cat/RestIndicesActionTests.java @@ -58,6 +58,7 @@ import org.elasticsearch.search.suggest.completion.CompletionStats; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.usage.UsageService; import java.nio.file.Path; import java.util.ArrayList; @@ -74,7 +75,8 @@ public class RestIndicesActionTests extends ESTestCase { public void testBuildTable() { final Settings settings = Settings.EMPTY; - final RestController restController = new RestController(settings, Collections.emptySet(), null, null, null); + UsageService usageService = new UsageService(settings); + final RestController restController = new RestController(settings, Collections.emptySet(), null, null, null, usageService); final RestIndicesAction action = new RestIndicesAction(settings, restController, new IndexNameExpressionResolver(settings)); // build a (semi-)random table diff --git a/core/src/test/java/org/elasticsearch/rest/action/cat/RestRecoveryActionTests.java b/core/src/test/java/org/elasticsearch/rest/action/cat/RestRecoveryActionTests.java index 6fce7219d67c2..148af7f7d875f 100644 --- a/core/src/test/java/org/elasticsearch/rest/action/cat/RestRecoveryActionTests.java +++ b/core/src/test/java/org/elasticsearch/rest/action/cat/RestRecoveryActionTests.java @@ -34,6 +34,7 @@ import org.elasticsearch.indices.recovery.RecoveryState; import org.elasticsearch.rest.RestController; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.usage.UsageService; import java.util.ArrayList; import java.util.Collections; @@ -50,7 +51,8 @@ public class RestRecoveryActionTests extends ESTestCase { public void testRestRecoveryAction() { final Settings settings = Settings.EMPTY; - final RestController restController = new RestController(settings, Collections.emptySet(), null, null, null); + UsageService usageService = new UsageService(settings); + final RestController restController = new RestController(settings, Collections.emptySet(), null, null, null, usageService); final RestRecoveryAction action = new RestRecoveryAction(settings, restController); final int totalShards = randomIntBetween(1, 32); final int successfulShards = Math.max(0, totalShards - randomIntBetween(1, 2)); diff --git a/core/src/test/java/org/elasticsearch/usage/UsageServiceTests.java b/core/src/test/java/org/elasticsearch/usage/UsageServiceTests.java new file mode 100644 index 0000000000000..c6347b014bfb8 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/usage/UsageServiceTests.java @@ -0,0 +1,115 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.usage; + +import org.elasticsearch.Version; +import org.elasticsearch.action.admin.cluster.node.usage.NodeUsage; +import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.rest.FakeRestRequest; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.sameInstance; + +public class UsageServiceTests extends ESTestCase { + + public void testRestUsage() throws Exception { + DiscoveryNode discoveryNode = new DiscoveryNode("foo", new TransportAddress(InetAddress.getByName("localhost"), 12345), + Version.CURRENT); + Settings settings = Settings.EMPTY; + RestRequest restRequest = new FakeRestRequest(); + BaseRestHandler handlerA = new MockRestHandler("a", settings); + BaseRestHandler handlerB = new MockRestHandler("b", settings); + BaseRestHandler handlerC = new MockRestHandler("c", settings); + BaseRestHandler handlerD = new MockRestHandler("d", settings); + BaseRestHandler handlerE = new MockRestHandler("e", settings); + BaseRestHandler handlerF = new MockRestHandler("f", settings); + UsageService usageService = new UsageService(settings); + usageService.addRestHandler(handlerA); + usageService.addRestHandler(handlerB); + usageService.addRestHandler(handlerC); + usageService.addRestHandler(handlerD); + usageService.addRestHandler(handlerE); + usageService.addRestHandler(handlerF); + handlerA.handleRequest(restRequest, null, null); + handlerB.handleRequest(restRequest, null, null); + handlerA.handleRequest(restRequest, null, null); + handlerA.handleRequest(restRequest, null, null); + handlerB.handleRequest(restRequest, null, null); + handlerC.handleRequest(restRequest, null, null); + handlerC.handleRequest(restRequest, null, null); + handlerD.handleRequest(restRequest, null, null); + handlerA.handleRequest(restRequest, null, null); + handlerB.handleRequest(restRequest, null, null); + handlerE.handleRequest(restRequest, null, null); + handlerF.handleRequest(restRequest, null, null); + handlerC.handleRequest(restRequest, null, null); + handlerD.handleRequest(restRequest, null, null); + NodeUsage usage = usageService.getUsageStats(discoveryNode, true); + assertThat(usage.getNode(), sameInstance(discoveryNode)); + Map restUsage = usage.getRestUsage(); + assertThat(restUsage, notNullValue()); + assertThat(restUsage.size(), equalTo(6)); + assertThat(restUsage.get("a"), equalTo(4L)); + assertThat(restUsage.get("b"), equalTo(3L)); + assertThat(restUsage.get("c"), equalTo(3L)); + assertThat(restUsage.get("d"), equalTo(2L)); + assertThat(restUsage.get("e"), equalTo(1L)); + assertThat(restUsage.get("f"), equalTo(1L)); + + usage = usageService.getUsageStats(discoveryNode, false); + assertThat(usage.getNode(), sameInstance(discoveryNode)); + assertThat(usage.getRestUsage(), nullValue()); + } + + private class MockRestHandler extends BaseRestHandler { + + private String name; + + protected MockRestHandler(String name, Settings settings) { + super(settings); + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { + return channel -> { + }; + } + + } + +} diff --git a/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/NodeRestUsageIT.java b/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/NodeRestUsageIT.java new file mode 100644 index 0000000000000..b94aa71b04029 --- /dev/null +++ b/distribution/integ-test-zip/src/test/java/org/elasticsearch/test/rest/NodeRestUsageIT.java @@ -0,0 +1,148 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.test.rest; + +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.notNullValue; + +public class NodeRestUsageIT extends ESRestTestCase { + + @SuppressWarnings("unchecked") + public void testWithRestUsage() throws IOException { + // First get the current usage figures + Response beforeResponse = client().performRequest("GET", + randomFrom("_nodes/usage", "_nodes/usage/rest_actions", "_nodes/usage/_all")); + Map beforeResponseBodyMap = entityAsMap(beforeResponse); + assertThat(beforeResponseBodyMap, notNullValue()); + Map before_nodesMap = (Map) beforeResponseBodyMap.get("_nodes"); + assertThat(before_nodesMap, notNullValue()); + Integer beforeTotal = (Integer) before_nodesMap.get("total"); + Integer beforeSuccessful = (Integer) before_nodesMap.get("successful"); + Integer beforeFailed = (Integer) before_nodesMap.get("failed"); + assertThat(beforeTotal, greaterThan(0)); + assertThat(beforeSuccessful, equalTo(beforeTotal)); + assertThat(beforeFailed, equalTo(0)); + + Map beforeNodesMap = (Map) beforeResponseBodyMap.get("nodes"); + assertThat(beforeNodesMap, notNullValue()); + assertThat(beforeNodesMap.size(), equalTo(beforeSuccessful)); + Map beforeCombinedRestUsage = new HashMap<>(); + beforeCombinedRestUsage.put("nodes_usage_action", 0L); + beforeCombinedRestUsage.put("create_index_action", 0L); + beforeCombinedRestUsage.put("document_index_action", 0L); + beforeCombinedRestUsage.put("search_action", 0L); + beforeCombinedRestUsage.put("refresh_action", 0L); + beforeCombinedRestUsage.put("cat_indices_action", 0L); + beforeCombinedRestUsage.put("nodes_info_action", 0L); + beforeCombinedRestUsage.put("nodes_stats_action", 0L); + beforeCombinedRestUsage.put("delete_index_action", 0L); + for (Map.Entry nodeEntry : beforeNodesMap.entrySet()) { + Map beforeRestActionUsage = (Map) ((Map) nodeEntry.getValue()) + .get("rest_actions"); + assertThat(beforeRestActionUsage, notNullValue()); + for (Map.Entry restActionEntry : beforeRestActionUsage.entrySet()) { + Long currentUsage = beforeCombinedRestUsage.get(restActionEntry.getKey()); + if (currentUsage == null) { + beforeCombinedRestUsage.put(restActionEntry.getKey(), ((Number) restActionEntry.getValue()).longValue()); + } else { + beforeCombinedRestUsage.put(restActionEntry.getKey(), currentUsage + ((Number) restActionEntry.getValue()).longValue()); + } + } + } + + // Do some requests to get some rest usage stats + client().performRequest("PUT", "/test"); + client().performRequest("POST", "/test/doc/1", Collections.emptyMap(), + new StringEntity("{ \"foo\": \"bar\"}", ContentType.APPLICATION_JSON)); + client().performRequest("POST", "/test/doc/2", Collections.emptyMap(), + new StringEntity("{ \"foo\": \"bar\"}", ContentType.APPLICATION_JSON)); + client().performRequest("POST", "/test/doc/3", Collections.emptyMap(), + new StringEntity("{ \"foo\": \"bar\"}", ContentType.APPLICATION_JSON)); + client().performRequest("GET", "/test/_search"); + client().performRequest("POST", "/test/doc/4", Collections.emptyMap(), + new StringEntity("{ \"foo\": \"bar\"}", ContentType.APPLICATION_JSON)); + client().performRequest("POST", "/test/_refresh"); + client().performRequest("GET", "/_cat/indices"); + client().performRequest("GET", "/_nodes"); + client().performRequest("GET", "/test/_search"); + client().performRequest("GET", "/_nodes/stats"); + client().performRequest("DELETE", "/test"); + + Response response = client().performRequest("GET", "_nodes/usage"); + Map responseBodyMap = entityAsMap(response); + assertThat(responseBodyMap, notNullValue()); + Map _nodesMap = (Map) responseBodyMap.get("_nodes"); + assertThat(_nodesMap, notNullValue()); + Integer total = (Integer) _nodesMap.get("total"); + Integer successful = (Integer) _nodesMap.get("successful"); + Integer failed = (Integer) _nodesMap.get("failed"); + assertThat(total, greaterThan(0)); + assertThat(successful, equalTo(total)); + assertThat(failed, equalTo(0)); + + Map nodesMap = (Map) responseBodyMap.get("nodes"); + assertThat(nodesMap, notNullValue()); + assertThat(nodesMap.size(), equalTo(successful)); + Map combinedRestUsage = new HashMap<>(); + for (Map.Entry nodeEntry : nodesMap.entrySet()) { + Map restActionUsage = (Map) ((Map) nodeEntry.getValue()).get("rest_actions"); + assertThat(restActionUsage, notNullValue()); + for (Map.Entry restActionEntry : restActionUsage.entrySet()) { + Long currentUsage = combinedRestUsage.get(restActionEntry.getKey()); + if (currentUsage == null) { + combinedRestUsage.put(restActionEntry.getKey(), ((Number) restActionEntry.getValue()).longValue()); + } else { + combinedRestUsage.put(restActionEntry.getKey(), currentUsage + ((Number) restActionEntry.getValue()).longValue()); + } + } + } + assertThat(combinedRestUsage.get("nodes_usage_action") - beforeCombinedRestUsage.get("nodes_usage_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("create_index_action") - beforeCombinedRestUsage.get("create_index_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("document_index_action") - beforeCombinedRestUsage.get("document_index_action"), equalTo(4L)); + assertThat(combinedRestUsage.get("search_action") - beforeCombinedRestUsage.get("search_action"), equalTo(2L)); + assertThat(combinedRestUsage.get("refresh_action") - beforeCombinedRestUsage.get("refresh_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("cat_indices_action") - beforeCombinedRestUsage.get("cat_indices_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("nodes_info_action") - beforeCombinedRestUsage.get("nodes_info_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("nodes_stats_action") - beforeCombinedRestUsage.get("nodes_stats_action"), equalTo(1L)); + assertThat(combinedRestUsage.get("delete_index_action") - beforeCombinedRestUsage.get("delete_index_action"), equalTo(1L)); + + } + + public void testMetricsWithAll() throws IOException { + ResponseException exception = expectThrows(ResponseException.class, + () -> client().performRequest("GET", "_nodes/usage/_all,rest_actions")); + assertNotNull(exception); + assertThat(exception.getMessage(), containsString("\"type\":\"illegal_argument_exception\"," + + "\"reason\":\"request [_nodes/usage/_all,rest_actions] contains _all and individual metrics [_all,rest_actions]\"")); + } + +} diff --git a/docs/build.gradle b/docs/build.gradle index b0cac649c5cb2..b52c7dee94da1 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -152,6 +152,14 @@ buildRestTests.setups['host'] = ''' - set: {nodes.$master.http.publish_address: host} ''' +buildRestTests.setups['node'] = ''' + # Fetch the node name. We use the host of the master because we know there will always be a master. + - do: + cluster.state: {} + - is_true: master_node + - set: { master_node: node_name } +''' + // Used by scripted metric docs buildRestTests.setups['ledger'] = ''' - do: diff --git a/docs/reference/cluster/nodes-usage.asciidoc b/docs/reference/cluster/nodes-usage.asciidoc new file mode 100644 index 0000000000000..5bc57461c8dec --- /dev/null +++ b/docs/reference/cluster/nodes-usage.asciidoc @@ -0,0 +1,64 @@ +[[cluster-nodes-usage]] +== Nodes Feature Usage + +[float] +=== Nodes usage + +The cluster nodes usage API allows to retrieve information on the usage +of features for each node. + +[source,js] +-------------------------------------------------- +GET _nodes/nodeId1,nodeId2/usage +GET _nodes/usage +-------------------------------------------------- +// CONSOLE +// TEST[setup:node] +// TEST[s/nodeId1,nodeId2/\$node_name/] + +The first command retrieves usage of all the nodes in the cluster. The +second command selectively retrieves nodes usage of only `nodeId1` and +`nodeId2`. All the nodes selective options are explained +<>. + +[float] +[[rest-usage]] +==== REST actions usage information + +The `rest_actions` field in the response contains a map of the REST +actions classname with a count of the number of times that action has +been called on the node: + +[source,js] +-------------------------------------------------- +{ + "_nodes": { + "total": 1, + "successful": 1, + "failed": 0 + }, + "cluster_name": "my_cluster", + "nodes": { + "pQHNt5rXTTWNvUgOrdynKg": { + "timestamp": 1492553961812, <1> + "since": 1492553906606, <2> + "rest_actions": { + "org.elasticsearch.rest.action.admin.cluster.RestNodesUsageAction": 1, + "org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction": 1, + "org.elasticsearch.rest.action.document.RestGetAction": 1, + "org.elasticsearch.rest.action.search.RestSearchAction": 19, <3> + "org.elasticsearch.rest.action.admin.cluster.RestNodesInfoAction": 36 + } + } + } +} +-------------------------------------------------- +// TESTRESPONSE[s/"my_cluster"/$body.cluster_name/] +// TESTRESPONSE[s/"pQHNt5rXTTWNvUgOrdynKg"/\$node_name/] +// TESTRESPONSE[s/1492553961812/$body.$_path/] +// TESTRESPONSE[s/1492553906606/$body.$_path/] +// TESTRESPONSE[s/"rest_actions": [^}]+}/"rest_actions": $body.$_path/] +<1> Timestamp for when this nodes usage request was performed. +<2> Timestamp for when the usage information recording was started. This is +equivalent to the time that the node was started. +<3> Search action has been called 19 times for this node. \ No newline at end of file diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestDeleteSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestDeleteSearchTemplateAction.java index 61a394462f9c8..23b6c2869593a 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestDeleteSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestDeleteSearchTemplateAction.java @@ -39,6 +39,11 @@ public RestDeleteSearchTemplateAction(Settings settings, RestController controll controller.registerHandler(DELETE, "/_search/template/{id}", this); } + @Override + public String getName() { + return "delete_search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String id = request.param("id"); diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestGetSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestGetSearchTemplateAction.java index 7d1ed4b57a421..d2b534e01f224 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestGetSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestGetSearchTemplateAction.java @@ -50,6 +50,11 @@ public RestGetSearchTemplateAction(Settings settings, RestController controller) controller.registerHandler(GET, "/_search/template/{id}", this); } + @Override + public String getName() { + return "get_search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, NodeClient client) throws IOException { String id = request.param("id"); diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java index f8bac3236d40b..c730305747e0d 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java @@ -55,6 +55,11 @@ public RestMultiSearchTemplateAction(Settings settings, RestController controlle controller.registerHandler(POST, "/{index}/{type}/_msearch/template", this); } + @Override + public String getName() { + return "multi_search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { if (request.hasContentOrSourceParam() == false) { diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestPutSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestPutSearchTemplateAction.java index 83925f0ec03b6..2107741448475 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestPutSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestPutSearchTemplateAction.java @@ -42,6 +42,11 @@ public RestPutSearchTemplateAction(Settings settings, RestController controller) controller.registerHandler(PUT, "/_search/template/{id}", this); } + @Override + public String getName() { + return "put_search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { String id = request.param("id"); diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestRenderSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestRenderSearchTemplateAction.java index 6647bd4bd4522..d8c67839cb80f 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestRenderSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestRenderSearchTemplateAction.java @@ -42,6 +42,11 @@ public RestRenderSearchTemplateAction(Settings settings, RestController controll controller.registerHandler(POST, "/_render/template/{id}", this); } + @Override + public String getName() { + return "render_search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { // Creates the render template request diff --git a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java index 3e967fa4286c1..ed1e0d6f1d18e 100644 --- a/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java +++ b/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java @@ -85,6 +85,11 @@ public RestSearchTemplateAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_search/template", this); } + @Override + public String getName() { + return "search_template_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { if (request.hasContentOrSourceParam() == false) { diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestDeleteByQueryAction.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestDeleteByQueryAction.java index f906ef7660da8..3d3a706098bec 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestDeleteByQueryAction.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestDeleteByQueryAction.java @@ -40,6 +40,11 @@ public RestDeleteByQueryAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_delete_by_query", this); } + @Override + public String getName() { + return "delete_by_query_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return doPrepareRequest(request, client, false, false); diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestReindexAction.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestReindexAction.java index 6c16c31efb153..17c7cf0c197d5 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestReindexAction.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestReindexAction.java @@ -100,6 +100,11 @@ public RestReindexAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/_reindex", this); } + @Override + public String getName() { + return "reindex_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return doPrepareRequest(request, client, true, true); diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestRethrottleAction.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestRethrottleAction.java index 4aa46f1a07780..9eed89885b90f 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestRethrottleAction.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestRethrottleAction.java @@ -44,6 +44,11 @@ public RestRethrottleAction(Settings settings, RestController controller, Suppli controller.registerHandler(POST, "/_reindex/{taskId}/_rethrottle", this); } + @Override + public String getName() { + return "rethrottle_action"; + } + @Override public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException { RethrottleRequest internalRequest = new RethrottleRequest(); diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestUpdateByQueryAction.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestUpdateByQueryAction.java index 345b23bf64522..3ddd3618ab812 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestUpdateByQueryAction.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestUpdateByQueryAction.java @@ -45,6 +45,11 @@ public RestUpdateByQueryAction(Settings settings, RestController controller) { controller.registerHandler(POST, "/{index}/{type}/_update_by_query", this); } + @Override + public String getName() { + return "update_by_query_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { return doPrepareRequest(request, client, false, true); diff --git a/plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/ExampleCatAction.java b/plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/ExampleCatAction.java index d7f3f94c81854..bdfc51d7d3635 100644 --- a/plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/ExampleCatAction.java +++ b/plugins/jvm-example/src/main/java/org/elasticsearch/plugin/example/ExampleCatAction.java @@ -41,6 +41,11 @@ public ExampleCatAction(Settings settings, RestController controller, ExamplePlu controller.registerHandler(GET, "/_cat/configured_example", this); } + @Override + public String getName() { + return "example_cat_action"; + } + @Override protected RestChannelConsumer doCatRequest(final RestRequest request, final NodeClient client) { Table table = getTableWithHeader(request); diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestDeprecationHeaderRestAction.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestDeprecationHeaderRestAction.java index bc60b7aa57439..11dcfd76fa5ac 100644 --- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestDeprecationHeaderRestAction.java +++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestDeprecationHeaderRestAction.java @@ -75,6 +75,11 @@ public TestDeprecationHeaderRestAction(Settings settings, RestController control DEPRECATED_ENDPOINT, deprecationLogger); } + @Override + public String getName() { + return "test_deprecation_header_action"; + } + @SuppressWarnings("unchecked") // List casts @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestResponseHeaderRestAction.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestResponseHeaderRestAction.java index d99dd5d524525..c7411f7986992 100644 --- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestResponseHeaderRestAction.java +++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/TestResponseHeaderRestAction.java @@ -35,6 +35,11 @@ public TestResponseHeaderRestAction(Settings settings, RestController controller controller.registerHandler(RestRequest.Method.GET, "/_protected", this); } + @Override + public String getName() { + return "test_response_header_action"; + } + @Override public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { if ("password".equals(request.header("Secret"))) { diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.usage.json b/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.usage.json new file mode 100644 index 0000000000000..b066a0105530d --- /dev/null +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/nodes.usage.json @@ -0,0 +1,38 @@ +{ + "nodes.usage": { + "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-usage.html", + "methods": ["GET"], + "url": { + "path": "/_nodes/usage", + "paths": [ + "/_nodes/usage", + "/_nodes/{node_id}/usage", + "/_nodes/usage/{metric}", + "/_nodes/{node_id}/usage/{metric}" + ], + "parts": { + "metric" : { + "type" : "list", + "options" : ["_all", "rest_actions"], + "description" : "Limit the information returned to the specified metrics" + }, + "node_id": { + "type" : "list", + "description" : "A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes" + } + }, + "params": { + "human": { + "type": "boolean", + "description": "Whether to return time and byte values in human-readable format.", + "default": false + }, + "timeout": { + "type" : "time", + "description" : "Explicit operation timeout" + } + } + }, + "body": null + } +} \ No newline at end of file