From 4464fe1dc172f176862caf9d907042d92d9636ee Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Mon, 9 Jan 2012 18:01:41 +0200 Subject: [PATCH] Node Stats API: Add specific flags for stats, simplified REST paths, closes #1597. --- .../cluster/node/info/NodesInfoResponse.java | 10 +- .../admin/cluster/node/stats/NodeStats.java | 52 +++++- .../cluster/node/stats/NodesStatsRequest.java | 158 +++++++++++++++++- .../node/stats/NodesStatsResponse.java | 58 ++++++- .../node/stats/TransportNodesStatsAction.java | 32 +++- .../node/stats/NodesStatsRequestBuilder.java | 64 +++++++ .../node/service/NodeService.java | 15 +- .../node/stats/RestNodesStatsAction.java | 141 ++++++++++++---- 8 files changed, 474 insertions(+), 56 deletions(-) diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoResponse.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoResponse.java index f8857db44d8..8b6fc920eb0 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoResponse.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoResponse.java @@ -89,11 +89,13 @@ public class NodesInfoResponse extends NodesOperationResponse implemen } } - builder.startObject("attributes"); - for (Map.Entry attr : nodeInfo.node().attributes().entrySet()) { - builder.field(attr.getKey(), attr.getValue()); + if (!nodeInfo.node().attributes().isEmpty()) { + builder.startObject("attributes"); + for (Map.Entry attr : nodeInfo.node().attributes().entrySet()) { + builder.field(attr.getKey(), attr.getValue()); + } + builder.endObject(); } - builder.endObject(); if (nodeInfo.settings() != null) { diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java index f7158fc668c..85008b36554 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStats.java @@ -36,32 +36,41 @@ import java.io.IOException; /** * Node statistics (static, does not change over time). - * - * */ public class NodeStats extends NodeOperationResponse { + @Nullable + private String hostname; + + @Nullable private NodeIndicesStats indices; + @Nullable private OsStats os; + @Nullable private ProcessStats process; + @Nullable private JvmStats jvm; + @Nullable private NetworkStats network; + @Nullable private TransportStats transport; + @Nullable private HttpStats http; NodeStats() { } - public NodeStats(DiscoveryNode node, NodeIndicesStats indices, - OsStats os, ProcessStats process, JvmStats jvm, NetworkStats network, - TransportStats transport, @Nullable HttpStats http) { + public NodeStats(DiscoveryNode node, @Nullable String hostname, @Nullable NodeIndicesStats indices, + @Nullable OsStats os, @Nullable ProcessStats process, @Nullable JvmStats jvm, @Nullable NetworkStats network, + @Nullable TransportStats transport, @Nullable HttpStats http) { super(node); + this.hostname = hostname; this.indices = indices; this.os = os; this.process = process; @@ -71,9 +80,20 @@ public class NodeStats extends NodeOperationResponse { this.http = http; } + @Nullable + public String hostname() { + return this.hostname; + } + + @Nullable + public String getHostname() { + return this.hostname; + } + /** * Indices level stats. */ + @Nullable public NodeIndicesStats indices() { return this.indices; } @@ -81,6 +101,7 @@ public class NodeStats extends NodeOperationResponse { /** * Indices level stats. */ + @Nullable public NodeIndicesStats getIndices() { return indices(); } @@ -88,6 +109,7 @@ public class NodeStats extends NodeOperationResponse { /** * Operating System level statistics. */ + @Nullable public OsStats os() { return this.os; } @@ -95,6 +117,7 @@ public class NodeStats extends NodeOperationResponse { /** * Operating System level statistics. */ + @Nullable public OsStats getOs() { return os(); } @@ -102,6 +125,7 @@ public class NodeStats extends NodeOperationResponse { /** * Process level statistics. */ + @Nullable public ProcessStats process() { return process; } @@ -109,6 +133,7 @@ public class NodeStats extends NodeOperationResponse { /** * Process level statistics. */ + @Nullable public ProcessStats getProcess() { return process(); } @@ -116,6 +141,7 @@ public class NodeStats extends NodeOperationResponse { /** * JVM level statistics. */ + @Nullable public JvmStats jvm() { return jvm; } @@ -123,6 +149,7 @@ public class NodeStats extends NodeOperationResponse { /** * JVM level statistics. */ + @Nullable public JvmStats getJvm() { return jvm(); } @@ -130,6 +157,7 @@ public class NodeStats extends NodeOperationResponse { /** * Network level statistics. */ + @Nullable public NetworkStats network() { return network; } @@ -137,22 +165,27 @@ public class NodeStats extends NodeOperationResponse { /** * Network level statistics. */ + @Nullable public NetworkStats getNetwork() { return network(); } + @Nullable public TransportStats transport() { return this.transport; } + @Nullable public TransportStats getTransport() { return transport(); } + @Nullable public HttpStats http() { return this.http; } + @Nullable public HttpStats getHttp() { return http(); } @@ -166,6 +199,9 @@ public class NodeStats extends NodeOperationResponse { @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); + if (in.readBoolean()) { + hostname = in.readUTF(); + } if (in.readBoolean()) { indices = NodeIndicesStats.readIndicesStats(in); } @@ -192,6 +228,12 @@ public class NodeStats extends NodeOperationResponse { @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); + if (hostname == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + out.writeUTF(hostname); + } if (indices == null) { out.writeBoolean(false); } else { diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java index 42fbf59fc8c..5cefb6208c3 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsRequest.java @@ -20,14 +20,24 @@ package org.elasticsearch.action.admin.cluster.node.stats; import org.elasticsearch.action.support.nodes.NodesOperationRequest; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; /** * A request to get node (cluster) level stats. - * - * */ public class NodesStatsRequest extends NodesOperationRequest { + private boolean indices = true; + private boolean os; + private boolean process; + private boolean jvm; + private boolean network; + private boolean transport; + private boolean http; + protected NodesStatsRequest() { } @@ -38,4 +48,148 @@ public class NodesStatsRequest extends NodesOperationRequest { public NodesStatsRequest(String... nodesIds) { super(nodesIds); } + + /** + * Clears all the request flags. + */ + public NodesStatsRequest clear() { + this.indices = false; + this.os = false; + this.process = false; + this.jvm = false; + this.network = false; + this.transport = false; + this.http = false; + return this; + } + + /** + * Should indices stats be returned. + */ + public boolean indices() { + return this.indices; + } + + /** + * Should indices stats be returned. + */ + public NodesStatsRequest indices(boolean indices) { + this.indices = indices; + return this; + } + + /** + * Should the node OS be returned. + */ + public boolean os() { + return this.os; + } + + /** + * Should the node OS be returned. + */ + public NodesStatsRequest os(boolean os) { + this.os = os; + return this; + } + + /** + * Should the node Process be returned. + */ + public boolean process() { + return this.process; + } + + /** + * Should the node Process be returned. + */ + public NodesStatsRequest process(boolean process) { + this.process = process; + return this; + } + + /** + * Should the node JVM be returned. + */ + public boolean jvm() { + return this.jvm; + } + + /** + * Should the node JVM be returned. + */ + public NodesStatsRequest jvm(boolean jvm) { + this.jvm = jvm; + return this; + } + + /** + * Should the node Network be returned. + */ + public boolean network() { + return this.network; + } + + /** + * Should the node Network be returned. + */ + public NodesStatsRequest network(boolean network) { + this.network = network; + return this; + } + + /** + * Should the node Transport be returned. + */ + public boolean transport() { + return this.transport; + } + + /** + * Should the node Transport be returned. + */ + public NodesStatsRequest transport(boolean transport) { + this.transport = transport; + return this; + } + + /** + * Should the node HTTP be returned. + */ + public boolean http() { + return this.http; + } + + /** + * Should the node HTTP be returned. + */ + public NodesStatsRequest http(boolean http) { + this.http = http; + return this; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + indices = in.readBoolean(); + os = in.readBoolean(); + process = in.readBoolean(); + jvm = in.readBoolean(); + network = in.readBoolean(); + transport = in.readBoolean(); + http = in.readBoolean(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeBoolean(indices); + out.writeBoolean(os); + out.writeBoolean(process); + out.writeBoolean(jvm); + out.writeBoolean(network); + out.writeBoolean(transport); + out.writeBoolean(http); + } + } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsResponse.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsResponse.java index 39d451b21b3..3db6edd9830 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsResponse.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/NodesStatsResponse.java @@ -23,13 +23,16 @@ import org.elasticsearch.action.support.nodes.NodesOperationResponse; 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 java.io.IOException; +import java.util.Map; /** * */ -public class NodesStatsResponse extends NodesOperationResponse { +public class NodesStatsResponse extends NodesOperationResponse implements ToXContent { NodesStatsResponse() { } @@ -55,4 +58,57 @@ public class NodesStatsResponse extends NodesOperationResponse { node.writeTo(out); } } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("cluster_name", clusterName().value()); + + builder.startObject("nodes"); + for (NodeStats nodeStats : this) { + builder.startObject(nodeStats.node().id(), XContentBuilder.FieldCaseConversion.NONE); + + builder.field("name", nodeStats.node().name(), XContentBuilder.FieldCaseConversion.NONE); + builder.field("transport_address", nodeStats.node().address().toString()); + + if (nodeStats.hostname() != null) { + builder.field("hostname", nodeStats.hostname(), XContentBuilder.FieldCaseConversion.NONE); + } + + if (!nodeStats.node().attributes().isEmpty()) { + builder.startObject("attributes"); + for (Map.Entry attr : nodeStats.node().attributes().entrySet()) { + builder.field(attr.getKey(), attr.getValue()); + } + builder.endObject(); + } + + if (nodeStats.indices() != null) { + nodeStats.indices().toXContent(builder, params); + } + + if (nodeStats.os() != null) { + nodeStats.os().toXContent(builder, params); + } + if (nodeStats.process() != null) { + nodeStats.process().toXContent(builder, params); + } + if (nodeStats.jvm() != null) { + nodeStats.jvm().toXContent(builder, params); + } + if (nodeStats.network() != null) { + nodeStats.network().toXContent(builder, params); + } + if (nodeStats.transport() != null) { + nodeStats.transport().toXContent(builder, params); + } + if (nodeStats.http() != null) { + nodeStats.http().toXContent(builder, params); + } + + builder.endObject(); + } + builder.endObject(); + + return builder; + } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java index 6a16c298404..3ccb8a5dc65 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java @@ -27,11 +27,14 @@ import org.elasticsearch.action.support.nodes.TransportNodesOperationAction; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.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.node.service.NodeService; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; +import java.io.IOException; import java.util.List; import java.util.concurrent.atomic.AtomicReferenceArray; @@ -84,7 +87,7 @@ public class TransportNodesStatsAction extends TransportNodesOperationAction listener) { client.nodesStats(request, listener); diff --git a/src/main/java/org/elasticsearch/node/service/NodeService.java b/src/main/java/org/elasticsearch/node/service/NodeService.java index 9e456d7ac65..37f94a44482 100644 --- a/src/main/java/org/elasticsearch/node/service/NodeService.java +++ b/src/main/java/org/elasticsearch/node/service/NodeService.java @@ -122,9 +122,22 @@ public class NodeService extends AbstractComponent { public NodeStats stats() { // for indices stats we want to include previous allocated shards stats as well (it will // only be applied to the sensible ones to use, like refresh/merge/flush/indexing stats) - return new NodeStats(clusterService.state().nodes().localNode(), indicesService.stats(true), + return new NodeStats(clusterService.state().nodes().localNode(), hostname, indicesService.stats(true), monitorService.osService().stats(), monitorService.processService().stats(), monitorService.jvmService().stats(), monitorService.networkService().stats(), transportService.stats(), httpServer == null ? null : httpServer.stats()); } + + public NodeStats stats(boolean indices, boolean os, boolean process, boolean jvm, boolean network, boolean transport, boolean http) { + // for indices stats we want to include previous allocated shards stats as well (it will + // only be applied to the sensible ones to use, like refresh/merge/flush/indexing stats) + return new NodeStats(clusterService.state().nodes().localNode(), hostname, + indices ? indicesService.stats(true) : null, + os ? monitorService.osService().stats() : null, + process ? monitorService.processService().stats() : null, + jvm ? monitorService.jvmService().stats() : null, + network ? monitorService.networkService().stats() : null, + transport ? transportService.stats() : null, + http ? (httpServer == null ? null : httpServer.stats()) : null); + } } diff --git a/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java b/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java index 19d5ecf45fe..5aed0920645 100644 --- a/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java +++ b/src/main/java/org/elasticsearch/rest/action/admin/cluster/node/stats/RestNodesStatsAction.java @@ -20,7 +20,6 @@ package org.elasticsearch.rest.action.admin.cluster.node.stats; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequest; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; import org.elasticsearch.client.Client; @@ -43,54 +42,59 @@ public class RestNodesStatsAction extends BaseRestHandler { super(settings, client); controller.registerHandler(RestRequest.Method.GET, "/_cluster/nodes/stats", this); controller.registerHandler(RestRequest.Method.GET, "/_cluster/nodes/{nodeId}/stats", this); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats", this); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats", this); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/indices", new RestIndicesHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/indices", new RestIndicesHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/os", new RestOsHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/os", new RestOsHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/process", new RestProcessHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/process", new RestProcessHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/jvm", new RestJvmHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/jvm", new RestJvmHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/network", new RestNetworkHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/network", new RestNetworkHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/transport", new RestTransportHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/transport", new RestTransportHandler()); + + controller.registerHandler(RestRequest.Method.GET, "/_nodes/stats/http", new RestHttpHandler()); + controller.registerHandler(RestRequest.Method.GET, "/_nodes/{nodeId}/stats/http", new RestHttpHandler()); } @Override public void handleRequest(final RestRequest request, final RestChannel channel) { String[] nodesIds = RestActions.splitNodes(request.param("nodeId")); NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(nodesIds); + boolean clear = request.paramAsBoolean("clear", false); + if (clear) { + nodesStatsRequest.clear(); + } + nodesStatsRequest.indices(request.paramAsBoolean("indices", nodesStatsRequest.indices())); + nodesStatsRequest.os(request.paramAsBoolean("os", nodesStatsRequest.os())); + nodesStatsRequest.process(request.paramAsBoolean("process", nodesStatsRequest.process())); + nodesStatsRequest.jvm(request.paramAsBoolean("jvm", nodesStatsRequest.jvm())); + nodesStatsRequest.network(request.paramAsBoolean("network", nodesStatsRequest.network())); + nodesStatsRequest.transport(request.paramAsBoolean("transport", nodesStatsRequest.transport())); + nodesStatsRequest.http(request.paramAsBoolean("http", nodesStatsRequest.http())); + executeNodeStats(request, channel, nodesStatsRequest); + } + + void executeNodeStats(final RestRequest request, final RestChannel channel, final NodesStatsRequest nodesStatsRequest) { nodesStatsRequest.listenerThreaded(false); client.admin().cluster().nodesStats(nodesStatsRequest, new ActionListener() { @Override - public void onResponse(NodesStatsResponse result) { + public void onResponse(NodesStatsResponse response) { try { XContentBuilder builder = RestXContentBuilder.restContentBuilder(request); builder.startObject(); - builder.field("cluster_name", result.clusterName().value()); - - builder.startObject("nodes"); - for (NodeStats nodeStats : result) { - builder.startObject(nodeStats.node().id(), XContentBuilder.FieldCaseConversion.NONE); - - builder.field("name", nodeStats.node().name(), XContentBuilder.FieldCaseConversion.NONE); - - if (nodeStats.indices() != null) { - nodeStats.indices().toXContent(builder, request); - } - - if (nodeStats.os() != null) { - nodeStats.os().toXContent(builder, request); - } - if (nodeStats.process() != null) { - nodeStats.process().toXContent(builder, request); - } - if (nodeStats.jvm() != null) { - nodeStats.jvm().toXContent(builder, request); - } - if (nodeStats.network() != null) { - nodeStats.network().toXContent(builder, request); - } - if (nodeStats.transport() != null) { - nodeStats.transport().toXContent(builder, request); - } - if (nodeStats.http() != null) { - nodeStats.http().toXContent(builder, request); - } - - builder.endObject(); - } - builder.endObject(); - + response.toXContent(builder, request); builder.endObject(); channel.sendResponse(new XContentRestResponse(request, RestStatus.OK, builder)); } catch (Exception e) { @@ -108,4 +112,67 @@ public class RestNodesStatsAction extends BaseRestHandler { } }); } + + class RestIndicesHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().indices(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestOsHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().os(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestProcessHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().process(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestJvmHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().jvm(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestNetworkHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().network(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestTransportHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().transport(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } + + class RestHttpHandler implements RestHandler { + @Override + public void handleRequest(final RestRequest request, final RestChannel channel) { + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(RestActions.splitNodes(request.param("nodeId"))); + nodesStatsRequest.clear().http(true); + executeNodeStats(request, channel, nodesStatsRequest); + } + } } \ No newline at end of file