|
| 1 | +/* |
| 2 | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one |
| 3 | + * or more contributor license agreements. Licensed under the "Elastic License |
| 4 | + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side |
| 5 | + * Public License v 1"; you may not use this file except in compliance with, at |
| 6 | + * your election, the "Elastic License 2.0", the "GNU Affero General Public |
| 7 | + * License v3.0 only", or the "Server Side Public License, v 1". |
| 8 | + */ |
| 9 | + |
| 10 | +package org.elasticsearch.rest.action.cat; |
| 11 | + |
| 12 | +import org.elasticsearch.action.FailedNodeException; |
| 13 | +import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; |
| 14 | +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequest; |
| 15 | +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestParameters; |
| 16 | +import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; |
| 17 | +import org.elasticsearch.client.internal.node.NodeClient; |
| 18 | +import org.elasticsearch.common.Table; |
| 19 | +import org.elasticsearch.common.regex.Regex; |
| 20 | +import org.elasticsearch.common.unit.ByteSizeValue; |
| 21 | +import org.elasticsearch.indices.breaker.CircuitBreakerStats; |
| 22 | +import org.elasticsearch.rest.RestRequest; |
| 23 | +import org.elasticsearch.rest.RestResponse; |
| 24 | +import org.elasticsearch.rest.Scope; |
| 25 | +import org.elasticsearch.rest.ServerlessScope; |
| 26 | +import org.elasticsearch.rest.action.RestResponseListener; |
| 27 | + |
| 28 | +import java.util.List; |
| 29 | +import java.util.Set; |
| 30 | + |
| 31 | +import static org.elasticsearch.common.util.set.Sets.addToCopy; |
| 32 | +import static org.elasticsearch.rest.RestRequest.Method.GET; |
| 33 | + |
| 34 | +@ServerlessScope(Scope.INTERNAL) |
| 35 | +public class RestCatCircuitBreakerAction extends AbstractCatAction { |
| 36 | + |
| 37 | + private static final Set<String> RESPONSE_PARAMS = addToCopy(AbstractCatAction.RESPONSE_PARAMS, "circuit_breaker_patterns"); |
| 38 | + |
| 39 | + @Override |
| 40 | + public String getName() { |
| 41 | + return "cat_circuitbreaker_action"; |
| 42 | + } |
| 43 | + |
| 44 | + @Override |
| 45 | + public List<Route> routes() { |
| 46 | + return List.of(new Route(GET, "/_cat/circuit_breaker"), new Route(GET, "/_cat/circuit_breaker/{circuit_breaker_patterns}")); |
| 47 | + } |
| 48 | + |
| 49 | + @Override |
| 50 | + protected void documentation(StringBuilder sb) { |
| 51 | + sb.append("/_cat/circuit_breaker\n"); |
| 52 | + sb.append("/_cat/circuit_breaker/{circuit_breaker_patterns}\n"); |
| 53 | + } |
| 54 | + |
| 55 | + @Override |
| 56 | + protected Set<String> responseParams() { |
| 57 | + return RESPONSE_PARAMS; |
| 58 | + } |
| 59 | + |
| 60 | + @Override |
| 61 | + protected RestChannelConsumer doCatRequest(RestRequest request, NodeClient client) { |
| 62 | + NodesStatsRequest nodesStatsRequest = new NodesStatsRequest(); // Empty nodes array sends request to all nodes. |
| 63 | + nodesStatsRequest.clear().addMetric(NodesStatsRequestParameters.Metric.BREAKER); |
| 64 | + |
| 65 | + return channel -> client.admin().cluster().nodesStats(nodesStatsRequest, new RestResponseListener<>(channel) { |
| 66 | + @Override |
| 67 | + public RestResponse buildResponse(final NodesStatsResponse nodesStatsResponse) throws Exception { |
| 68 | + RestResponse response = RestTable.buildResponse(buildTable(request, nodesStatsResponse), channel); |
| 69 | + if (nodesStatsResponse.failures().isEmpty() == false) { |
| 70 | + response.addHeader("Warning", "Partial success, missing info from " + nodesStatsResponse.failures().size() + " nodes."); |
| 71 | + } |
| 72 | + return response; |
| 73 | + } |
| 74 | + }); |
| 75 | + } |
| 76 | + |
| 77 | + @Override |
| 78 | + protected Table getTableWithHeader(RestRequest request) { |
| 79 | + Table table = new Table(); |
| 80 | + table.startHeaders(); |
| 81 | + table.addCell("node_id", "default:true;alias:id;desc:persistent node id"); |
| 82 | + table.addCell("node_name", "default:false;alias:nn;desc:node name"); |
| 83 | + table.addCell("breaker", "default:true;alias:br;desc:breaker name"); |
| 84 | + table.addCell("limit", "default:true;alias:l;desc:limit size"); |
| 85 | + table.addCell("limit_bytes", "default:false;alias:lb;desc:limit size in bytes"); |
| 86 | + table.addCell("estimated", "default:true;alias:e;desc:estimated size"); |
| 87 | + table.addCell("estimated_bytes", "default:false;alias:eb;desc:estimated size in bytes"); |
| 88 | + table.addCell("tripped", "default:true;alias:t;desc:tripped count"); |
| 89 | + table.addCell("overhead", "default:false;alias:o;desc:overhead"); |
| 90 | + table.endHeaders(); |
| 91 | + return table; |
| 92 | + } |
| 93 | + |
| 94 | + private Table buildTable(RestRequest request, NodesStatsResponse nodesStatsResponse) { |
| 95 | + final Table table = getTableWithHeader(request); |
| 96 | + final String[] circuitBreakers = request.paramAsStringArray("circuit_breaker_patterns", new String[] { "*" }); |
| 97 | + |
| 98 | + for (final NodeStats nodeStats : nodesStatsResponse.getNodes()) { |
| 99 | + if (nodeStats.getBreaker() == null) { |
| 100 | + continue; |
| 101 | + } |
| 102 | + for (final CircuitBreakerStats circuitBreakerStats : nodeStats.getBreaker().getAllStats()) { |
| 103 | + if (Regex.simpleMatch(circuitBreakers, circuitBreakerStats.getName()) == false) { |
| 104 | + continue; |
| 105 | + } |
| 106 | + table.startRow(); |
| 107 | + table.addCell(nodeStats.getNode().getId()); |
| 108 | + table.addCell(nodeStats.getNode().getName()); |
| 109 | + table.addCell(circuitBreakerStats.getName()); |
| 110 | + table.addCell(ByteSizeValue.ofBytes(circuitBreakerStats.getLimit())); |
| 111 | + table.addCell(circuitBreakerStats.getLimit()); |
| 112 | + table.addCell(ByteSizeValue.ofBytes(circuitBreakerStats.getEstimated())); |
| 113 | + table.addCell(circuitBreakerStats.getEstimated()); |
| 114 | + table.addCell(circuitBreakerStats.getTrippedCount()); |
| 115 | + table.addCell(circuitBreakerStats.getOverhead()); |
| 116 | + table.endRow(); |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + for (final FailedNodeException errors : nodesStatsResponse.failures()) { |
| 121 | + table.startRow(); |
| 122 | + table.addCell(errors.nodeId()); |
| 123 | + table.addCell("N/A"); |
| 124 | + table.addCell(errors.getMessage()); |
| 125 | + table.addCell("N/A"); |
| 126 | + table.addCell("N/A"); |
| 127 | + table.addCell("N/A"); |
| 128 | + table.addCell("N/A"); |
| 129 | + table.addCell("N/A"); |
| 130 | + table.addCell("N/A"); |
| 131 | + table.endRow(); |
| 132 | + } |
| 133 | + |
| 134 | + return table; |
| 135 | + } |
| 136 | +} |
0 commit comments