|
| 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 | + * you may not use this file except in compliance with the Elastic License. |
| 5 | + */ |
| 6 | +package org.elasticsearch.xpack.ml.rest.cat; |
| 7 | + |
| 8 | +import org.elasticsearch.client.node.NodeClient; |
| 9 | +import org.elasticsearch.cluster.node.DiscoveryNode; |
| 10 | +import org.elasticsearch.common.Strings; |
| 11 | +import org.elasticsearch.common.Table; |
| 12 | +import org.elasticsearch.common.unit.TimeValue; |
| 13 | +import org.elasticsearch.rest.RestController; |
| 14 | +import org.elasticsearch.rest.RestRequest; |
| 15 | +import org.elasticsearch.rest.RestResponse; |
| 16 | +import org.elasticsearch.rest.action.RestResponseListener; |
| 17 | +import org.elasticsearch.rest.action.cat.AbstractCatAction; |
| 18 | +import org.elasticsearch.rest.action.cat.RestTable; |
| 19 | +import org.elasticsearch.xpack.core.ml.action.GetDatafeedsStatsAction; |
| 20 | +import org.elasticsearch.xpack.core.ml.datafeed.DatafeedConfig; |
| 21 | +import org.elasticsearch.xpack.core.ml.datafeed.DatafeedTimingStats; |
| 22 | + |
| 23 | +import static org.elasticsearch.rest.RestRequest.Method.GET; |
| 24 | + |
| 25 | +public class RestCatDatafeedsAction extends AbstractCatAction { |
| 26 | + |
| 27 | + public RestCatDatafeedsAction(RestController controller) { |
| 28 | + controller.registerHandler(GET, "_cat/ml/datafeeds/{" + DatafeedConfig.ID.getPreferredName() + "}", this); |
| 29 | + controller.registerHandler(GET, "_cat/ml/datafeeds", this); |
| 30 | + } |
| 31 | + |
| 32 | + @Override |
| 33 | + public String getName() { |
| 34 | + return "cat_ml_get_datafeeds_action"; |
| 35 | + } |
| 36 | + |
| 37 | + @Override |
| 38 | + protected RestChannelConsumer doCatRequest(RestRequest restRequest, NodeClient client) { |
| 39 | + String datafeedId = restRequest.param(DatafeedConfig.ID.getPreferredName()); |
| 40 | + if (Strings.isNullOrEmpty(datafeedId)) { |
| 41 | + datafeedId = GetDatafeedsStatsAction.ALL; |
| 42 | + } |
| 43 | + GetDatafeedsStatsAction.Request request = new GetDatafeedsStatsAction.Request(datafeedId); |
| 44 | + request.setAllowNoDatafeeds(restRequest.paramAsBoolean(GetDatafeedsStatsAction.Request.ALLOW_NO_DATAFEEDS.getPreferredName(), |
| 45 | + request.allowNoDatafeeds())); |
| 46 | + return channel -> client.execute(GetDatafeedsStatsAction.INSTANCE, request, new RestResponseListener<>(channel) { |
| 47 | + @Override |
| 48 | + public RestResponse buildResponse(GetDatafeedsStatsAction.Response getDatafeedsStatsRespons) throws Exception { |
| 49 | + return RestTable.buildResponse(buildTable(restRequest, getDatafeedsStatsRespons), channel); |
| 50 | + } |
| 51 | + }); |
| 52 | + } |
| 53 | + |
| 54 | + @Override |
| 55 | + protected void documentation(StringBuilder sb) { |
| 56 | + sb.append("/_cat/ml/datafeeds\n"); |
| 57 | + sb.append("/_cat/ml/datafeeds/{datafeed_id}\n"); |
| 58 | + } |
| 59 | + |
| 60 | + @Override |
| 61 | + protected Table getTableWithHeader(RestRequest request) { |
| 62 | + Table table = new Table(); |
| 63 | + table.startHeaders(); |
| 64 | + |
| 65 | + // Datafeed Info |
| 66 | + table.addCell("id", TableColumnAttributeBuilder.builder().setDescription("the datafeed_id").build()); |
| 67 | + table.addCell("state", TableColumnAttributeBuilder.builder() |
| 68 | + .setDescription("the datafeed state") |
| 69 | + .setAliases("s") |
| 70 | + .setTextAlignment(TableColumnAttributeBuilder.TextAlign.RIGHT) |
| 71 | + .build()); |
| 72 | + table.addCell("assignment_explanation", |
| 73 | + TableColumnAttributeBuilder.builder("why the datafeed is or is not assigned to a node", false) |
| 74 | + .setAliases("ae") |
| 75 | + .build()); |
| 76 | + |
| 77 | + // Timing stats |
| 78 | + table.addCell("bucket.count", |
| 79 | + TableColumnAttributeBuilder.builder("bucket count") |
| 80 | + .setAliases("bc", "bucketCount") |
| 81 | + .build()); |
| 82 | + table.addCell("search.count", |
| 83 | + TableColumnAttributeBuilder.builder("number of searches ran by the datafeed") |
| 84 | + .setAliases("sc", "searchCount") |
| 85 | + .build()); |
| 86 | + table.addCell("search.time", |
| 87 | + TableColumnAttributeBuilder.builder("the total search time", false) |
| 88 | + .setAliases("st", "searchTime") |
| 89 | + .build()); |
| 90 | + table.addCell("search.bucket_avg", |
| 91 | + TableColumnAttributeBuilder.builder("the average search time per bucket (millisecond)", false) |
| 92 | + .setAliases("sba", "bucketTimeMin") |
| 93 | + .build()); |
| 94 | + table.addCell("search.exp_avg_hour", |
| 95 | + TableColumnAttributeBuilder.builder("the exponential average search time per hour (millisecond)", false) |
| 96 | + .setAliases("seah", "searchExpAvgHour") |
| 97 | + .build()); |
| 98 | + |
| 99 | + //Node info |
| 100 | + table.addCell("node.id", |
| 101 | + TableColumnAttributeBuilder.builder("id of the assigned node", false) |
| 102 | + .setAliases("ni", "nodeId") |
| 103 | + .build()); |
| 104 | + table.addCell("node.name", |
| 105 | + TableColumnAttributeBuilder.builder("name of the assigned node", false) |
| 106 | + .setAliases("nn", "nodeName") |
| 107 | + .build()); |
| 108 | + table.addCell("node.ephemeral_id", |
| 109 | + TableColumnAttributeBuilder.builder("ephemeral id of the assigned node", false) |
| 110 | + .setAliases("ne", "nodeEphemeralId") |
| 111 | + .build()); |
| 112 | + table.addCell("node.address", |
| 113 | + TableColumnAttributeBuilder.builder("network address of the assigned node", false) |
| 114 | + .setAliases("na", "nodeAddress") |
| 115 | + .build()); |
| 116 | + |
| 117 | + table.endHeaders(); |
| 118 | + return table; |
| 119 | + } |
| 120 | + |
| 121 | + private Table buildTable(RestRequest request, GetDatafeedsStatsAction.Response dfStats) { |
| 122 | + Table table = getTableWithHeader(request); |
| 123 | + dfStats.getResponse().results().forEach(df -> { |
| 124 | + table.startRow(); |
| 125 | + table.addCell(df.getDatafeedId()); |
| 126 | + table.addCell(df.getDatafeedState().toString()); |
| 127 | + table.addCell(df.getAssignmentExplanation()); |
| 128 | + |
| 129 | + DatafeedTimingStats timingStats = df.getTimingStats(); |
| 130 | + table.addCell(timingStats == null ? 0 : timingStats.getBucketCount()); |
| 131 | + table.addCell(timingStats == null ? 0 : timingStats.getSearchCount()); |
| 132 | + table.addCell(timingStats == null ? |
| 133 | + TimeValue.timeValueMillis(0) : |
| 134 | + TimeValue.timeValueMillis((long)timingStats.getTotalSearchTimeMs())); |
| 135 | + table.addCell(timingStats == null || timingStats.getBucketCount() == 0 ? 0.0 : timingStats.getAvgSearchTimePerBucketMs()); |
| 136 | + table.addCell(timingStats == null ? 0.0 : timingStats.getExponentialAvgSearchTimePerHourMs()); |
| 137 | + |
| 138 | + DiscoveryNode node = df.getNode(); |
| 139 | + table.addCell(node == null ? null : node.getId()); |
| 140 | + table.addCell(node == null ? null : node.getName()); |
| 141 | + table.addCell(node == null ? null : node.getEphemeralId()); |
| 142 | + table.addCell(node == null ? null : node.getAddress().toString()); |
| 143 | + |
| 144 | + table.endRow(); |
| 145 | + }); |
| 146 | + return table; |
| 147 | + } |
| 148 | +} |
0 commit comments