Browse Source

Add tests/fix docs for nodes info API (#79223)

The docs for `GET _nodes/<node>/<metric>` omitted a couple of metrics
and indicated that this API returned dynamic stats rather than static
info. They also didn't mention that `_all` is a legal value, nor
did it give a way to suppress all metrics even though this is possible.

This commit adjusts the docs and adds tests to ensure that selecting
metrics works as expected and to ensure that there is a future-proof
legal way to suppress all metrics.

Closes #79187

Co-authored-by: James Rodewig <40268737+jrodewig@users.noreply.github.com>
David Turner 4 years ago
parent
commit
5767d51c2b

+ 21 - 9
docs/reference/cluster/nodes-info.asciidoc

@@ -46,18 +46,28 @@ comma-separated list, such as `http,ingest`.
 [%collapsible%open]
 .Valid values for `<metric>`
 ====
+`aggregations`::
+Information about the available types of aggregation.
+
 `http`::
-HTTP connection information.
+Information about the HTTP interface of this node.
+
+`indices`::
++
+--
+Node-level configuration related to indexing:
+
+* `total_indexing_buffer`: the maximum size of the indexing buffer on this node.
+--
 
 `ingest`::
 Information about ingest pipelines and processors.
 
 `jvm`::
-JVM stats, memory pool information, garbage collection, buffer pools, number of
-loaded/unloaded classes.
+JVM information, including its name, its version, and its configuration.
 
 `os`::
-Operating system stats, load average, mem, swap.
+Operating system information, including its name and version.
 
 `plugins`::
 +
@@ -74,23 +84,25 @@ process
 --
 
 `process`::
-Process statistics, memory consumption, cpu usage, open file descriptors.
+Process information, including the numeric process ID.
 
 `settings`::
 Lists all node settings in use as defined in the `elasticsearch.yml` file.
 
 `thread_pool`::
-Statistics about each thread pool, including current size, queue and rejected
-tasks
+Information about the configuration of each thread pool.
 
 `transport`::
-Transport statistics about sent and received bytes in cluster communication.
+Information about the transport interface of the node.
 ====
 
+If you use the full `GET /_nodes/<node_id>/<metric>` form of this API then you
+can also request the metric `_all` to retrieve all metrics, or you can request
+the metric `_none` to suppress all metrics and retrieve only the identity of
+the node.
 
 include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=node-id]
 
-
 [[cluster-nodes-info-api-response-body]]
 ==== {api-response-body-title}
 

+ 10 - 4
rest-api-spec/src/main/resources/rest-api-spec/api/nodes.info.json

@@ -46,9 +46,11 @@
                 "transport",
                 "http",
                 "plugins",
-                "ingest"
+                "ingest",
+                "indices",
+                "aggregations"
               ],
-              "description":"A comma-separated list of metrics you wish returned. Leave empty to return all."
+              "description":"A comma-separated list of metrics you wish returned. Leave empty to return all metrics."
             }
           }
         },
@@ -73,9 +75,13 @@
                 "transport",
                 "http",
                 "plugins",
-                "ingest"
+                "ingest",
+                "indices",
+                "aggregations",
+                "_all",
+                "_none"
               ],
-              "description":"A comma-separated list of metrics you wish returned. Leave empty to return all."
+              "description":"A comma-separated list of metrics you wish returned. Use `_all` to retrieve all metrics and `_none` to retrieve the node identity without any additional metrics."
             }
           }
         }

+ 480 - 0
rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/nodes.info/50_metrics.yml

@@ -0,0 +1,480 @@
+setup:
+  - skip:
+      features: [arbitrary_key]
+
+---
+"_all metrics":
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "_all"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_true:  nodes.$node_id.aggregations
+  - is_true:  nodes.$node_id.http
+  - is_true:  nodes.$node_id.ingest
+  - is_true:  nodes.$node_id.jvm
+  - is_true:  nodes.$node_id.modules
+  - is_true:  nodes.$node_id.os
+  - is_true:  nodes.$node_id.plugins
+  - is_true:  nodes.$node_id.process
+  - is_true:  nodes.$node_id.settings
+  - is_true:  nodes.$node_id.thread_pool
+  - is_true:  nodes.$node_id.total_indexing_buffer
+  - is_true:  nodes.$node_id.transport
+
+---
+"settings metric":
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "settings"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_true:  nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"os metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "os"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_true:  nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"process metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "process"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_true:  nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"jvm metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "jvm"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_true:  nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"thread_pool metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "thread_pool"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_true:  nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"transport metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "transport"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_true:  nodes.$node_id.transport
+
+---
+"http metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "http"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_true:  nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"plugins metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "plugins"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_true:  nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_true:  nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"ingest metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "ingest"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_true:  nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"indices metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "indices"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_true:  nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"aggregations metric":
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "aggregations"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_true:  nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"lists of metrics":
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "settings,os"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_true:  nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_true:  nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport
+
+---
+"no metrics":
+
+# Sometimes users just want to identify one or more nodes and not get any further detail. Today
+# Elasticsearch is lenient and ignores any unknown metrics, but for futureproofing we document
+# that `_none` can legitimately be used in this case.
+
+  - do:
+      nodes.info:
+        node_id: "_master"
+        metric: "_none"
+  - set:
+      nodes._arbitrary_key_: node_id
+
+  - is_true:  nodes.$node_id.attributes
+  - is_true:  nodes.$node_id.build_flavor
+  - is_true:  nodes.$node_id.build_hash
+  - is_true:  nodes.$node_id.build_type
+  - is_true:  nodes.$node_id.host
+  - is_true:  nodes.$node_id.ip
+  - is_true:  nodes.$node_id.name
+  - is_true:  nodes.$node_id.roles
+  - is_true:  nodes.$node_id.transport_address
+  - is_true:  nodes.$node_id.version
+
+  - is_false: nodes.$node_id.aggregations
+  - is_false: nodes.$node_id.http
+  - is_false: nodes.$node_id.ingest
+  - is_false: nodes.$node_id.jvm
+  - is_false: nodes.$node_id.modules
+  - is_false: nodes.$node_id.os
+  - is_false: nodes.$node_id.plugins
+  - is_false: nodes.$node_id.process
+  - is_false: nodes.$node_id.settings
+  - is_false: nodes.$node_id.thread_pool
+  - is_false: nodes.$node_id.total_indexing_buffer
+  - is_false: nodes.$node_id.transport

+ 1 - 5
server/src/main/java/org/elasticsearch/action/admin/cluster/node/info/NodesInfoRequest.java

@@ -143,7 +143,7 @@ public class NodesInfoRequest extends BaseNodesRequest<NodesInfoRequest> {
         AGGREGATIONS("aggregations"),
         INDICES("indices");
 
-        private String metricName;
+        private final String metricName;
 
         Metric(String name) {
             this.metricName = name;
@@ -153,10 +153,6 @@ public class NodesInfoRequest extends BaseNodesRequest<NodesInfoRequest> {
             return this.metricName;
         }
 
-        boolean containedIn(Set<String> metricNames) {
-            return metricNames.contains(this.metricName());
-        }
-
         public static Set<String> allMetrics() {
             return Arrays.stream(values()).map(Metric::metricName).collect(Collectors.toSet());
         }

+ 1 - 1
server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesInfoAction.java

@@ -87,7 +87,7 @@ public class RestNodesInfoAction extends BaseRestHandler {
             nodesInfoRequest.all();
         } else {
             nodesInfoRequest.clear();
-            // disregard unknown metrics
+            // disregard unknown metrics; TODO eschew this lenience?
             metrics.retainAll(ALLOWED_METRICS);
             nodesInfoRequest.addMetrics(metrics.toArray(String[]::new));
         }