From e2d0daa870e6b1d6c2bff666289d1dde3d4b44c0 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Tue, 21 Aug 2018 11:21:39 -0500 Subject: [PATCH 01/11] HLRC: Adding pojos for get job stats HLRC: Adding pojos for job stats request --- .../protocol/xpack/ml/NodeAttributes.java | 114 ++++++++++++ .../xpack/ml/job/config/JobState.java | 39 ++++ .../xpack/ml/job/stats/ForecastStats.java | 127 +++++++++++++ .../protocol/xpack/ml/job/stats/JobStats.java | 172 ++++++++++++++++++ .../xpack/ml/job/stats/SimpleStats.java | 118 ++++++++++++ .../xpack/ml/NodeAttributesTests.java | 40 ++++ .../ml/job/stats/ForecastStatsTests.java | 80 ++++++++ .../xpack/ml/job/stats/JobStatsTests.java | 62 +++++++ .../xpack/ml/job/stats/SimpleStatsTests.java | 43 +++++ 9 files changed, 795 insertions(+) create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java new file mode 100644 index 0000000000000..97ed1b9bd8871 --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java @@ -0,0 +1,114 @@ +package org.elasticsearch.protocol.xpack.ml; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; + +public class NodeAttributes implements ToXContentObject { + + public static final ParseField ID = new ParseField("id"); + public static final ParseField NAME = new ParseField("name"); + public static final ParseField EPHEMERAL_ID = new ParseField("ephemeral_id"); + public static final ParseField TRANSPORT_ADDRESS = new ParseField("transport_address"); + public static final ParseField ATTRIBUTES = new ParseField("attributes"); + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("node", true, + (a) -> { + int i = 0; + String id = (String) a[i++]; + String name = (String) a[i++]; + String ephemeralId = (String) a[i++]; + String transportAddress = (String) a[i++]; + Map attributes = (Map) a[i]; + return new NodeAttributes(id, name, ephemeralId, transportAddress, attributes); + }); + + static { + PARSER.declareString(ConstructingObjectParser.constructorArg(), ID); + PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME); + PARSER.declareString(ConstructingObjectParser.constructorArg(), EPHEMERAL_ID); + PARSER.declareString(ConstructingObjectParser.constructorArg(), TRANSPORT_ADDRESS); + PARSER.declareField(ConstructingObjectParser.constructorArg(), + (p, c) -> p.mapStrings(), + ATTRIBUTES, + ObjectParser.ValueType.OBJECT); + } + + private final String id; + private final String name; + private final String ephemeralId; + private final String transportAddress; + private final Map attributes; + + public NodeAttributes(String id, String name, String ephemeralId, String transportAddress, Map attributes) { + this.id = id; + this.name = name; + this.ephemeralId = ephemeralId; + this.transportAddress = transportAddress; + this.attributes = Collections.unmodifiableMap(attributes); + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getEphemeralId() { + return ephemeralId; + } + + public String getTransportAddress() { + return transportAddress; + } + + public Map getAttributes() { + return attributes; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(ID.getPreferredName(), id); + builder.field(NAME.getPreferredName(), name); + builder.field(EPHEMERAL_ID.getPreferredName(), ephemeralId); + builder.field(TRANSPORT_ADDRESS.getPreferredName(), transportAddress); + builder.field(ATTRIBUTES.getPreferredName(), attributes); + builder.endObject(); + return builder; + } + + @Override + public int hashCode() { + return Objects.hash(id, name, ephemeralId, transportAddress, attributes); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + NodeAttributes that = (NodeAttributes) other; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name) && + Objects.equals(ephemeralId, that.ephemeralId) && + Objects.equals(transportAddress, that.transportAddress) && + Objects.equals(attributes, that.attributes); + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java new file mode 100644 index 0000000000000..737a26996a18d --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java @@ -0,0 +1,39 @@ +/* + * 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.protocol.xpack.ml.job.config; + +import java.util.Locale; + +/** + * Jobs whether running or complete are in one of these states. + * When a job is created it is initialised in to the state closed + * i.e. it is not running. + */ +public enum JobState { + + CLOSING, CLOSED, OPENED, FAILED, OPENING; + + public static JobState fromString(String name) { + return valueOf(name.trim().toUpperCase(Locale.ROOT)); + } + + public String value() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java new file mode 100644 index 0000000000000..300cedc77c0fb --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java @@ -0,0 +1,127 @@ +/* + * 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.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * A class to hold statistics about forecasts. + */ +public class ForecastStats implements ToXContentObject { + + public static final ParseField TOTAL = new ParseField("total"); + public static final ParseField FORECASTED_JOBS = new ParseField("forecasted_jobs"); + public static final ParseField MEMORY = new ParseField("memory_bytes"); + public static final ParseField RUNTIME = new ParseField("processing_time_ms"); + public static final ParseField RECORDS = new ParseField("records"); + public static final ParseField STATUSES = new ParseField("status"); + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("forecast_stats", + true, + (a) -> { + int i = 0; + long total = (long)a[i++]; + SimpleStats memoryStats = (SimpleStats)a[i++]; + SimpleStats recordStats = (SimpleStats)a[i++]; + SimpleStats runtimeStats = (SimpleStats)a[i++]; + Map statusCounts = (Map)a[i]; + return new ForecastStats(total, memoryStats, recordStats, runtimeStats, statusCounts); + }); + + static { + PARSER.declareLong(ConstructingObjectParser.constructorArg(), TOTAL); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, MEMORY); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, RECORDS); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, RUNTIME); + PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), + p -> { + Map counts = new HashMap<>(); + p.map().forEach((key, value) -> counts.put(key, (Long)value)); + return counts; + }, STATUSES, ObjectParser.ValueType.OBJECT); + } + + private long total; + private long forecastedJobs; + private SimpleStats memoryStats; + private SimpleStats recordStats; + private SimpleStats runtimeStats; + private Map statusCounts; + + public ForecastStats(long total, + SimpleStats memoryStats, + SimpleStats recordStats, + SimpleStats runtimeStats, + Map statusCounts) { + this.total = total; + this.forecastedJobs = total > 0 ? 1 : 0; + this.memoryStats = Objects.requireNonNull(memoryStats); + this.recordStats = Objects.requireNonNull(recordStats); + this.runtimeStats = Objects.requireNonNull(runtimeStats); + this.statusCounts = Collections.unmodifiableMap(statusCounts); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(TOTAL.getPreferredName(), total); + builder.field(FORECASTED_JOBS.getPreferredName(), forecastedJobs); + + if (total > 0) { + builder.field(MEMORY.getPreferredName(), memoryStats); + builder.field(RECORDS.getPreferredName(), recordStats); + builder.field(RUNTIME.getPreferredName(), runtimeStats); + builder.field(STATUSES.getPreferredName(), statusCounts); + } + return builder.endObject(); + } + + @Override + public int hashCode() { + return Objects.hash(total, forecastedJobs, memoryStats, recordStats, runtimeStats, statusCounts); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + ForecastStats other = (ForecastStats) obj; + return Objects.equals(total, other.total) && Objects.equals(forecastedJobs, other.forecastedJobs) + && Objects.equals(memoryStats, other.memoryStats) && Objects.equals(recordStats, other.recordStats) + && Objects.equals(runtimeStats, other.runtimeStats) && Objects.equals(statusCounts, other.statusCounts); + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java new file mode 100644 index 0000000000000..a484625ac2afa --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java @@ -0,0 +1,172 @@ +package org.elasticsearch.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.protocol.xpack.ml.job.config.Job; +import org.elasticsearch.protocol.xpack.ml.job.config.JobState; +import org.elasticsearch.protocol.xpack.ml.job.process.DataCounts; +import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStats; +import org.elasticsearch.protocol.xpack.ml.NodeAttributes; +import org.elasticsearch.protocol.xpack.ml.job.util.TimeUtil; + +import java.io.IOException; +import java.util.Objects; + +public class JobStats implements ToXContentObject { + + private static final ParseField DATA_COUNTS = new ParseField("data_counts"); + private static final ParseField MODEL_SIZE_STATS = new ParseField("model_size_stats"); + private static final ParseField FORECASTS_STATS = new ParseField("forecasts_stats"); + private static final ParseField STATE = new ParseField("state"); + private static final ParseField NODE = new ParseField("node"); + private static final ParseField OPEN_TIME = new ParseField("open_time"); + private static final ParseField ASSIGNMENT_EXPLANATION = new ParseField("assignment_explanation"); + + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("job_stats", + true, + (a) -> { + int i = 0; + String jobId = (String) a[i++]; + DataCounts dataCounts = (DataCounts) a[i++]; + JobState jobState = (JobState) a[i++]; + ModelSizeStats modelSizeStats = (ModelSizeStats) a[i++]; + ForecastStats forecastStats = (ForecastStats) a[i++]; + NodeAttributes node = (NodeAttributes) a[i++]; + String assignmentExplanation = (String) a[i++]; + TimeValue openTime = (TimeValue) a[i]; + return new JobStats(jobId, + dataCounts, + jobState, + modelSizeStats, + forecastStats, + node, + assignmentExplanation, + openTime); + }); + + static { + PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID); + PARSER.declareObject(ConstructingObjectParser.constructorArg(), DataCounts.PARSER, DATA_COUNTS); + PARSER.declareField(ConstructingObjectParser.constructorArg(), + (p) -> JobState.fromString(p.text()), + STATE, + ObjectParser.ValueType.VALUE); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), ModelSizeStats.PARSER, MODEL_SIZE_STATS); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), ForecastStats.PARSER, FORECASTS_STATS); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), NodeAttributes.PARSER, NODE); + PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), ASSIGNMENT_EXPLANATION); + PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), + (p) -> TimeUtil.parseTimeField(p, OPEN_TIME.getPreferredName()), + OPEN_TIME, + ObjectParser.ValueType.VALUE); + } + + + private final String jobId; + private DataCounts dataCounts; + private JobState state; + private ModelSizeStats modelSizeStats; + private ForecastStats forecastStats; + private NodeAttributes node; + private String assignmentExplanation; + private TimeValue openTime; + + JobStats(String jobId, DataCounts dataCounts, JobState state, @Nullable ModelSizeStats modelSizeStats, + @Nullable ForecastStats forecastStats, @Nullable NodeAttributes node, + @Nullable String assignmentExplanation, @Nullable TimeValue opentime) { + this.jobId = Objects.requireNonNull(jobId); + this.dataCounts = Objects.requireNonNull(dataCounts); + this.state = Objects.requireNonNull(state); + this.modelSizeStats = modelSizeStats; + this.forecastStats = forecastStats; + this.node = node; + this.assignmentExplanation = assignmentExplanation; + this.openTime = opentime; + } + + public String getJobId() { + return jobId; + } + + public DataCounts getDataCounts() { + return dataCounts; + } + + public ModelSizeStats getModelSizeStats() { + return modelSizeStats; + } + + public ForecastStats getForecastStats() { + return forecastStats; + } + + public JobState getState() { + return state; + } + + public NodeAttributes getNode() { + return node; + } + + public String getAssignmentExplanation() { + return assignmentExplanation; + } + + public TimeValue getOpenTime() { + return openTime; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(Job.ID.getPreferredName(), jobId); + builder.field(DATA_COUNTS.getPreferredName(), dataCounts); + builder.field(STATE.getPreferredName(), state.toString()); + if (modelSizeStats != null) { + builder.field(MODEL_SIZE_STATS.getPreferredName(), modelSizeStats); + } + if (forecastStats != null) { + builder.field(FORECASTS_STATS.getPreferredName(), forecastStats); + } + if (node != null) { + builder.field(NODE.getPreferredName(), node); + } + if (assignmentExplanation != null) { + builder.field(ASSIGNMENT_EXPLANATION.getPreferredName(), assignmentExplanation); + } + if (openTime != null) { + builder.field(OPEN_TIME.getPreferredName(), openTime.getStringRep()); + } + return builder.endObject(); + } + + @Override + public int hashCode() { + return Objects.hash(jobId, dataCounts, modelSizeStats, forecastStats, state, node, assignmentExplanation, openTime); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + JobStats other = (JobStats) obj; + return Objects.equals(jobId, other.jobId) + && Objects.equals(this.dataCounts, other.dataCounts) + && Objects.equals(this.modelSizeStats, other.modelSizeStats) + && Objects.equals(this.forecastStats, other.forecastStats) + && Objects.equals(this.state, other.state) + && Objects.equals(this.node, other.node) + && Objects.equals(this.assignmentExplanation, other.assignmentExplanation) + && Objects.equals(this.openTime, other.openTime); + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java new file mode 100644 index 0000000000000..e50b363e92814 --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java @@ -0,0 +1,118 @@ +/* + * 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.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Objects; + +/** + * Helper class for min, max, avg and total statistics for a quantity + */ +public class SimpleStats implements ToXContentObject { + + public static final ParseField MIN = new ParseField("min"); + public static final ParseField MAX = new ParseField("max"); + public static final ParseField AVG = new ParseField("avg"); + public static final ParseField TOTAL = new ParseField("total"); + + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("simple_stats", true, + (a) -> { + int i = 0; + double total = (double)a[i++]; + double min = (double)a[i++]; + double max = (double)a[i++]; + double avg = (double)a[i++]; + return new SimpleStats(total, min, max, avg); + }); + + static { + PARSER.declareDouble(ConstructingObjectParser.constructorArg(), TOTAL); + PARSER.declareDouble(ConstructingObjectParser.constructorArg(), MIN); + PARSER.declareDouble(ConstructingObjectParser.constructorArg(), MAX); + PARSER.declareDouble(ConstructingObjectParser.constructorArg(), AVG); + } + + private double total; + private double min; + private double max; + private double avg; + + SimpleStats(double total, double min, double max, double avg) { + this.total = total; + this.min = min; + this.max = max; + this.avg = avg; + } + + public double getMin() { + return min; + } + + public double getMax() { + return max; + } + + public double getAvg() { + return avg; + } + + public double getTotal() { + return total; + } + + @Override + public int hashCode() { + return Objects.hash(total, min, max, avg); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + SimpleStats other = (SimpleStats) obj; + return Objects.equals(total, other.total) && + Objects.equals(min, other.min) && + Objects.equals(avg, other.avg) && + Objects.equals(max, other.max); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(MIN.getPreferredName(), min); + builder.field(MAX.getPreferredName(), max); + builder.field(AVG.getPreferredName(), avg); + builder.field(TOTAL.getPreferredName(), total); + builder.endObject(); + return builder; + } +} + diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java new file mode 100644 index 0000000000000..7fc5e5fbc2d05 --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java @@ -0,0 +1,40 @@ +package org.elasticsearch.protocol.xpack.ml; + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class NodeAttributesTests extends AbstractXContentTestCase { + + public static NodeAttributes createRandom() { + int numberOfAttributes = randomIntBetween(1, 10); + Map attributes = new HashMap<>(numberOfAttributes); + for(int i = 0; i < numberOfAttributes; i++) { + String val = randomAlphaOfLength(10); + attributes.put("key-"+i, val); + } + return new NodeAttributes(randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + attributes); + } + + @Override + protected NodeAttributes createTestInstance() { + return createRandom(); + } + + @Override + protected NodeAttributes doParseInstance(XContentParser parser) throws IOException { + return NodeAttributes.PARSER.parse(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java new file mode 100644 index 0000000000000..1bdb6948d9289 --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java @@ -0,0 +1,80 @@ +/* + * 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.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.json.JsonXContent; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class ForecastStatsTests extends AbstractXContentTestCase { + + public void testEmpty() throws IOException { + ForecastStats forecastStats = new ForecastStats(0, null, null, null, null); + + XContentBuilder builder = JsonXContent.contentBuilder(); + forecastStats.toXContent(builder, ToXContent.EMPTY_PARAMS); + + XContentParser parser = createParser(builder); + Map properties = parser.map(); + assertTrue(properties.containsKey(ForecastStats.TOTAL.getPreferredName())); + assertTrue(properties.containsKey(ForecastStats.FORECASTED_JOBS.getPreferredName())); + assertFalse(properties.containsKey(ForecastStats.MEMORY.getPreferredName())); + assertFalse(properties.containsKey(ForecastStats.RECORDS.getPreferredName())); + assertFalse(properties.containsKey(ForecastStats.RUNTIME.getPreferredName())); + assertFalse(properties.containsKey(ForecastStats.STATUSES.getPreferredName())); + } + + @Override + public ForecastStats createTestInstance() { + return createForecastStats(1, 22); + } + + @Override + protected ForecastStats doParseInstance(XContentParser parser) throws IOException { + return ForecastStats.PARSER.parse(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } + + public static ForecastStats createForecastStats(long minTotal, long maxTotal) { + return new ForecastStats(randomLongBetween(minTotal, maxTotal), createSimpleStats(), + createSimpleStats(), createSimpleStats(), createCountStats()); + } + + private static SimpleStats createSimpleStats() { + return new SimpleStatsTests().createTestInstance(); + } + + private static Map createCountStats() { + Map countStats = new HashMap<>(); + for (int i = 0; i < randomInt(10); ++i) { + countStats.put(randomAlphaOfLengthBetween(1, 20), randomLongBetween(1L, 100L)); + } + return countStats; + } +} diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java new file mode 100644 index 0000000000000..7f695dc767b4b --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java @@ -0,0 +1,62 @@ +/* + * 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.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.protocol.xpack.ml.NodeAttributes; +import org.elasticsearch.protocol.xpack.ml.NodeAttributesTests; +import org.elasticsearch.protocol.xpack.ml.job.config.JobState; +import org.elasticsearch.protocol.xpack.ml.job.config.JobTests; +import org.elasticsearch.protocol.xpack.ml.job.process.DataCounts; +import org.elasticsearch.protocol.xpack.ml.job.process.DataCountsTests; +import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStats; +import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStatsTests; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; + + +public class JobStatsTests extends AbstractXContentTestCase { + + @Override + protected JobStats createTestInstance() { + String jobId = JobTests.randomValidJobId(); + JobState state = randomFrom(JobState.CLOSING, JobState.CLOSED, JobState.OPENED, JobState.FAILED, JobState.OPENING); + DataCounts dataCounts = DataCountsTests.createTestInstance(jobId); + + ModelSizeStats modelSizeStats = randomBoolean() ? ModelSizeStatsTests.createRandomized() : null; + ForecastStats forecastStats = randomBoolean() ? ForecastStatsTests.createForecastStats(1, 22) : null; + NodeAttributes nodeAttributes = randomBoolean() ? NodeAttributesTests.createRandom() : null; + String assigmentExplanation = randomBoolean() ? randomAlphaOfLength(10) : null; + TimeValue openTime = randomBoolean() ? TimeValue.timeValueMillis(randomIntBetween(1, 10000)) : null; + + return new JobStats(jobId, dataCounts, state, modelSizeStats, forecastStats, nodeAttributes, assigmentExplanation, openTime); + } + + @Override + protected JobStats doParseInstance(XContentParser parser) throws IOException { + return JobStats.PARSER.parse(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java new file mode 100644 index 0000000000000..6f4d9c54e3b6b --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java @@ -0,0 +1,43 @@ +/* + * 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.protocol.xpack.ml.job.stats; + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; + + +public class SimpleStatsTests extends AbstractXContentTestCase { + + @Override + protected SimpleStats createTestInstance() { + return new SimpleStats(randomDouble(), randomDouble(), randomDouble(), randomDouble()); + } + + @Override + protected SimpleStats doParseInstance(XContentParser parser) throws IOException { + return SimpleStats.PARSER.parse(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} From 8a7feb4f1e6b41f3df828503876f2956fa4ba46d Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Fri, 24 Aug 2018 09:12:51 -0500 Subject: [PATCH 02/11] HLRC: Adding job stats pojos --- .../xpack/ml/job/stats/ForecastStats.java | 2 +- .../protocol/xpack/ml/job/stats/JobStats.java | 6 +++--- .../xpack/ml/NodeAttributesTests.java | 2 +- .../ml/job/stats/ForecastStatsTests.java | 21 +------------------ .../xpack/ml/job/stats/JobStatsTests.java | 2 +- 5 files changed, 7 insertions(+), 26 deletions(-) diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java index 300cedc77c0fb..b9ef7af9f104b 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java @@ -64,7 +64,7 @@ public class ForecastStats implements ToXContentObject { PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), p -> { Map counts = new HashMap<>(); - p.map().forEach((key, value) -> counts.put(key, (Long)value)); + p.map().forEach((key, value) -> counts.put(key, ((Number)value).longValue())); return counts; }, STATUSES, ObjectParser.ValueType.OBJECT); } diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java index a484625ac2afa..82446e77e058f 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java @@ -12,7 +12,6 @@ import org.elasticsearch.protocol.xpack.ml.job.process.DataCounts; import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStats; import org.elasticsearch.protocol.xpack.ml.NodeAttributes; -import org.elasticsearch.protocol.xpack.ml.job.util.TimeUtil; import java.io.IOException; import java.util.Objects; @@ -35,7 +34,8 @@ public class JobStats implements ToXContentObject { String jobId = (String) a[i++]; DataCounts dataCounts = (DataCounts) a[i++]; JobState jobState = (JobState) a[i++]; - ModelSizeStats modelSizeStats = (ModelSizeStats) a[i++]; + ModelSizeStats.Builder modelSizeStatsBuilder = (ModelSizeStats.Builder) a[i++]; + ModelSizeStats modelSizeStats = modelSizeStatsBuilder == null ? null : modelSizeStatsBuilder.build(); ForecastStats forecastStats = (ForecastStats) a[i++]; NodeAttributes node = (NodeAttributes) a[i++]; String assignmentExplanation = (String) a[i++]; @@ -62,7 +62,7 @@ public class JobStats implements ToXContentObject { PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), NodeAttributes.PARSER, NODE); PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), ASSIGNMENT_EXPLANATION); PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), - (p) -> TimeUtil.parseTimeField(p, OPEN_TIME.getPreferredName()), + (p) -> TimeValue.parseTimeValue(p.text(), OPEN_TIME.getPreferredName()), OPEN_TIME, ObjectParser.ValueType.VALUE); } diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java index 7fc5e5fbc2d05..8f262f86a62c7 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java @@ -35,6 +35,6 @@ protected NodeAttributes doParseInstance(XContentParser parser) throws IOExcepti @Override protected boolean supportsUnknownFields() { - return true; + return false; } } diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java index 1bdb6948d9289..1681defbbde6c 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java @@ -18,10 +18,7 @@ */ package org.elasticsearch.protocol.xpack.ml.job.stats; -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; @@ -30,22 +27,6 @@ public class ForecastStatsTests extends AbstractXContentTestCase { - public void testEmpty() throws IOException { - ForecastStats forecastStats = new ForecastStats(0, null, null, null, null); - - XContentBuilder builder = JsonXContent.contentBuilder(); - forecastStats.toXContent(builder, ToXContent.EMPTY_PARAMS); - - XContentParser parser = createParser(builder); - Map properties = parser.map(); - assertTrue(properties.containsKey(ForecastStats.TOTAL.getPreferredName())); - assertTrue(properties.containsKey(ForecastStats.FORECASTED_JOBS.getPreferredName())); - assertFalse(properties.containsKey(ForecastStats.MEMORY.getPreferredName())); - assertFalse(properties.containsKey(ForecastStats.RECORDS.getPreferredName())); - assertFalse(properties.containsKey(ForecastStats.RUNTIME.getPreferredName())); - assertFalse(properties.containsKey(ForecastStats.STATUSES.getPreferredName())); - } - @Override public ForecastStats createTestInstance() { return createForecastStats(1, 22); @@ -58,7 +39,7 @@ protected ForecastStats doParseInstance(XContentParser parser) throws IOExceptio @Override protected boolean supportsUnknownFields() { - return true; + return false; } public static ForecastStats createForecastStats(long minTotal, long maxTotal) { diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java index 7f695dc767b4b..3329eee6cfa12 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java @@ -57,6 +57,6 @@ protected JobStats doParseInstance(XContentParser parser) throws IOException { @Override protected boolean supportsUnknownFields() { - return true; + return false; } } From de52ab235e550516d662312310364197e33f8d6f Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Mon, 27 Aug 2018 10:07:09 -0500 Subject: [PATCH 03/11] HLRC: ML job stats --- .../client/MLRequestConverters.java | 18 +++ .../client/MachineLearningClient.java | 43 ++++++ .../client/MLRequestConvertersTests.java | 18 +++ .../client/MachineLearningGetResultsIT.java | 5 + .../client/MachineLearningIT.java | 65 +++++++++ .../MlClientDocumentationIT.java | 58 ++++++++ .../high-level/ml/get-job-stats.asciidoc | 57 ++++++++ .../high-level/supported-apis.asciidoc | 2 + .../xpack/ml/GetJobsStatsRequest.java | 129 ++++++++++++++++++ .../xpack/ml/GetJobsStatsResponse.java | 70 ++++++++++ .../protocol/xpack/ml/NodeAttributes.java | 18 +++ .../xpack/ml/job/stats/ForecastStats.java | 52 ++++++- .../protocol/xpack/ml/job/stats/JobStats.java | 37 ++++- .../xpack/ml/GetJobsStatsRequestTests.java | 69 ++++++++++ .../xpack/ml/GetJobsStatsResponseTests.java | 53 +++++++ .../xpack/ml/job/stats/JobStatsTests.java | 9 +- 16 files changed, 695 insertions(+), 8 deletions(-) create mode 100644 docs/java-rest/high-level/ml/get-job-stats.asciidoc create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java create mode 100644 x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java create mode 100644 x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java index 6c1cc20570102..5c4e660aee209 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java @@ -29,6 +29,7 @@ import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest; import org.elasticsearch.protocol.xpack.ml.GetJobRequest; import org.elasticsearch.protocol.xpack.ml.GetBucketsRequest; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; import org.elasticsearch.protocol.xpack.ml.OpenJobRequest; import org.elasticsearch.protocol.xpack.ml.PutJobRequest; @@ -124,4 +125,21 @@ static Request getBuckets(GetBucketsRequest getBucketsRequest) throws IOExceptio request.setEntity(createEntity(getBucketsRequest, REQUEST_BODY_CONTENT_TYPE)); return request; } + + static Request getJobsStats(GetJobsStatsRequest getJobsStatsRequest) { + String endpoint = new EndpointBuilder() + .addPathPartAsIs("_xpack") + .addPathPartAsIs("ml") + .addPathPartAsIs("anomaly_detectors") + .addPathPart(Strings.collectionToCommaDelimitedString(getJobsStatsRequest.getJobIds())) + .addPathPartAsIs("_stats") + .build(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + + RequestConverters.Params params = new RequestConverters.Params(request); + if (getJobsStatsRequest.isAllowNoJobs() != null) { + params.putParam("allow_no_jobs", Boolean.toString(getJobsStatsRequest.isAllowNoJobs())); + } + return request; + } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index c4dcc1eaffc5a..e58c084d13300 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -27,6 +27,8 @@ import org.elasticsearch.protocol.xpack.ml.GetBucketsResponse; import org.elasticsearch.protocol.xpack.ml.GetJobRequest; import org.elasticsearch.protocol.xpack.ml.GetJobResponse; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; import org.elasticsearch.protocol.xpack.ml.OpenJobRequest; import org.elasticsearch.protocol.xpack.ml.OpenJobResponse; import org.elasticsearch.protocol.xpack.ml.PutJobRequest; @@ -285,4 +287,45 @@ public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, A listener, Collections.emptySet()); } + + /** + * Gets one or more Machine Learning job statistics. + * + *

+ * For additional info + * see + *

+ * @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options + * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return {@link GetJobsStatsResponse} response object containing + * the {@link org.elasticsearch.protocol.xpack.ml.job.stats.JobStats} objects and the number of jobs found + * @throws IOException when there is a serialization issue sending the request or receiving the response + */ + public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(request, + MLRequestConverters::getJobsStats, + options, + GetJobsStatsResponse::fromXContent, + Collections.emptySet()); + } + + /** + * Gets one or more Machine Learning job configuration info, asynchronously. + * + *

+ * For additional info + * see + *

+ * @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options + * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener Listener to be notified with {@link GetJobsStatsResponse} upon request completion + */ + public void getJobStatsAsync(GetJobsStatsRequest request, RequestOptions options, ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(request, + MLRequestConverters::getJobsStats, + options, + GetJobsStatsResponse::fromXContent, + listener, + Collections.emptySet()); + } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java index 9065cda9cd6fc..eaeb1993a3019 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java @@ -30,6 +30,7 @@ import org.elasticsearch.protocol.xpack.ml.DeleteJobRequest; import org.elasticsearch.protocol.xpack.ml.GetBucketsRequest; import org.elasticsearch.protocol.xpack.ml.GetJobRequest; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; import org.elasticsearch.protocol.xpack.ml.OpenJobRequest; import org.elasticsearch.protocol.xpack.ml.PutJobRequest; import org.elasticsearch.protocol.xpack.ml.job.config.AnalysisConfig; @@ -139,6 +140,23 @@ public void testGetBuckets() throws IOException { } } + public void testGetJobsStats() { + GetJobsStatsRequest getJobsStatsRequestRequest = new GetJobsStatsRequest(); + + Request request = MLRequestConverters.getJobsStats(getJobsStatsRequestRequest); + + assertEquals(HttpGet.METHOD_NAME, request.getMethod()); + assertEquals("/_xpack/ml/anomaly_detectors/_stats", request.getEndpoint()); + assertFalse(request.getParameters().containsKey("allow_no_jobs")); + + getJobsStatsRequestRequest = new GetJobsStatsRequest("job1", "jobs*"); + getJobsStatsRequestRequest.setAllowNoJobs(true); + request = MLRequestConverters.getJobsStats(getJobsStatsRequestRequest); + + assertEquals("/_xpack/ml/anomaly_detectors/job1,jobs*/_stats", request.getEndpoint()); + assertEquals(Boolean.toString(true), request.getParameters().get("allow_no_jobs")); + } + private static Job createValidJob(String jobId) { AnalysisConfig.Builder analysisConfig = AnalysisConfig.builder(Collections.singletonList( Detector.builder().setFunction("count").build())); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java index a4f83c347ad13..99a2356b67e4f 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java @@ -194,6 +194,11 @@ public void testGetBuckets() throws IOException { } } + public void testGetJobsStats() throws IOException { + + } + + private static class BucketStats { // score < 50.0 private long minorCount; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index cec5dd7ccf8ff..004fce85a99f6 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -19,6 +19,7 @@ package org.elasticsearch.client; import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.protocol.xpack.ml.CloseJobRequest; import org.elasticsearch.protocol.xpack.ml.CloseJobResponse; @@ -26,6 +27,8 @@ import org.elasticsearch.protocol.xpack.ml.DeleteJobResponse; import org.elasticsearch.protocol.xpack.ml.GetJobRequest; import org.elasticsearch.protocol.xpack.ml.GetJobResponse; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; import org.elasticsearch.protocol.xpack.ml.OpenJobRequest; import org.elasticsearch.protocol.xpack.ml.OpenJobResponse; import org.elasticsearch.protocol.xpack.ml.PutJobRequest; @@ -34,6 +37,8 @@ import org.elasticsearch.protocol.xpack.ml.job.config.DataDescription; import org.elasticsearch.protocol.xpack.ml.job.config.Detector; import org.elasticsearch.protocol.xpack.ml.job.config.Job; +import org.elasticsearch.protocol.xpack.ml.job.config.JobState; +import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; import org.junit.After; import java.io.IOException; @@ -41,6 +46,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasSize; @@ -138,6 +144,65 @@ public void testCloseJob() throws Exception { assertTrue(response.isClosed()); } + public void testGetJobsStats() throws Exception { + String jobId1 = "ml-get-job-stats-test-id-1"; + String jobId2 = "ml-get-job-stats-test-id-2"; + + Job job1 = buildJob(jobId1); + Job job2 = buildJob(jobId2); + MachineLearningClient machineLearningClient = highLevelClient().machineLearning(); + machineLearningClient.putJob(new PutJobRequest(job1), RequestOptions.DEFAULT); + machineLearningClient.putJob(new PutJobRequest(job2), RequestOptions.DEFAULT); + + machineLearningClient.openJob(new OpenJobRequest(jobId1), RequestOptions.DEFAULT); + + GetJobsStatsRequest request = new GetJobsStatsRequest(jobId1, jobId2); + + Thread.sleep(1000); + // Test getting specific jobs stats + GetJobsStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + + assertEquals(2, response.count()); + assertThat(response.jobs(), hasSize(2)); + assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), containsInAnyOrder(jobId1, jobId2)); + for (JobStats stats : response.jobs()) { + if (stats.getJobId().equals(jobId1)) { + assertEquals(JobState.OPENED, stats.getState()); + } else { + assertEquals(JobState.CLOSED, stats.getState()); + } + } + + // Test getting all jobs explicitly + request = GetJobsStatsRequest.allJobsStats(); + response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + + assertTrue(response.count() >= 2L); + assertTrue(response.jobs().size() >= 2L); + assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + + // Test getting all jobs implicitly + response = execute(new GetJobsStatsRequest(), machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + + assertTrue(response.count() >= 2L); + assertTrue(response.jobs().size() >= 2L); + assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + + // Test getting all jobs with wildcard + request = new GetJobsStatsRequest("ml-get-job-stats-test-id-*"); + response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + assertTrue(response.count() >= 2L); + assertTrue(response.jobs().size() >= 2L); + assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + + // Test when allow no jobs is false + final GetJobsStatsRequest erroredRequest = new GetJobsStatsRequest("jobs-that-do-not-exist*"); + erroredRequest.setAllowNoJobs(false); + ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, + () -> execute(erroredRequest, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync)); + assertThat(exception.status().getStatus(), equalTo(404)); + } + public static String randomValidJobId() { CodepointSetGenerator generator = new CodepointSetGenerator("abcdefghijklmnopqrstuvwxyz0123456789".toCharArray()); return generator.ofCodePointsLength(random(), 10, 10); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index 683f91dae2eb1..c816d39952b03 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -37,6 +37,8 @@ import org.elasticsearch.protocol.xpack.ml.GetBucketsResponse; import org.elasticsearch.protocol.xpack.ml.GetJobRequest; import org.elasticsearch.protocol.xpack.ml.GetJobResponse; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; +import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; import org.elasticsearch.protocol.xpack.ml.OpenJobRequest; import org.elasticsearch.protocol.xpack.ml.OpenJobResponse; import org.elasticsearch.protocol.xpack.ml.PutJobRequest; @@ -46,6 +48,7 @@ import org.elasticsearch.protocol.xpack.ml.job.config.Detector; import org.elasticsearch.protocol.xpack.ml.job.config.Job; import org.elasticsearch.protocol.xpack.ml.job.results.Bucket; +import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; import org.elasticsearch.protocol.xpack.ml.job.util.PageParams; import org.junit.After; @@ -454,4 +457,59 @@ public void onFailure(Exception e) { assertTrue(latch.await(30L, TimeUnit.SECONDS)); } } + + public void testGetJobStats() throws Exception { + RestHighLevelClient client = highLevelClient(); + + Job job = MachineLearningIT.buildJob("get-machine-learning-job-stats1"); + client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT); + + Job secondJob = MachineLearningIT.buildJob("get-machine-learning-job-stats2"); + client.machineLearning().putJob(new PutJobRequest(secondJob), RequestOptions.DEFAULT); + + { + //tag::x-pack-ml-get-job-stats-request + GetJobsStatsRequest request = new GetJobsStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); //<1> + request.setAllowNoJobs(true); //<2> + //end::x-pack-ml-get-job-stats-request + + //tag::x-pack-ml-get-job-stats-execute + GetJobsStatsResponse response = client.machineLearning().getJobStats(request, RequestOptions.DEFAULT); + long numberOfJobsStats = response.count(); //<1> + List jobsStats = response.jobs(); //<2> + //end::x-pack-ml-get-job-stats-execute + + assertEquals(2, response.count()); + assertThat(response.jobs(), hasSize(2)); + assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), + containsInAnyOrder(job.getId(), secondJob.getId())); + } + { + GetJobsStatsRequest request = new GetJobsStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); + + // tag::x-pack-ml-get-job-stats-listener + ActionListener listener = new ActionListener() { + @Override + public void onResponse(GetJobsStatsResponse response) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::x-pack-ml-get-job-stats-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::x-pack-ml-get-job-stats-execute-async + client.machineLearning().getJobStatsAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::x-pack-ml-get-job-stats-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } + } } diff --git a/docs/java-rest/high-level/ml/get-job-stats.asciidoc b/docs/java-rest/high-level/ml/get-job-stats.asciidoc new file mode 100644 index 0000000000000..d517184212024 --- /dev/null +++ b/docs/java-rest/high-level/ml/get-job-stats.asciidoc @@ -0,0 +1,57 @@ +[[java-rest-high-x-pack-ml-get-job-stats]] +=== Get Job Stats API + +The Get Job Stats API provides the ability to get {ml} job's statistics in the cluster. +It accepts a `GetJobsStatsRequest` object and responds +with a `GetJobsStatsResponse` object. + +[[java-rest-high-x-pack-ml-get-job-stats-request]] +==== Get Job Stats Request + +A `GetJobsStatsRequest` object gets can have any number of `jobId` +entries. However, they all must be non-null. An empty list is the same as +requesting for all jobs. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-request] +-------------------------------------------------- +<1> Constructing a new request referencing existing `jobIds`, can contain wildcards +<2> Whether to ignore if a wildcard expression matches no jobs. + (This includes `_all` string or when no jobs have been specified) + +[[java-rest-high-x-pack-ml-get-job-stats-execution]] +==== Execution + +The request can be executed through the `MachineLearningClient` contained +in the `RestHighLevelClient` object, accessed via the `machineLearningClient()` method. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-execute] +-------------------------------------------------- +<1> `getCount()` from the `GetJobsStatsResponse` indicates the number of jobs statistics found +<2> `getJobs()` is the collection of {ml} `JobStats` objects found + +[[java-rest-high-x-pack-ml-get-job-stats-execution-async]] +==== Asynchronous Execution + +The request can also be executed asynchronously: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-execute-async] +-------------------------------------------------- +<1> The `GetJobsStatsRequest` to execute and the `ActionListener` to use when +the execution completes + +The method does not block and returns immediately. The passed `ActionListener` is used +to notify the caller of completion. A typical `ActionListener` for `GetJobsStatsResponse` may +look like + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-listener] +-------------------------------------------------- +<1> `onResponse` is called back when the action is completed successfully +<2> `onFailure` is called back when some unexpected error occurs diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index e04e391f3e0b7..1ce06b919ef1f 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -210,6 +210,7 @@ The Java High Level REST Client supports the following Machine Learning APIs: * <> * <> * <> +* <> include::ml/put-job.asciidoc[] include::ml/get-job.asciidoc[] @@ -217,6 +218,7 @@ include::ml/delete-job.asciidoc[] include::ml/open-job.asciidoc[] include::ml/close-job.asciidoc[] include::ml/get-buckets.asciidoc[] +include::ml/get-job-stats.asciidoc[] == Migration APIs diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java new file mode 100644 index 0000000000000..182740e1d2188 --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java @@ -0,0 +1,129 @@ +package org.elasticsearch.protocol.xpack.ml; + +import org.elasticsearch.action.ActionRequest; +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + + +/** + * Request object to get {@link org.elasticsearch.protocol.xpack.ml.job.stats.JobStats} objects with the matching `jobId`s + * + * `_all` explicitly gets all the jobs in the cluster + * An empty request (no `jobId`s) implicitly gets all the jobs in the cluster + */ +public class GetJobsStatsRequest extends ActionRequest implements ToXContentObject { + + public static final ParseField JOB_ID = new ParseField("job_id"); + public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs"); + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "get_jobs_stats_request", + true, a -> new GetJobsStatsRequest((List) a[0])); + + static { + PARSER.declareField(ConstructingObjectParser.constructorArg(), + p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())), + JOB_ID, ObjectParser.ValueType.STRING_ARRAY); + PARSER.declareBoolean(GetJobsStatsRequest::setAllowNoJobs, ALLOW_NO_JOBS); + } + + private static final String ALL_JOBS = "_all"; + + private final List jobIds; + private Boolean allowNoJobs; + + /** + * Explicitly gets all jobs statistics + * + * @return a {@link GetJobsStatsRequest} for all existing jobs + */ + public static GetJobsStatsRequest allJobsStats(){ + return new GetJobsStatsRequest(ALL_JOBS); + } + + GetJobsStatsRequest(List jobIds) { + if (jobIds.stream().anyMatch(Objects::isNull)) { + throw new NullPointerException("jobIds must not contain null values"); + } + this.jobIds = new ArrayList<>(jobIds); + } + + /** + * Get the specified Job's statistics via their unique jobIds + * + * @param jobIds must be non-null and each jobId must be non-null + */ + public GetJobsStatsRequest(String... jobIds) { + this(Arrays.asList(jobIds)); + } + + /** + * All the jobIds for which to get statistics + */ + public List getJobIds() { + return jobIds; + } + + public Boolean isAllowNoJobs() { + return this.allowNoJobs; + } + + /** + * Whether to ignore if a wildcard expression matches no jobs. + * + * This includes `_all` string or when no jobs have been specified + * + * @param allowNoJobs When {@code true} ignore if wildcard or `_all` matches no jobs. Defaults to {@code true} + */ + public void setAllowNoJobs(boolean allowNoJobs) { + this.allowNoJobs = allowNoJobs; + } + + @Override + public int hashCode() { + return Objects.hash(jobIds, allowNoJobs); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || getClass() != other.getClass()) { + return false; + } + + GetJobsStatsRequest that = (GetJobsStatsRequest) other; + return Objects.equals(jobIds, that.jobIds) && + Objects.equals(allowNoJobs, that.allowNoJobs); + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(JOB_ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds)); + if (allowNoJobs != null) { + builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs); + } + builder.endObject(); + return builder; + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java new file mode 100644 index 0000000000000..d6e4dc334834d --- /dev/null +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java @@ -0,0 +1,70 @@ +package org.elasticsearch.protocol.xpack.ml; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; + +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; + +/** + * Contains a {@link List} of the found {@link JobStats} objects and the total count found + */ +public class GetJobsStatsResponse extends AbstractResultResponse { + + public static final ParseField RESULTS_FIELD = new ParseField("jobs"); + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>("jobs_stats_response", true, + a -> new GetJobsStatsResponse((List) a[0], (long) a[1])); + + static { + PARSER.declareObjectArray(constructorArg(), JobStats.PARSER, RESULTS_FIELD); + PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT); + } + + GetJobsStatsResponse(List jobStats, long count) { + super(RESULTS_FIELD, jobStats, count); + } + + /** + * The collection of {@link JobStats} objects found in the query + */ + public List jobs() { + return results; + } + + public static GetJobsStatsResponse fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } + + @Override + public int hashCode() { + return Objects.hash(results, count); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + GetJobsStatsResponse other = (GetJobsStatsResponse) obj; + return Objects.equals(results, other.results) && count == other.count; + } + + @Override + public final String toString() { + return Strings.toString(this); + } +} diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java index 97ed1b9bd8871..e2d324a6bbdfa 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java @@ -11,6 +11,9 @@ import java.util.Map; import java.util.Objects; +/** + * Class containing an Elastic Node's attributes + */ public class NodeAttributes implements ToXContentObject { public static final ParseField ID = new ParseField("id"); @@ -57,22 +60,37 @@ public NodeAttributes(String id, String name, String ephemeralId, String transpo this.attributes = Collections.unmodifiableMap(attributes); } + /** + * The unique identifier of the node. + */ public String getId() { return id; } + /** + * The node name. + */ public String getName() { return name; } + /** + * The ephemeral id of the node. + */ public String getEphemeralId() { return ephemeralId; } + /** + * The host and port where transport HTTP connections are accepted. + */ public String getTransportAddress() { return transportAddress; } + /** + * Additional attributes related to this node e.g., {"ml.max_open_jobs": "10"}. + */ public Map getAttributes() { return attributes; } diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java index b9ef7af9f104b..2ad4df6462c4a 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java @@ -83,10 +83,54 @@ public ForecastStats(long total, Map statusCounts) { this.total = total; this.forecastedJobs = total > 0 ? 1 : 0; - this.memoryStats = Objects.requireNonNull(memoryStats); - this.recordStats = Objects.requireNonNull(recordStats); - this.runtimeStats = Objects.requireNonNull(runtimeStats); - this.statusCounts = Collections.unmodifiableMap(statusCounts); + if (total > 0) { + this.memoryStats = Objects.requireNonNull(memoryStats); + this.recordStats = Objects.requireNonNull(recordStats); + this.runtimeStats = Objects.requireNonNull(runtimeStats); + this.statusCounts = Collections.unmodifiableMap(statusCounts); + } + } + + /** + * The number of forecasts currently available for this model. + */ + public long getTotal() { + return total; + } + + /** + * The number of jobs that have at least one forecast. + */ + public long getForecastedJobs() { + return forecastedJobs; + } + + /** + * Statistics about the memory usage: minimum, maximum, average and total. + */ + public SimpleStats getMemoryStats() { + return memoryStats; + } + + /** + * Statistics about the number of forecast records: minimum, maximum, average and total. + */ + public SimpleStats getRecordStats() { + return recordStats; + } + + /** + * Statistics about the forecast runtime in milliseconds: minimum, maximum, average and total + */ + public SimpleStats getRuntimeStats() { + return runtimeStats; + } + + /** + * Counts per forecast status, for example: {"finished" : 2}. + */ + public Map getStatusCounts() { + return statusCounts; } @Override diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java index 82446e77e058f..c2381ae3f3d5b 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java @@ -16,6 +16,10 @@ import java.io.IOException; import java.util.Objects; +/** + * Class containing the statistics for a Machine Learning job. + * + */ public class JobStats implements ToXContentObject { private static final ParseField DATA_COUNTS = new ParseField("data_counts"); @@ -62,9 +66,9 @@ public class JobStats implements ToXContentObject { PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), NodeAttributes.PARSER, NODE); PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), ASSIGNMENT_EXPLANATION); PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), - (p) -> TimeValue.parseTimeValue(p.text(), OPEN_TIME.getPreferredName()), + (p, c) -> TimeValue.parseTimeValue(p.textOrNull(), OPEN_TIME.getPreferredName()), OPEN_TIME, - ObjectParser.ValueType.VALUE); + ObjectParser.ValueType.STRING_OR_NULL); } @@ -90,34 +94,63 @@ public class JobStats implements ToXContentObject { this.openTime = opentime; } + /** + * The jobId referencing the job for these statistics + */ public String getJobId() { return jobId; } + /** + * An object that describes the number of records processed and any related error counts + * See {@link DataCounts} + */ public DataCounts getDataCounts() { return dataCounts; } + /** + * An object that provides information about the size and contents of the model. + * See {@link ModelSizeStats} + */ public ModelSizeStats getModelSizeStats() { return modelSizeStats; } + /** + * An object that provides statistical information about forecasts of this job. + * See {@link ForecastStats} + */ public ForecastStats getForecastStats() { return forecastStats; } + /** + * The status of the job + * See {@link JobState} + */ public JobState getState() { return state; } + /** + * For open jobs only, contains information about the node where the job runs + * See {@link NodeAttributes} + */ public NodeAttributes getNode() { return node; } + /** + * For open jobs only, contains messages relating to the selection of a node to run the job. + */ public String getAssignmentExplanation() { return assignmentExplanation; } + /** + * For open jobs only, the elapsed time for which the job has been open + */ public TimeValue getOpenTime() { return openTime; } diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java new file mode 100644 index 0000000000000..8cd90399039c1 --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java @@ -0,0 +1,69 @@ +/* + * 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.protocol.xpack.ml; + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GetJobsStatsRequestTests extends AbstractXContentTestCase { + + public void testAllJobsRequest() { + GetJobsStatsRequest request = GetJobsStatsRequest.allJobsStats(); + + assertEquals(request.getJobIds().size(), 1); + assertEquals(request.getJobIds().get(0), "_all"); + } + + public void testNewWithJobId() { + Exception exception = expectThrows(NullPointerException.class, () -> new GetJobsStatsRequest("job",null)); + assertEquals(exception.getMessage(), "jobIds must not contain null values"); + } + + @Override + protected GetJobsStatsRequest createTestInstance() { + int jobCount = randomIntBetween(0, 10); + List jobIds = new ArrayList<>(jobCount); + + for (int i = 0; i < jobCount; i++) { + jobIds.add(randomAlphaOfLength(10)); + } + + GetJobsStatsRequest request = new GetJobsStatsRequest(jobIds); + + if (randomBoolean()) { + request.setAllowNoJobs(randomBoolean()); + } + + return request; + } + + @Override + protected GetJobsStatsRequest doParseInstance(XContentParser parser) throws IOException { + return GetJobsStatsRequest.PARSER.parse(parser, null); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } +} diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java new file mode 100644 index 0000000000000..3f95ddccc84f7 --- /dev/null +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java @@ -0,0 +1,53 @@ +/* + * 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.protocol.xpack.ml; + +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; +import org.elasticsearch.protocol.xpack.ml.job.stats.JobStatsTests; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class GetJobsStatsResponseTests extends AbstractXContentTestCase { + + @Override + protected GetJobsStatsResponse createTestInstance() { + + int count = randomIntBetween(1, 5); + List results = new ArrayList<>(count); + for(int i = 0; i < count; i++) { + results.add(JobStatsTests.createRandomInstance()); + } + + return new GetJobsStatsResponse(results, count); + } + + @Override + protected GetJobsStatsResponse doParseInstance(XContentParser parser) throws IOException { + return GetJobsStatsResponse.fromXContent(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } +} diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java index 3329eee6cfa12..bc510a8ab1c53 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java @@ -35,8 +35,8 @@ public class JobStatsTests extends AbstractXContentTestCase { - @Override - protected JobStats createTestInstance() { + + public static JobStats createRandomInstance() { String jobId = JobTests.randomValidJobId(); JobState state = randomFrom(JobState.CLOSING, JobState.CLOSED, JobState.OPENED, JobState.FAILED, JobState.OPENING); DataCounts dataCounts = DataCountsTests.createTestInstance(jobId); @@ -50,6 +50,11 @@ protected JobStats createTestInstance() { return new JobStats(jobId, dataCounts, state, modelSizeStats, forecastStats, nodeAttributes, assigmentExplanation, openTime); } + @Override + protected JobStats createTestInstance() { + return createRandomInstance(); + } + @Override protected JobStats doParseInstance(XContentParser parser) throws IOException { return JobStats.PARSER.parse(parser, null); From c8d3f5a2a355c8942ade0c5f4004a122d111384c Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Mon, 27 Aug 2018 13:07:42 -0500 Subject: [PATCH 04/11] Minor syntax changes and adding license headers --- .../client/MachineLearningClient.java | 2 +- .../client/MachineLearningGetResultsIT.java | 5 --- .../client/MachineLearningIT.java | 10 ++--- .../high-level/ml/get-job-stats.asciidoc | 7 ++-- .../xpack/ml/GetJobsStatsRequest.java | 22 +++++++++- .../xpack/ml/GetJobsStatsResponse.java | 18 ++++++++ .../protocol/xpack/ml/NodeAttributes.java | 20 ++++++++- .../xpack/ml/job/config/JobState.java | 2 +- .../xpack/ml/job/stats/ForecastStats.java | 15 ++++--- .../protocol/xpack/ml/job/stats/JobStats.java | 42 ++++++++++++++----- .../xpack/ml/job/stats/SimpleStats.java | 1 - .../xpack/ml/GetJobsStatsRequestTests.java | 2 +- .../xpack/ml/NodeAttributesTests.java | 18 ++++++++ .../ml/job/stats/ForecastStatsTests.java | 5 ++- .../xpack/ml/job/stats/JobStatsTests.java | 1 - 15 files changed, 131 insertions(+), 39 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index e58c084d13300..de132a7f1d274 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -314,7 +314,7 @@ public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOpti * *

* For additional info - * see + * see *

* @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java index 99a2356b67e4f..a4f83c347ad13 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningGetResultsIT.java @@ -194,11 +194,6 @@ public void testGetBuckets() throws IOException { } } - public void testGetJobsStats() throws IOException { - - } - - private static class BucketStats { // score < 50.0 private long minorCount; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index 004fce85a99f6..b37efb6dae168 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -159,7 +159,7 @@ public void testGetJobsStats() throws Exception { GetJobsStatsRequest request = new GetJobsStatsRequest(jobId1, jobId2); Thread.sleep(1000); - // Test getting specific jobs stats + // Test getting specific GetJobsStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertEquals(2, response.count()); @@ -173,7 +173,7 @@ public void testGetJobsStats() throws Exception { } } - // Test getting all jobs explicitly + // Test getting all explicitly request = GetJobsStatsRequest.allJobsStats(); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); @@ -181,21 +181,21 @@ public void testGetJobsStats() throws Exception { assertTrue(response.jobs().size() >= 2L); assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); - // Test getting all jobs implicitly + // Test getting all implicitly response = execute(new GetJobsStatsRequest(), machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); assertTrue(response.jobs().size() >= 2L); assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); - // Test getting all jobs with wildcard + // Test getting all with wildcard request = new GetJobsStatsRequest("ml-get-job-stats-test-id-*"); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); assertTrue(response.jobs().size() >= 2L); assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); - // Test when allow no jobs is false + // Test when allow_no_jobs is false final GetJobsStatsRequest erroredRequest = new GetJobsStatsRequest("jobs-that-do-not-exist*"); erroredRequest.setAllowNoJobs(false); ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, diff --git a/docs/java-rest/high-level/ml/get-job-stats.asciidoc b/docs/java-rest/high-level/ml/get-job-stats.asciidoc index d517184212024..2a5166e4156cf 100644 --- a/docs/java-rest/high-level/ml/get-job-stats.asciidoc +++ b/docs/java-rest/high-level/ml/get-job-stats.asciidoc @@ -1,16 +1,17 @@ [[java-rest-high-x-pack-ml-get-job-stats]] === Get Job Stats API -The Get Job Stats API provides the ability to get {ml} job's statistics in the cluster. +The Get Job Stats API provides the ability to get any number of + {ml} job's statistics in the cluster. It accepts a `GetJobsStatsRequest` object and responds with a `GetJobsStatsResponse` object. [[java-rest-high-x-pack-ml-get-job-stats-request]] ==== Get Job Stats Request -A `GetJobsStatsRequest` object gets can have any number of `jobId` +A `GetJobsStatsRequest` object can have any number of `jobId` entries. However, they all must be non-null. An empty list is the same as -requesting for all jobs. +requesting statistics for all jobs. ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java index 182740e1d2188..32775da147c10 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java @@ -1,3 +1,21 @@ +/* + * 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.protocol.xpack.ml; import org.elasticsearch.action.ActionRequest; @@ -19,8 +37,8 @@ /** * Request object to get {@link org.elasticsearch.protocol.xpack.ml.job.stats.JobStats} objects with the matching `jobId`s * - * `_all` explicitly gets all the jobs in the cluster - * An empty request (no `jobId`s) implicitly gets all the jobs in the cluster + * `_all` explicitly gets all the jobs' statistics in the cluster + * An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster */ public class GetJobsStatsRequest extends ActionRequest implements ToXContentObject { diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java index d6e4dc334834d..28af9cf57cd8d 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java @@ -1,3 +1,21 @@ +/* + * 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.protocol.xpack.ml; import org.elasticsearch.common.ParseField; diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java index e2d324a6bbdfa..aae4d96975aa2 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java @@ -1,3 +1,21 @@ +/* + * 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.protocol.xpack.ml; import org.elasticsearch.common.ParseField; @@ -12,7 +30,7 @@ import java.util.Objects; /** - * Class containing an Elastic Node's attributes + * A Pojo class containing an Elastic Node's attributes */ public class NodeAttributes implements ToXContentObject { diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java index 737a26996a18d..1556de5bf072f 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java @@ -22,7 +22,7 @@ /** * Jobs whether running or complete are in one of these states. - * When a job is created it is initialised in to the state closed + * When a job is created it is initialised in the state closed * i.e. it is not running. */ public enum JobState { diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java index 2ad4df6462c4a..bfe54e2c3f7cd 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java @@ -155,17 +155,20 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj == null) { - return false; + if (this == obj) { + return true; } - if (getClass() != obj.getClass()) { + if (obj == null || getClass() != obj.getClass()) { return false; } ForecastStats other = (ForecastStats) obj; - return Objects.equals(total, other.total) && Objects.equals(forecastedJobs, other.forecastedJobs) - && Objects.equals(memoryStats, other.memoryStats) && Objects.equals(recordStats, other.recordStats) - && Objects.equals(runtimeStats, other.runtimeStats) && Objects.equals(statusCounts, other.statusCounts); + return Objects.equals(total, other.total) && + Objects.equals(forecastedJobs, other.forecastedJobs) && + Objects.equals(memoryStats, other.memoryStats) && + Objects.equals(recordStats, other.recordStats) && + Objects.equals(runtimeStats, other.runtimeStats) && + Objects.equals(statusCounts, other.statusCounts); } } diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java index c2381ae3f3d5b..ff59b7eb66d9a 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java @@ -1,3 +1,21 @@ +/* + * 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.protocol.xpack.ml.job.stats; import org.elasticsearch.common.Nullable; @@ -186,20 +204,22 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (obj == null) { - return false; + if (this == obj) { + return true; } - if (getClass() != obj.getClass()) { + + if (obj == null || getClass() != obj.getClass()) { return false; } + JobStats other = (JobStats) obj; - return Objects.equals(jobId, other.jobId) - && Objects.equals(this.dataCounts, other.dataCounts) - && Objects.equals(this.modelSizeStats, other.modelSizeStats) - && Objects.equals(this.forecastStats, other.forecastStats) - && Objects.equals(this.state, other.state) - && Objects.equals(this.node, other.node) - && Objects.equals(this.assignmentExplanation, other.assignmentExplanation) - && Objects.equals(this.openTime, other.openTime); + return Objects.equals(jobId, other.jobId) && + Objects.equals(this.dataCounts, other.dataCounts) && + Objects.equals(this.modelSizeStats, other.modelSizeStats) && + Objects.equals(this.forecastStats, other.forecastStats) && + Objects.equals(this.state, other.state) && + Objects.equals(this.node, other.node) && + Objects.equals(this.assignmentExplanation, other.assignmentExplanation) && + Objects.equals(this.openTime, other.openTime); } } diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java index e50b363e92814..ea08692d80b35 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java +++ b/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java @@ -92,7 +92,6 @@ public boolean equals(Object obj) { return true; } - if (obj == null || getClass() != obj.getClass()) { return false; } diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java index 8cd90399039c1..ff46e46a5f333 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java @@ -35,7 +35,7 @@ public void testAllJobsRequest() { } public void testNewWithJobId() { - Exception exception = expectThrows(NullPointerException.class, () -> new GetJobsStatsRequest("job",null)); + Exception exception = expectThrows(NullPointerException.class, () -> new GetJobsStatsRequest("job", null)); assertEquals(exception.getMessage(), "jobIds must not contain null values"); } diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java index 8f262f86a62c7..298359996ac03 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java @@ -1,3 +1,21 @@ +/* + * 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.protocol.xpack.ml; import org.elasticsearch.common.xcontent.XContentParser; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java index 1681defbbde6c..2169a1b44221e 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java @@ -29,7 +29,10 @@ public class ForecastStatsTests extends AbstractXContentTestCase @Override public ForecastStats createTestInstance() { - return createForecastStats(1, 22); + if (randomBoolean()) { + return createForecastStats(1, 22); + } + return new ForecastStats(0, null,null,null,null); } @Override diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java index bc510a8ab1c53..80e07259a00fd 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java +++ b/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java @@ -35,7 +35,6 @@ public class JobStatsTests extends AbstractXContentTestCase { - public static JobStats createRandomInstance() { String jobId = JobTests.randomValidJobId(); JobState state = randomFrom(JobState.CLOSING, JobState.CLOSED, JobState.OPENED, JobState.FAILED, JobState.OPENING); From da0c1bd58dbc09089e1272045c721789f77122cd Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Mon, 27 Aug 2018 15:35:44 -0500 Subject: [PATCH 05/11] minor comment change --- .../java/org/elasticsearch/client/MachineLearningClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index de132a7f1d274..5b30ea49378d0 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -293,7 +293,7 @@ public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, A * *

* For additional info - * see + * see Get Job stats docs *

* @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized @@ -314,7 +314,7 @@ public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOpti * *

* For additional info - * see + * see Get Job stats docs *

* @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized From 79dd816ef0a69a82e32c558a11786033d7f9e2e0 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Wed, 29 Aug 2018 08:37:41 -0500 Subject: [PATCH 06/11] Moving to client package, minor changes --- .../client/MLRequestConverters.java | 2 +- .../client/MachineLearningClient.java | 7 ++++--- .../client}/ml/GetJobsStatsRequest.java | 4 ++-- .../client}/ml/GetJobsStatsResponse.java | 6 +++--- .../client}/ml/NodeAttributes.java | 2 +- .../client}/ml/job/config/JobState.java | 2 +- .../client}/ml/job/stats/ForecastStats.java | 2 +- .../client}/ml/job/stats/JobStats.java | 12 ++++++------ .../client}/ml/job/stats/SimpleStats.java | 2 +- .../client/MLRequestConvertersTests.java | 2 +- .../client/MachineLearningIT.java | 8 ++++---- .../documentation/MlClientDocumentationIT.java | 6 +++--- .../client}/ml/GetJobsStatsRequestTests.java | 2 +- .../client}/ml/GetJobsStatsResponseTests.java | 6 +++--- .../client}/ml/NodeAttributesTests.java | 2 +- .../ml/job/stats/ForecastStatsTests.java | 2 +- .../client}/ml/job/stats/JobStatsTests.java | 18 +++++++++--------- .../client}/ml/job/stats/SimpleStatsTests.java | 2 +- .../high-level/supported-apis.asciidoc | 4 ++-- 19 files changed, 46 insertions(+), 45 deletions(-) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/GetJobsStatsRequest.java (96%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/GetJobsStatsResponse.java (93%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/NodeAttributes.java (99%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/job/config/JobState.java (95%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/job/stats/ForecastStats.java (99%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/job/stats/JobStats.java (95%) rename {x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/main/java/org/elasticsearch/client}/ml/job/stats/SimpleStats.java (98%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/GetJobsStatsRequestTests.java (98%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/GetJobsStatsResponseTests.java (90%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/NodeAttributesTests.java (97%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/job/stats/ForecastStatsTests.java (97%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/job/stats/JobStatsTests.java (80%) rename {x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack => client/rest-high-level/src/test/java/org/elasticsearch/client}/ml/job/stats/SimpleStatsTests.java (96%) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java index 743211765f149..573e1c2bffa3e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java @@ -31,7 +31,7 @@ import org.elasticsearch.client.ml.OpenJobRequest; import org.elasticsearch.client.ml.PutJobRequest; import org.elasticsearch.common.Strings; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobsStatsRequest; import java.io.IOException; diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index 6c9662c3ad204..f007818726895 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -19,8 +19,9 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; +import org.elasticsearch.client.ml.job.stats.JobStats; +import org.elasticsearch.client.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobsStatsResponse; import org.elasticsearch.client.ml.CloseJobRequest; import org.elasticsearch.client.ml.CloseJobResponse; import org.elasticsearch.client.ml.DeleteJobRequest; @@ -298,7 +299,7 @@ public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, A * @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized * @return {@link GetJobsStatsResponse} response object containing - * the {@link org.elasticsearch.protocol.xpack.ml.job.stats.JobStats} objects and the number of jobs found + * the {@link JobStats} objects and the number of jobs found * @throws IOException when there is a serialization issue sending the request or receiving the response */ public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOptions options) throws IOException { diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java similarity index 96% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java index 32775da147c10..df5a88db288b5 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; @@ -35,7 +35,7 @@ /** - * Request object to get {@link org.elasticsearch.protocol.xpack.ml.job.stats.JobStats} objects with the matching `jobId`s + * Request object to get {@link org.elasticsearch.client.ml.job.stats.JobStats} objects with the matching `jobId`s * * `_all` explicitly gets all the jobs' statistics in the cluster * An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java similarity index 93% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java index 28af9cf57cd8d..92a650c327047 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java @@ -16,13 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; +import org.elasticsearch.client.ml.job.stats.JobStats; import java.io.IOException; import java.util.List; @@ -44,7 +44,7 @@ public class GetJobsStatsResponse extends AbstractResultResponse { static { PARSER.declareObjectArray(constructorArg(), JobStats.PARSER, RESULTS_FIELD); - PARSER.declareLong(constructorArg(), AbstractResultResponse.COUNT); + PARSER.declareLong(constructorArg(), COUNT); } GetJobsStatsResponse(List jobStats, long count) { diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java similarity index 99% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java index aae4d96975aa2..892df340abd6b 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/NodeAttributes.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/NodeAttributes.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ConstructingObjectParser; diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/config/JobState.java similarity index 95% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/config/JobState.java index 1556de5bf072f..32684bd7e62b4 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/config/JobState.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/config/JobState.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.config; +package org.elasticsearch.client.ml.job.config; import java.util.Locale; diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java similarity index 99% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java index bfe54e2c3f7cd..f98fe5640273e 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ConstructingObjectParser; diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java similarity index 95% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java index ff59b7eb66d9a..ac0051b84dbab 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java @@ -16,8 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; +import org.elasticsearch.client.ml.job.config.Job; +import org.elasticsearch.client.ml.job.config.JobState; +import org.elasticsearch.client.ml.job.process.DataCounts; +import org.elasticsearch.client.ml.job.process.ModelSizeStats; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.unit.TimeValue; @@ -25,11 +29,7 @@ import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.protocol.xpack.ml.job.config.Job; -import org.elasticsearch.protocol.xpack.ml.job.config.JobState; -import org.elasticsearch.protocol.xpack.ml.job.process.DataCounts; -import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStats; -import org.elasticsearch.protocol.xpack.ml.NodeAttributes; +import org.elasticsearch.client.ml.NodeAttributes; import java.io.IOException; import java.util.Objects; diff --git a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java similarity index 98% rename from x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java index ea08692d80b35..f428f28a7c043 100644 --- a/x-pack/protocol/src/main/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ConstructingObjectParser; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java index 7aecd71e70cfd..015b0051ffc5e 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java @@ -36,7 +36,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.json.JsonXContent; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobsStatsRequest; import org.elasticsearch.test.ESTestCase; import java.io.ByteArrayOutputStream; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index d2413a7cb89a2..023c3fd8b70ee 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -21,10 +21,10 @@ import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; -import org.elasticsearch.protocol.xpack.ml.job.config.JobState; -import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; +import org.elasticsearch.client.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobsStatsResponse; +import org.elasticsearch.client.ml.job.config.JobState; +import org.elasticsearch.client.ml.job.stats.JobStats; import org.elasticsearch.client.ml.CloseJobRequest; import org.elasticsearch.client.ml.CloseJobResponse; import org.elasticsearch.client.ml.DeleteJobRequest; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index 1c317b0fc0a61..d73c2e54796ea 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -47,9 +47,9 @@ import org.elasticsearch.client.ml.job.util.PageParams; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsRequest; -import org.elasticsearch.protocol.xpack.ml.GetJobsStatsResponse; -import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; +import org.elasticsearch.client.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobsStatsResponse; +import org.elasticsearch.client.ml.job.stats.JobStats; import org.junit.After; import java.io.IOException; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java similarity index 98% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java index ff46e46a5f333..d91f5d80e9c1d 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractXContentTestCase; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java similarity index 90% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java index 3f95ddccc84f7..a643239d4b580 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/GetJobsStatsResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java @@ -16,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.protocol.xpack.ml.job.stats.JobStats; -import org.elasticsearch.protocol.xpack.ml.job.stats.JobStatsTests; +import org.elasticsearch.client.ml.job.stats.JobStats; +import org.elasticsearch.client.ml.job.stats.JobStatsTests; import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java similarity index 97% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java index 298359996ac03..4390050769b41 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/NodeAttributesTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml; +package org.elasticsearch.client.ml; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractXContentTestCase; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java similarity index 97% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java index 2169a1b44221e..aa41189c8b6c5 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/ForecastStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractXContentTestCase; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java similarity index 80% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java index 80e07259a00fd..c008b1b236bdc 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/JobStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java @@ -16,18 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; +import org.elasticsearch.client.ml.NodeAttributes; +import org.elasticsearch.client.ml.NodeAttributesTests; +import org.elasticsearch.client.ml.job.process.DataCounts; +import org.elasticsearch.client.ml.job.process.DataCountsTests; +import org.elasticsearch.client.ml.job.process.ModelSizeStats; +import org.elasticsearch.client.ml.job.process.ModelSizeStatsTests; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.protocol.xpack.ml.NodeAttributes; -import org.elasticsearch.protocol.xpack.ml.NodeAttributesTests; -import org.elasticsearch.protocol.xpack.ml.job.config.JobState; -import org.elasticsearch.protocol.xpack.ml.job.config.JobTests; -import org.elasticsearch.protocol.xpack.ml.job.process.DataCounts; -import org.elasticsearch.protocol.xpack.ml.job.process.DataCountsTests; -import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStats; -import org.elasticsearch.protocol.xpack.ml.job.process.ModelSizeStatsTests; +import org.elasticsearch.client.ml.job.config.JobState; +import org.elasticsearch.client.ml.job.config.JobTests; import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; diff --git a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java similarity index 96% rename from x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java index 6f4d9c54e3b6b..a1d559023cb83 100644 --- a/x-pack/protocol/src/test/java/org/elasticsearch/protocol/xpack/ml/job/stats/SimpleStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.elasticsearch.protocol.xpack.ml.job.stats; +package org.elasticsearch.client.ml.job.stats; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractXContentTestCase; diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 3f5f903c61ebe..b5431f2f04969 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -211,16 +211,16 @@ The Java High Level REST Client supports the following Machine Learning APIs: * <> * <> * <> -* <> * <> +* <> include::ml/put-job.asciidoc[] include::ml/get-job.asciidoc[] include::ml/delete-job.asciidoc[] include::ml/open-job.asciidoc[] include::ml/close-job.asciidoc[] -include::ml/get-buckets.asciidoc[] include::ml/get-job-stats.asciidoc[] +include::ml/get-buckets.asciidoc[] == Migration APIs From a6512a4a76e4adb9ea3ed4df13758617a7adfa1a Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Wed, 29 Aug 2018 14:54:01 -0500 Subject: [PATCH 07/11] Addressing PR comments --- .../client/MachineLearningClient.java | 2 +- .../client/ml/GetJobsStatsRequest.java | 13 +++++------ .../client/ml/GetJobsStatsResponse.java | 2 +- .../client/ml/job/stats/ForecastStats.java | 22 +++++++++---------- .../client/ml/job/stats/JobStats.java | 14 ++++++------ .../client/ml/job/stats/SimpleStats.java | 8 +++---- .../client/MachineLearningIT.java | 20 ++++++++--------- .../MlClientDocumentationIT.java | 6 ++--- .../client/ml/GetJobsStatsRequestTests.java | 4 ++-- .../high-level/ml/get-job-stats.asciidoc | 2 +- 10 files changed, 46 insertions(+), 47 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index 1fd582adf475c..cc395c34e066e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -292,7 +292,7 @@ public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, A } /** - * Gets one or more Machine Learning job statistics. + * Gets usage statistics for one or more Machine Learning jobs * *

* For additional info diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java index df5a88db288b5..76fa6bb53298e 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java @@ -20,6 +20,7 @@ import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.client.ml.job.config.Job; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.ConstructingObjectParser; @@ -35,25 +36,23 @@ /** - * Request object to get {@link org.elasticsearch.client.ml.job.stats.JobStats} objects with the matching `jobId`s + * Request object to get {@link org.elasticsearch.client.ml.job.stats.JobStats} by their respective jobIds * * `_all` explicitly gets all the jobs' statistics in the cluster * An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster */ public class GetJobsStatsRequest extends ActionRequest implements ToXContentObject { - public static final ParseField JOB_ID = new ParseField("job_id"); public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs"); @SuppressWarnings("unchecked") public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( - "get_jobs_stats_request", - true, a -> new GetJobsStatsRequest((List) a[0])); + "get_jobs_stats_request", a -> new GetJobsStatsRequest((List) a[0])); static { PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())), - JOB_ID, ObjectParser.ValueType.STRING_ARRAY); + Job.ID, ObjectParser.ValueType.STRING_ARRAY); PARSER.declareBoolean(GetJobsStatsRequest::setAllowNoJobs, ALLOW_NO_JOBS); } @@ -67,7 +66,7 @@ public class GetJobsStatsRequest extends ActionRequest implements ToXContentObje * * @return a {@link GetJobsStatsRequest} for all existing jobs */ - public static GetJobsStatsRequest allJobsStats(){ + public static GetJobsStatsRequest getAllJobsStatsRequest(){ return new GetJobsStatsRequest(ALL_JOBS); } @@ -137,7 +136,7 @@ public ActionRequestValidationException validate() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.field(JOB_ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds)); + builder.field(Job.ID.getPreferredName(), Strings.collectionToCommaDelimitedString(jobIds)); if (allowNoJobs != null) { builder.field(ALLOW_NO_JOBS.getPreferredName(), allowNoJobs); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java index 92a650c327047..06b30e7b6b6ef 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java @@ -54,7 +54,7 @@ public class GetJobsStatsResponse extends AbstractResultResponse { /** * The collection of {@link JobStats} objects found in the query */ - public List jobs() { + public List jobStats() { return results; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java index f98fe5640273e..a6b41beca8366 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/ForecastStats.java @@ -37,10 +37,10 @@ public class ForecastStats implements ToXContentObject { public static final ParseField TOTAL = new ParseField("total"); public static final ParseField FORECASTED_JOBS = new ParseField("forecasted_jobs"); - public static final ParseField MEMORY = new ParseField("memory_bytes"); - public static final ParseField RUNTIME = new ParseField("processing_time_ms"); + public static final ParseField MEMORY_BYTES = new ParseField("memory_bytes"); + public static final ParseField PROCESSING_TIME_MS = new ParseField("processing_time_ms"); public static final ParseField RECORDS = new ParseField("records"); - public static final ParseField STATUSES = new ParseField("status"); + public static final ParseField STATUS = new ParseField("status"); @SuppressWarnings("unchecked") public static final ConstructingObjectParser PARSER = @@ -58,19 +58,19 @@ public class ForecastStats implements ToXContentObject { static { PARSER.declareLong(ConstructingObjectParser.constructorArg(), TOTAL); - PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, MEMORY); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, MEMORY_BYTES); PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, RECORDS); - PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, RUNTIME); + PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), SimpleStats.PARSER, PROCESSING_TIME_MS); PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(), p -> { Map counts = new HashMap<>(); p.map().forEach((key, value) -> counts.put(key, ((Number)value).longValue())); return counts; - }, STATUSES, ObjectParser.ValueType.OBJECT); + }, STATUS, ObjectParser.ValueType.OBJECT); } - private long total; - private long forecastedJobs; + private final long total; + private final long forecastedJobs; private SimpleStats memoryStats; private SimpleStats recordStats; private SimpleStats runtimeStats; @@ -140,10 +140,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.field(FORECASTED_JOBS.getPreferredName(), forecastedJobs); if (total > 0) { - builder.field(MEMORY.getPreferredName(), memoryStats); + builder.field(MEMORY_BYTES.getPreferredName(), memoryStats); builder.field(RECORDS.getPreferredName(), recordStats); - builder.field(RUNTIME.getPreferredName(), runtimeStats); - builder.field(STATUSES.getPreferredName(), statusCounts); + builder.field(PROCESSING_TIME_MS.getPreferredName(), runtimeStats); + builder.field(STATUS.getPreferredName(), statusCounts); } return builder.endObject(); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java index ac0051b84dbab..df5be4aa4c5cc 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/JobStats.java @@ -91,13 +91,13 @@ public class JobStats implements ToXContentObject { private final String jobId; - private DataCounts dataCounts; - private JobState state; - private ModelSizeStats modelSizeStats; - private ForecastStats forecastStats; - private NodeAttributes node; - private String assignmentExplanation; - private TimeValue openTime; + private final DataCounts dataCounts; + private final JobState state; + private final ModelSizeStats modelSizeStats; + private final ForecastStats forecastStats; + private final NodeAttributes node; + private final String assignmentExplanation; + private final TimeValue openTime; JobStats(String jobId, DataCounts dataCounts, JobState state, @Nullable ModelSizeStats modelSizeStats, @Nullable ForecastStats forecastStats, @Nullable NodeAttributes node, diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java index f428f28a7c043..f4c8aa0fa3b29 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/job/stats/SimpleStats.java @@ -53,10 +53,10 @@ public class SimpleStats implements ToXContentObject { PARSER.declareDouble(ConstructingObjectParser.constructorArg(), AVG); } - private double total; - private double min; - private double max; - private double avg; + private final double total; + private final double min; + private final double max; + private final double avg; SimpleStats(double total, double min, double max, double avg) { this.total = total; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index 023c3fd8b70ee..9b80d27a600f2 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -163,9 +163,9 @@ public void testGetJobsStats() throws Exception { GetJobsStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertEquals(2, response.count()); - assertThat(response.jobs(), hasSize(2)); - assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), containsInAnyOrder(jobId1, jobId2)); - for (JobStats stats : response.jobs()) { + assertThat(response.jobStats(), hasSize(2)); + assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), containsInAnyOrder(jobId1, jobId2)); + for (JobStats stats : response.jobStats()) { if (stats.getJobId().equals(jobId1)) { assertEquals(JobState.OPENED, stats.getState()); } else { @@ -174,26 +174,26 @@ public void testGetJobsStats() throws Exception { } // Test getting all explicitly - request = GetJobsStatsRequest.allJobsStats(); + request = GetJobsStatsRequest.getAllJobsStatsRequest(); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); - assertTrue(response.jobs().size() >= 2L); - assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + assertTrue(response.jobStats().size() >= 2L); + assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test getting all implicitly response = execute(new GetJobsStatsRequest(), machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); - assertTrue(response.jobs().size() >= 2L); - assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + assertTrue(response.jobStats().size() >= 2L); + assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test getting all with wildcard request = new GetJobsStatsRequest("ml-get-job-stats-test-id-*"); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); - assertTrue(response.jobs().size() >= 2L); - assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); + assertTrue(response.jobStats().size() >= 2L); + assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test when allow_no_jobs is false final GetJobsStatsRequest erroredRequest = new GetJobsStatsRequest("jobs-that-do-not-exist*"); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index df930294dadfb..c1ff9597c64a5 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -479,12 +479,12 @@ public void testGetJobStats() throws Exception { //tag::x-pack-ml-get-job-stats-execute GetJobsStatsResponse response = client.machineLearning().getJobStats(request, RequestOptions.DEFAULT); long numberOfJobsStats = response.count(); //<1> - List jobsStats = response.jobs(); //<2> + List jobsStats = response.jobStats(); //<2> //end::x-pack-ml-get-job-stats-execute assertEquals(2, response.count()); - assertThat(response.jobs(), hasSize(2)); - assertThat(response.jobs().stream().map(JobStats::getJobId).collect(Collectors.toList()), + assertThat(response.jobStats(), hasSize(2)); + assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), containsInAnyOrder(job.getId(), secondJob.getId())); } { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java index d91f5d80e9c1d..ca0809b834e06 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java @@ -28,7 +28,7 @@ public class GetJobsStatsRequestTests extends AbstractXContentTestCase { public void testAllJobsRequest() { - GetJobsStatsRequest request = GetJobsStatsRequest.allJobsStats(); + GetJobsStatsRequest request = GetJobsStatsRequest.getAllJobsStatsRequest(); assertEquals(request.getJobIds().size(), 1); assertEquals(request.getJobIds().get(0), "_all"); @@ -64,6 +64,6 @@ protected GetJobsStatsRequest doParseInstance(XContentParser parser) throws IOEx @Override protected boolean supportsUnknownFields() { - return true; + return false; } } diff --git a/docs/java-rest/high-level/ml/get-job-stats.asciidoc b/docs/java-rest/high-level/ml/get-job-stats.asciidoc index 2a5166e4156cf..4f6e24f9fd0ec 100644 --- a/docs/java-rest/high-level/ml/get-job-stats.asciidoc +++ b/docs/java-rest/high-level/ml/get-job-stats.asciidoc @@ -32,7 +32,7 @@ in the `RestHighLevelClient` object, accessed via the `machineLearningClient()` include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-execute] -------------------------------------------------- <1> `getCount()` from the `GetJobsStatsResponse` indicates the number of jobs statistics found -<2> `getJobs()` is the collection of {ml} `JobStats` objects found +<2> `getJobStats()` is the collection of {ml} `JobStats` objects found [[java-rest-high-x-pack-ml-get-job-stats-execution-async]] ==== Asynchronous Execution From 2c9e23133e205b67388e7233a84ec32ec535766d Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Wed, 29 Aug 2018 15:32:40 -0500 Subject: [PATCH 08/11] removing bad sleep --- .../test/java/org/elasticsearch/client/MachineLearningIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index 9b80d27a600f2..29acb52c8c2c7 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -158,7 +158,6 @@ public void testGetJobsStats() throws Exception { GetJobsStatsRequest request = new GetJobsStatsRequest(jobId1, jobId2); - Thread.sleep(1000); // Test getting specific GetJobsStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); From b7618847ed7f8d676beaa7dc0db76181669bca97 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Thu, 30 Aug 2018 14:49:27 -0500 Subject: [PATCH 09/11] addressing minor comment around test methods --- .../client/ml/job/stats/ForecastStatsTests.java | 16 ++++++++-------- .../client/ml/job/stats/JobStatsTests.java | 2 +- .../client/ml/job/stats/SimpleStatsTests.java | 6 +++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java index aa41189c8b6c5..ed36cf531dc5e 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java @@ -30,7 +30,7 @@ public class ForecastStatsTests extends AbstractXContentTestCase @Override public ForecastStats createTestInstance() { if (randomBoolean()) { - return createForecastStats(1, 22); + return createRandom(1, 22); } return new ForecastStats(0, null,null,null,null); } @@ -45,13 +45,13 @@ protected boolean supportsUnknownFields() { return false; } - public static ForecastStats createForecastStats(long minTotal, long maxTotal) { - return new ForecastStats(randomLongBetween(minTotal, maxTotal), createSimpleStats(), - createSimpleStats(), createSimpleStats(), createCountStats()); - } - - private static SimpleStats createSimpleStats() { - return new SimpleStatsTests().createTestInstance(); + public static ForecastStats createRandom(long minTotal, long maxTotal) { + return new ForecastStats( + randomLongBetween(minTotal, maxTotal), + SimpleStatsTests.createRandom(), + SimpleStatsTests.createRandom(), + SimpleStatsTests.createRandom(), + createCountStats()); } private static Map createCountStats() { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java index c008b1b236bdc..cc2d4ae732059 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java @@ -41,7 +41,7 @@ public static JobStats createRandomInstance() { DataCounts dataCounts = DataCountsTests.createTestInstance(jobId); ModelSizeStats modelSizeStats = randomBoolean() ? ModelSizeStatsTests.createRandomized() : null; - ForecastStats forecastStats = randomBoolean() ? ForecastStatsTests.createForecastStats(1, 22) : null; + ForecastStats forecastStats = randomBoolean() ? ForecastStatsTests.createRandom(1, 22) : null; NodeAttributes nodeAttributes = randomBoolean() ? NodeAttributesTests.createRandom() : null; String assigmentExplanation = randomBoolean() ? randomAlphaOfLength(10) : null; TimeValue openTime = randomBoolean() ? TimeValue.timeValueMillis(randomIntBetween(1, 10000)) : null; diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java index a1d559023cb83..eb9e47af9ba28 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/SimpleStatsTests.java @@ -28,7 +28,7 @@ public class SimpleStatsTests extends AbstractXContentTestCase { @Override protected SimpleStats createTestInstance() { - return new SimpleStats(randomDouble(), randomDouble(), randomDouble(), randomDouble()); + return createRandom(); } @Override @@ -40,4 +40,8 @@ protected SimpleStats doParseInstance(XContentParser parser) throws IOException protected boolean supportsUnknownFields() { return true; } + + public static SimpleStats createRandom() { + return new SimpleStats(randomDouble(), randomDouble(), randomDouble(), randomDouble()); + } } From a45fbec0b14db526e258a3ad315505994352e545 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Thu, 30 Aug 2018 15:09:30 -0500 Subject: [PATCH 10/11] adding toplevel random fields for tests --- .../org/elasticsearch/client/ml/GetJobResponseTests.java | 8 +++++++- .../org/elasticsearch/client/ml/NodeAttributesTests.java | 8 +++++++- .../client/ml/job/stats/ForecastStatsTests.java | 8 +++++++- .../elasticsearch/client/ml/job/stats/JobStatsTests.java | 8 +++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobResponseTests.java index 181804c9676fe..8cc990730f78e 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobResponseTests.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; public class GetJobResponseTests extends AbstractXContentTestCase { @@ -46,8 +47,13 @@ protected GetJobResponse doParseInstance(XContentParser parser) throws IOExcepti return GetJobResponse.fromXContent(parser); } + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return field -> !field.isEmpty(); + } + @Override protected boolean supportsUnknownFields() { - return false; + return true; } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java index 4390050769b41..cee1710a62232 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/NodeAttributesTests.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; public class NodeAttributesTests extends AbstractXContentTestCase { @@ -51,8 +52,13 @@ protected NodeAttributes doParseInstance(XContentParser parser) throws IOExcepti return NodeAttributes.PARSER.parse(parser, null); } + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return field -> !field.isEmpty(); + } + @Override protected boolean supportsUnknownFields() { - return false; + return true; } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java index ed36cf531dc5e..16dfa305479be 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/ForecastStatsTests.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; public class ForecastStatsTests extends AbstractXContentTestCase { @@ -42,7 +43,12 @@ protected ForecastStats doParseInstance(XContentParser parser) throws IOExceptio @Override protected boolean supportsUnknownFields() { - return false; + return true; + } + + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return field -> !field.isEmpty(); } public static ForecastStats createRandom(long minTotal, long maxTotal) { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java index cc2d4ae732059..5d00f879140e0 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/stats/JobStatsTests.java @@ -31,6 +31,7 @@ import org.elasticsearch.test.AbstractXContentTestCase; import java.io.IOException; +import java.util.function.Predicate; public class JobStatsTests extends AbstractXContentTestCase { @@ -59,8 +60,13 @@ protected JobStats doParseInstance(XContentParser parser) throws IOException { return JobStats.PARSER.parse(parser, null); } + @Override + protected Predicate getRandomFieldsExcludeFilter() { + return field -> !field.isEmpty(); + } + @Override protected boolean supportsUnknownFields() { - return false; + return true; } } From fdf2aa0b50169add672ff39452fe0f77815fa402 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Fri, 31 Aug 2018 11:30:16 -0500 Subject: [PATCH 11/11] addressing minor review comments --- .../client/MLRequestConverters.java | 10 ++++---- .../client/MachineLearningClient.java | 24 +++++++++---------- ...tsRequest.java => GetJobStatsRequest.java} | 20 ++++++++-------- ...Response.java => GetJobStatsResponse.java} | 12 +++++----- .../client/MLRequestConvertersTests.java | 14 +++++------ .../client/MachineLearningIT.java | 18 +++++++------- .../MlClientDocumentationIT.java | 21 +++++++++------- ...ests.java => GetJobStatsRequestTests.java} | 14 +++++------ ...sts.java => GetJobStatsResponseTests.java} | 10 ++++---- .../high-level/ml/get-job-stats.asciidoc | 17 +++++++++---- 10 files changed, 86 insertions(+), 74 deletions(-) rename client/rest-high-level/src/main/java/org/elasticsearch/client/ml/{GetJobsStatsRequest.java => GetJobStatsRequest.java} (85%) rename client/rest-high-level/src/main/java/org/elasticsearch/client/ml/{GetJobsStatsResponse.java => GetJobStatsResponse.java} (83%) rename client/rest-high-level/src/test/java/org/elasticsearch/client/ml/{GetJobsStatsRequestTests.java => GetJobStatsRequestTests.java} (78%) rename client/rest-high-level/src/test/java/org/elasticsearch/client/ml/{GetJobsStatsResponseTests.java => GetJobStatsResponseTests.java} (80%) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java index 559d3332e533d..3fda07e672805 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MLRequestConverters.java @@ -28,11 +28,11 @@ import org.elasticsearch.client.ml.DeleteJobRequest; import org.elasticsearch.client.ml.GetBucketsRequest; import org.elasticsearch.client.ml.GetJobRequest; +import org.elasticsearch.client.ml.GetJobStatsRequest; import org.elasticsearch.client.ml.GetRecordsRequest; import org.elasticsearch.client.ml.OpenJobRequest; import org.elasticsearch.client.ml.PutJobRequest; import org.elasticsearch.common.Strings; -import org.elasticsearch.client.ml.GetJobsStatsRequest; import java.io.IOException; @@ -127,19 +127,19 @@ static Request getBuckets(GetBucketsRequest getBucketsRequest) throws IOExceptio return request; } - static Request getJobsStats(GetJobsStatsRequest getJobsStatsRequest) { + static Request getJobStats(GetJobStatsRequest getJobStatsRequest) { String endpoint = new EndpointBuilder() .addPathPartAsIs("_xpack") .addPathPartAsIs("ml") .addPathPartAsIs("anomaly_detectors") - .addPathPart(Strings.collectionToCommaDelimitedString(getJobsStatsRequest.getJobIds())) + .addPathPart(Strings.collectionToCommaDelimitedString(getJobStatsRequest.getJobIds())) .addPathPartAsIs("_stats") .build(); Request request = new Request(HttpGet.METHOD_NAME, endpoint); RequestConverters.Params params = new RequestConverters.Params(request); - if (getJobsStatsRequest.isAllowNoJobs() != null) { - params.putParam("allow_no_jobs", Boolean.toString(getJobsStatsRequest.isAllowNoJobs())); + if (getJobStatsRequest.isAllowNoJobs() != null) { + params.putParam("allow_no_jobs", Boolean.toString(getJobStatsRequest.isAllowNoJobs())); } return request; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java index cc395c34e066e..59e222c5e4cd3 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/MachineLearningClient.java @@ -19,9 +19,9 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; +import org.elasticsearch.client.ml.GetJobStatsRequest; +import org.elasticsearch.client.ml.GetJobStatsResponse; import org.elasticsearch.client.ml.job.stats.JobStats; -import org.elasticsearch.client.ml.GetJobsStatsRequest; -import org.elasticsearch.client.ml.GetJobsStatsResponse; import org.elasticsearch.client.ml.CloseJobRequest; import org.elasticsearch.client.ml.CloseJobResponse; import org.elasticsearch.client.ml.DeleteJobRequest; @@ -298,17 +298,17 @@ public void getBucketsAsync(GetBucketsRequest request, RequestOptions options, A * For additional info * see Get Job stats docs *

- * @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options + * @param request {@link GetJobStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized - * @return {@link GetJobsStatsResponse} response object containing + * @return {@link GetJobStatsResponse} response object containing * the {@link JobStats} objects and the number of jobs found * @throws IOException when there is a serialization issue sending the request or receiving the response */ - public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOptions options) throws IOException { + public GetJobStatsResponse getJobStats(GetJobStatsRequest request, RequestOptions options) throws IOException { return restHighLevelClient.performRequestAndParseEntity(request, - MLRequestConverters::getJobsStats, + MLRequestConverters::getJobStats, options, - GetJobsStatsResponse::fromXContent, + GetJobStatsResponse::fromXContent, Collections.emptySet()); } @@ -319,15 +319,15 @@ public GetJobsStatsResponse getJobStats(GetJobsStatsRequest request, RequestOpti * For additional info * see Get Job stats docs *

- * @param request {@link GetJobsStatsRequest} Request containing a list of jobId(s) and additional options + * @param request {@link GetJobStatsRequest} Request containing a list of jobId(s) and additional options * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized - * @param listener Listener to be notified with {@link GetJobsStatsResponse} upon request completion + * @param listener Listener to be notified with {@link GetJobStatsResponse} upon request completion */ - public void getJobStatsAsync(GetJobsStatsRequest request, RequestOptions options, ActionListener listener) { + public void getJobStatsAsync(GetJobStatsRequest request, RequestOptions options, ActionListener listener) { restHighLevelClient.performRequestAsyncAndParseEntity(request, - MLRequestConverters::getJobsStats, + MLRequestConverters::getJobStats, options, - GetJobsStatsResponse::fromXContent, + GetJobStatsResponse::fromXContent, listener, Collections.emptySet()); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java similarity index 85% rename from client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java index 76fa6bb53298e..d8eb350755dcb 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsRequest.java @@ -41,19 +41,19 @@ * `_all` explicitly gets all the jobs' statistics in the cluster * An empty request (no `jobId`s) implicitly gets all the jobs' statistics in the cluster */ -public class GetJobsStatsRequest extends ActionRequest implements ToXContentObject { +public class GetJobStatsRequest extends ActionRequest implements ToXContentObject { public static final ParseField ALLOW_NO_JOBS = new ParseField("allow_no_jobs"); @SuppressWarnings("unchecked") - public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( - "get_jobs_stats_request", a -> new GetJobsStatsRequest((List) a[0])); + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + "get_jobs_stats_request", a -> new GetJobStatsRequest((List) a[0])); static { PARSER.declareField(ConstructingObjectParser.constructorArg(), p -> Arrays.asList(Strings.commaDelimitedListToStringArray(p.text())), Job.ID, ObjectParser.ValueType.STRING_ARRAY); - PARSER.declareBoolean(GetJobsStatsRequest::setAllowNoJobs, ALLOW_NO_JOBS); + PARSER.declareBoolean(GetJobStatsRequest::setAllowNoJobs, ALLOW_NO_JOBS); } private static final String ALL_JOBS = "_all"; @@ -64,13 +64,13 @@ public class GetJobsStatsRequest extends ActionRequest implements ToXContentObje /** * Explicitly gets all jobs statistics * - * @return a {@link GetJobsStatsRequest} for all existing jobs + * @return a {@link GetJobStatsRequest} for all existing jobs */ - public static GetJobsStatsRequest getAllJobsStatsRequest(){ - return new GetJobsStatsRequest(ALL_JOBS); + public static GetJobStatsRequest getAllJobStatsRequest(){ + return new GetJobStatsRequest(ALL_JOBS); } - GetJobsStatsRequest(List jobIds) { + GetJobStatsRequest(List jobIds) { if (jobIds.stream().anyMatch(Objects::isNull)) { throw new NullPointerException("jobIds must not contain null values"); } @@ -82,7 +82,7 @@ public static GetJobsStatsRequest getAllJobsStatsRequest(){ * * @param jobIds must be non-null and each jobId must be non-null */ - public GetJobsStatsRequest(String... jobIds) { + public GetJobStatsRequest(String... jobIds) { this(Arrays.asList(jobIds)); } @@ -123,7 +123,7 @@ public boolean equals(Object other) { return false; } - GetJobsStatsRequest that = (GetJobsStatsRequest) other; + GetJobStatsRequest that = (GetJobStatsRequest) other; return Objects.equals(jobIds, that.jobIds) && Objects.equals(allowNoJobs, that.allowNoJobs); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java similarity index 83% rename from client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java index 06b30e7b6b6ef..2e3ba113d193c 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobsStatsResponse.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetJobStatsResponse.java @@ -33,21 +33,21 @@ /** * Contains a {@link List} of the found {@link JobStats} objects and the total count found */ -public class GetJobsStatsResponse extends AbstractResultResponse { +public class GetJobStatsResponse extends AbstractResultResponse { public static final ParseField RESULTS_FIELD = new ParseField("jobs"); @SuppressWarnings("unchecked") - public static final ConstructingObjectParser PARSER = + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("jobs_stats_response", true, - a -> new GetJobsStatsResponse((List) a[0], (long) a[1])); + a -> new GetJobStatsResponse((List) a[0], (long) a[1])); static { PARSER.declareObjectArray(constructorArg(), JobStats.PARSER, RESULTS_FIELD); PARSER.declareLong(constructorArg(), COUNT); } - GetJobsStatsResponse(List jobStats, long count) { + GetJobStatsResponse(List jobStats, long count) { super(RESULTS_FIELD, jobStats, count); } @@ -58,7 +58,7 @@ public List jobStats() { return results; } - public static GetJobsStatsResponse fromXContent(XContentParser parser) throws IOException { + public static GetJobStatsResponse fromXContent(XContentParser parser) throws IOException { return PARSER.parse(parser, null); } @@ -77,7 +77,7 @@ public boolean equals(Object obj) { return false; } - GetJobsStatsResponse other = (GetJobsStatsResponse) obj; + GetJobStatsResponse other = (GetJobStatsResponse) obj; return Objects.equals(results, other.results) && count == other.count; } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java index 015b0051ffc5e..4950a1c8139f6 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MLRequestConvertersTests.java @@ -36,7 +36,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.json.JsonXContent; -import org.elasticsearch.client.ml.GetJobsStatsRequest; +import org.elasticsearch.client.ml.GetJobStatsRequest; import org.elasticsearch.test.ESTestCase; import java.io.ByteArrayOutputStream; @@ -140,18 +140,18 @@ public void testGetBuckets() throws IOException { } } - public void testGetJobsStats() { - GetJobsStatsRequest getJobsStatsRequestRequest = new GetJobsStatsRequest(); + public void testGetJobStats() { + GetJobStatsRequest getJobStatsRequestRequest = new GetJobStatsRequest(); - Request request = MLRequestConverters.getJobsStats(getJobsStatsRequestRequest); + Request request = MLRequestConverters.getJobStats(getJobStatsRequestRequest); assertEquals(HttpGet.METHOD_NAME, request.getMethod()); assertEquals("/_xpack/ml/anomaly_detectors/_stats", request.getEndpoint()); assertFalse(request.getParameters().containsKey("allow_no_jobs")); - getJobsStatsRequestRequest = new GetJobsStatsRequest("job1", "jobs*"); - getJobsStatsRequestRequest.setAllowNoJobs(true); - request = MLRequestConverters.getJobsStats(getJobsStatsRequestRequest); + getJobStatsRequestRequest = new GetJobStatsRequest("job1", "jobs*"); + getJobStatsRequestRequest.setAllowNoJobs(true); + request = MLRequestConverters.getJobStats(getJobStatsRequestRequest); assertEquals("/_xpack/ml/anomaly_detectors/job1,jobs*/_stats", request.getEndpoint()); assertEquals(Boolean.toString(true), request.getParameters().get("allow_no_jobs")); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java index 29acb52c8c2c7..7b8e4b3e4c4c7 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/MachineLearningIT.java @@ -21,8 +21,8 @@ import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.client.ml.GetJobsStatsRequest; -import org.elasticsearch.client.ml.GetJobsStatsResponse; +import org.elasticsearch.client.ml.GetJobStatsRequest; +import org.elasticsearch.client.ml.GetJobStatsResponse; import org.elasticsearch.client.ml.job.config.JobState; import org.elasticsearch.client.ml.job.stats.JobStats; import org.elasticsearch.client.ml.CloseJobRequest; @@ -144,7 +144,7 @@ public void testCloseJob() throws Exception { assertTrue(response.isClosed()); } - public void testGetJobsStats() throws Exception { + public void testGetJobStats() throws Exception { String jobId1 = "ml-get-job-stats-test-id-1"; String jobId2 = "ml-get-job-stats-test-id-2"; @@ -156,10 +156,10 @@ public void testGetJobsStats() throws Exception { machineLearningClient.openJob(new OpenJobRequest(jobId1), RequestOptions.DEFAULT); - GetJobsStatsRequest request = new GetJobsStatsRequest(jobId1, jobId2); + GetJobStatsRequest request = new GetJobStatsRequest(jobId1, jobId2); // Test getting specific - GetJobsStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + GetJobStatsResponse response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertEquals(2, response.count()); assertThat(response.jobStats(), hasSize(2)); @@ -173,7 +173,7 @@ public void testGetJobsStats() throws Exception { } // Test getting all explicitly - request = GetJobsStatsRequest.getAllJobsStatsRequest(); + request = GetJobStatsRequest.getAllJobStatsRequest(); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); @@ -181,21 +181,21 @@ public void testGetJobsStats() throws Exception { assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test getting all implicitly - response = execute(new GetJobsStatsRequest(), machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); + response = execute(new GetJobStatsRequest(), machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); assertTrue(response.jobStats().size() >= 2L); assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test getting all with wildcard - request = new GetJobsStatsRequest("ml-get-job-stats-test-id-*"); + request = new GetJobStatsRequest("ml-get-job-stats-test-id-*"); response = execute(request, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync); assertTrue(response.count() >= 2L); assertTrue(response.jobStats().size() >= 2L); assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), hasItems(jobId1, jobId2)); // Test when allow_no_jobs is false - final GetJobsStatsRequest erroredRequest = new GetJobsStatsRequest("jobs-that-do-not-exist*"); + final GetJobStatsRequest erroredRequest = new GetJobStatsRequest("jobs-that-do-not-exist*"); erroredRequest.setAllowNoJobs(false); ElasticsearchStatusException exception = expectThrows(ElasticsearchStatusException.class, () -> execute(erroredRequest, machineLearningClient::getJobStats, machineLearningClient::getJobStatsAsync)); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java index c1ff9597c64a5..d97db0a311f75 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/MlClientDocumentationIT.java @@ -35,6 +35,8 @@ import org.elasticsearch.client.ml.GetBucketsResponse; import org.elasticsearch.client.ml.GetJobRequest; import org.elasticsearch.client.ml.GetJobResponse; +import org.elasticsearch.client.ml.GetJobStatsRequest; +import org.elasticsearch.client.ml.GetJobStatsResponse; import org.elasticsearch.client.ml.GetRecordsRequest; import org.elasticsearch.client.ml.GetRecordsResponse; import org.elasticsearch.client.ml.OpenJobRequest; @@ -50,8 +52,6 @@ import org.elasticsearch.client.ml.job.util.PageParams; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.client.ml.GetJobsStatsRequest; -import org.elasticsearch.client.ml.GetJobsStatsResponse; import org.elasticsearch.client.ml.job.stats.JobStats; import org.junit.After; @@ -472,28 +472,31 @@ public void testGetJobStats() throws Exception { { //tag::x-pack-ml-get-job-stats-request - GetJobsStatsRequest request = new GetJobsStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); //<1> + GetJobStatsRequest request = new GetJobStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); //<1> request.setAllowNoJobs(true); //<2> //end::x-pack-ml-get-job-stats-request //tag::x-pack-ml-get-job-stats-execute - GetJobsStatsResponse response = client.machineLearning().getJobStats(request, RequestOptions.DEFAULT); - long numberOfJobsStats = response.count(); //<1> - List jobsStats = response.jobStats(); //<2> + GetJobStatsResponse response = client.machineLearning().getJobStats(request, RequestOptions.DEFAULT); //end::x-pack-ml-get-job-stats-execute + //tag::x-pack-ml-get-job-stats-response + long numberOfJobStats = response.count(); //<1> + List jobStats = response.jobStats(); //<2> + //end::x-pack-ml-get-job-stats-response + assertEquals(2, response.count()); assertThat(response.jobStats(), hasSize(2)); assertThat(response.jobStats().stream().map(JobStats::getJobId).collect(Collectors.toList()), containsInAnyOrder(job.getId(), secondJob.getId())); } { - GetJobsStatsRequest request = new GetJobsStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); + GetJobStatsRequest request = new GetJobStatsRequest("get-machine-learning-job-stats1", "get-machine-learning-job-*"); // tag::x-pack-ml-get-job-stats-listener - ActionListener listener = new ActionListener() { + ActionListener listener = new ActionListener() { @Override - public void onResponse(GetJobsStatsResponse response) { + public void onResponse(GetJobStatsResponse response) { // <1> } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsRequestTests.java similarity index 78% rename from client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsRequestTests.java index ca0809b834e06..690e582976656 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsRequestTests.java @@ -25,22 +25,22 @@ import java.util.ArrayList; import java.util.List; -public class GetJobsStatsRequestTests extends AbstractXContentTestCase { +public class GetJobStatsRequestTests extends AbstractXContentTestCase { public void testAllJobsRequest() { - GetJobsStatsRequest request = GetJobsStatsRequest.getAllJobsStatsRequest(); + GetJobStatsRequest request = GetJobStatsRequest.getAllJobStatsRequest(); assertEquals(request.getJobIds().size(), 1); assertEquals(request.getJobIds().get(0), "_all"); } public void testNewWithJobId() { - Exception exception = expectThrows(NullPointerException.class, () -> new GetJobsStatsRequest("job", null)); + Exception exception = expectThrows(NullPointerException.class, () -> new GetJobStatsRequest("job", null)); assertEquals(exception.getMessage(), "jobIds must not contain null values"); } @Override - protected GetJobsStatsRequest createTestInstance() { + protected GetJobStatsRequest createTestInstance() { int jobCount = randomIntBetween(0, 10); List jobIds = new ArrayList<>(jobCount); @@ -48,7 +48,7 @@ protected GetJobsStatsRequest createTestInstance() { jobIds.add(randomAlphaOfLength(10)); } - GetJobsStatsRequest request = new GetJobsStatsRequest(jobIds); + GetJobStatsRequest request = new GetJobStatsRequest(jobIds); if (randomBoolean()) { request.setAllowNoJobs(randomBoolean()); @@ -58,8 +58,8 @@ protected GetJobsStatsRequest createTestInstance() { } @Override - protected GetJobsStatsRequest doParseInstance(XContentParser parser) throws IOException { - return GetJobsStatsRequest.PARSER.parse(parser, null); + protected GetJobStatsRequest doParseInstance(XContentParser parser) throws IOException { + return GetJobStatsRequest.PARSER.parse(parser, null); } @Override diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsResponseTests.java similarity index 80% rename from client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsResponseTests.java index a643239d4b580..23f7bcc042b4a 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobsStatsResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetJobStatsResponseTests.java @@ -27,10 +27,10 @@ import java.util.ArrayList; import java.util.List; -public class GetJobsStatsResponseTests extends AbstractXContentTestCase { +public class GetJobStatsResponseTests extends AbstractXContentTestCase { @Override - protected GetJobsStatsResponse createTestInstance() { + protected GetJobStatsResponse createTestInstance() { int count = randomIntBetween(1, 5); List results = new ArrayList<>(count); @@ -38,12 +38,12 @@ protected GetJobsStatsResponse createTestInstance() { results.add(JobStatsTests.createRandomInstance()); } - return new GetJobsStatsResponse(results, count); + return new GetJobStatsResponse(results, count); } @Override - protected GetJobsStatsResponse doParseInstance(XContentParser parser) throws IOException { - return GetJobsStatsResponse.fromXContent(parser); + protected GetJobStatsResponse doParseInstance(XContentParser parser) throws IOException { + return GetJobStatsResponse.fromXContent(parser); } @Override diff --git a/docs/java-rest/high-level/ml/get-job-stats.asciidoc b/docs/java-rest/high-level/ml/get-job-stats.asciidoc index 4f6e24f9fd0ec..90f7794ae765b 100644 --- a/docs/java-rest/high-level/ml/get-job-stats.asciidoc +++ b/docs/java-rest/high-level/ml/get-job-stats.asciidoc @@ -3,8 +3,8 @@ The Get Job Stats API provides the ability to get any number of {ml} job's statistics in the cluster. -It accepts a `GetJobsStatsRequest` object and responds -with a `GetJobsStatsResponse` object. +It accepts a `GetJobStatsRequest` object and responds +with a `GetJobStatsResponse` object. [[java-rest-high-x-pack-ml-get-job-stats-request]] ==== Get Job Stats Request @@ -31,8 +31,6 @@ in the `RestHighLevelClient` object, accessed via the `machineLearningClient()` -------------------------------------------------- include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-execute] -------------------------------------------------- -<1> `getCount()` from the `GetJobsStatsResponse` indicates the number of jobs statistics found -<2> `getJobStats()` is the collection of {ml} `JobStats` objects found [[java-rest-high-x-pack-ml-get-job-stats-execution-async]] ==== Asynchronous Execution @@ -56,3 +54,14 @@ include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats -------------------------------------------------- <1> `onResponse` is called back when the action is completed successfully <2> `onFailure` is called back when some unexpected error occurs + +[[java-rest-high-x-pack-ml-get-job-stats-response]] +==== Get Job Stats Response +The returned `GetJobStatsResponse` contains the requested job statistics: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/MlClientDocumentationIT.java[x-pack-ml-get-job-stats-response] +-------------------------------------------------- +<1> `getCount()` indicates the number of jobs statistics found +<2> `getJobStats()` is the collection of {ml} `JobStats` objects found \ No newline at end of file