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 28e52a8d6271e..6d7fefe907fc6 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
@@ -43,6 +43,7 @@
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobStatsRequest;
+import org.elasticsearch.client.ml.GetModelSnapshotsRequest;
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetRecordsRequest;
import org.elasticsearch.client.ml.OpenJobRequest;
@@ -361,6 +362,19 @@ static Request getCategories(GetCategoriesRequest getCategoriesRequest) throws I
return request;
}
+ static Request getModelSnapshots(GetModelSnapshotsRequest getModelSnapshotsRequest) throws IOException {
+ String endpoint = new EndpointBuilder()
+ .addPathPartAsIs("_xpack")
+ .addPathPartAsIs("ml")
+ .addPathPartAsIs("anomaly_detectors")
+ .addPathPart(getModelSnapshotsRequest.getJobId())
+ .addPathPartAsIs("model_snapshots")
+ .build();
+ Request request = new Request(HttpGet.METHOD_NAME, endpoint);
+ request.setEntity(createEntity(getModelSnapshotsRequest, REQUEST_BODY_CONTENT_TYPE));
+ return request;
+ }
+
static Request getOverallBuckets(GetOverallBucketsRequest getOverallBucketsRequest) throws IOException {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
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 4b62712c571e9..e327f9b2a5812 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
@@ -49,6 +49,8 @@
import org.elasticsearch.client.ml.GetJobResponse;
import org.elasticsearch.client.ml.GetJobStatsRequest;
import org.elasticsearch.client.ml.GetJobStatsResponse;
+import org.elasticsearch.client.ml.GetModelSnapshotsRequest;
+import org.elasticsearch.client.ml.GetModelSnapshotsResponse;
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetOverallBucketsResponse;
import org.elasticsearch.client.ml.GetRecordsRequest;
@@ -897,6 +899,46 @@ public void getCategoriesAsync(GetCategoriesRequest request, RequestOptions opti
Collections.emptySet());
}
+ /**
+ * Gets the snapshots for a Machine Learning Job.
+ *
+ * For additional info
+ * see
+ * ML GET model snapshots documentation
+ *
+ * @param request The request
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @throws IOException when there is a serialization issue sending the request or receiving the response
+ */
+ public GetModelSnapshotsResponse getModelSnapshots(GetModelSnapshotsRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request,
+ MLRequestConverters::getModelSnapshots,
+ options,
+ GetModelSnapshotsResponse::fromXContent,
+ Collections.emptySet());
+ }
+
+ /**
+ * Gets the snapshots for a Machine Learning Job, notifies listener once the requested snapshots are retrieved.
+ *
+ * For additional info
+ * see
+ * ML GET model snapshots documentation
+ *
+ * @param request The request
+ * @param options Additional request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener Listener to be notified upon request completion
+ */
+ public void getModelSnapshotsAsync(GetModelSnapshotsRequest request, RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request,
+ MLRequestConverters::getModelSnapshots,
+ options,
+ GetModelSnapshotsResponse::fromXContent,
+ listener,
+ Collections.emptySet());
+ }
+
/**
* Gets overall buckets for a set of Machine Learning Jobs.
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsRequest.java
new file mode 100644
index 0000000000000..8743f3043e589
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsRequest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.client.ml;
+
+import org.elasticsearch.action.ActionRequest;
+import org.elasticsearch.action.ActionRequestValidationException;
+import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.client.ml.job.util.PageParams;
+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;
+
+/**
+ * A request to retrieve information about model snapshots for a given job
+ */
+public class GetModelSnapshotsRequest extends ActionRequest implements ToXContentObject {
+
+
+ public static final ParseField SNAPSHOT_ID = new ParseField("snapshot_id");
+ public static final ParseField SORT = new ParseField("sort");
+ public static final ParseField START = new ParseField("start");
+ public static final ParseField END = new ParseField("end");
+ public static final ParseField DESC = new ParseField("desc");
+
+ public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "get_model_snapshots_request", a -> new GetModelSnapshotsRequest((String) a[0]));
+
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), Job.ID);
+ PARSER.declareString(GetModelSnapshotsRequest::setSnapshotId, SNAPSHOT_ID);
+ PARSER.declareString(GetModelSnapshotsRequest::setSort, SORT);
+ PARSER.declareStringOrNull(GetModelSnapshotsRequest::setStart, START);
+ PARSER.declareStringOrNull(GetModelSnapshotsRequest::setEnd, END);
+ PARSER.declareBoolean(GetModelSnapshotsRequest::setDesc, DESC);
+ PARSER.declareObject(GetModelSnapshotsRequest::setPageParams, PageParams.PARSER, PageParams.PAGE);
+ }
+
+ private final String jobId;
+ private String snapshotId;
+ private String sort;
+ private String start;
+ private String end;
+ private Boolean desc;
+ private PageParams pageParams;
+
+ /**
+ * Constructs a request to retrieve snapshot information from a given job
+ * @param jobId id of the job from which to retrieve results
+ */
+ public GetModelSnapshotsRequest(String jobId) {
+ this.jobId = Objects.requireNonNull(jobId);
+ }
+
+ public String getJobId() {
+ return jobId;
+ }
+
+ public String getSnapshotId() {
+ return snapshotId;
+ }
+
+ /**
+ * Sets the id of the snapshot to retrieve.
+ * @param snapshotId the snapshot id
+ */
+ public void setSnapshotId(String snapshotId) {
+ this.snapshotId = snapshotId;
+ }
+
+ public String getSort() {
+ return sort;
+ }
+
+ /**
+ * Sets the value of "sort".
+ * Specifies the snapshot field to sort on.
+ * @param sort value of "sort".
+ */
+ public void setSort(String sort) {
+ this.sort = sort;
+ }
+
+ public PageParams getPageParams() {
+ return pageParams;
+ }
+
+ /**
+ * Sets the paging parameters
+ * @param pageParams the paging parameters
+ */
+ public void setPageParams(PageParams pageParams) {
+ this.pageParams = pageParams;
+ }
+
+ public String getStart() {
+ return start;
+ }
+
+ /**
+ * Sets the value of "start" which is a timestamp.
+ * Only snapshots whose timestamp is on or after the "start" value will be returned.
+ * @param start String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setStart(String start) {
+ this.start = start;
+ }
+
+
+ public String getEnd() {
+ return end;
+ }
+
+ /**
+ * Sets the value of "end" which is a timestamp.
+ * Only snapshots whose timestamp is before the "end" value will be returned.
+ * @param end String representation of a timestamp; may be an epoch seconds, epoch millis or an ISO string
+ */
+ public void setEnd(String end) {
+ this.end = end;
+ }
+
+ public Boolean getDesc() {
+ return desc;
+ }
+
+ /**
+ * Sets the value of "desc".
+ * Specifies the sorting order.
+ * @param desc value of "desc"
+ */
+ public void setDesc(boolean desc) {
+ this.desc = desc;
+ }
+
+ @Override
+ public ActionRequestValidationException validate() {
+ return null;
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject();
+ builder.field(Job.ID.getPreferredName(), jobId);
+ if (snapshotId != null) {
+ builder.field(SNAPSHOT_ID.getPreferredName(), snapshotId);
+ }
+ if (sort != null) {
+ builder.field(SORT.getPreferredName(), sort);
+ }
+ if (start != null) {
+ builder.field(START.getPreferredName(), start);
+ }
+ if (end != null) {
+ builder.field(END.getPreferredName(), end);
+ }
+ if (desc != null) {
+ builder.field(DESC.getPreferredName(), desc);
+ }
+ if (pageParams != null) {
+ builder.field(PageParams.PAGE.getPreferredName(), pageParams);
+ } builder.endObject();
+ return builder;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetModelSnapshotsRequest request = (GetModelSnapshotsRequest) obj;
+ return Objects.equals(jobId, request.jobId)
+ && Objects.equals(snapshotId, request.snapshotId)
+ && Objects.equals(sort, request.sort)
+ && Objects.equals(start, request.start)
+ && Objects.equals(end, request.end)
+ && Objects.equals(desc, request.desc)
+ && Objects.equals(pageParams, request.pageParams);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jobId, snapshotId, pageParams, start, end, sort, desc);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsResponse.java
new file mode 100644
index 0000000000000..d4932d27a89f5
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ml/GetModelSnapshotsResponse.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.client.ml;
+
+import org.elasticsearch.client.ml.job.process.ModelSnapshot;
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * A response containing the requested snapshots
+ */
+public class GetModelSnapshotsResponse extends AbstractResultResponse {
+
+ public static final ParseField SNAPSHOTS = new ParseField("model_snapshots");
+
+ @SuppressWarnings("unchecked")
+ public static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("get_model_snapshots_response", true,
+ a -> new GetModelSnapshotsResponse((List) a[0], (long) a[1]));
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), ModelSnapshot.PARSER, SNAPSHOTS);
+ PARSER.declareLong(ConstructingObjectParser.constructorArg(), COUNT);
+ }
+
+ public static GetModelSnapshotsResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
+ GetModelSnapshotsResponse(List snapshotBuilders, long count) {
+ super(SNAPSHOTS, snapshotBuilders.stream().map(ModelSnapshot.Builder::build).collect(Collectors.toList()), count);
+ }
+
+ /**
+ * The retrieved snapshots
+ * @return the retrieved snapshots
+ */
+ public List snapshots() {
+ return results;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(count, results);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GetModelSnapshotsResponse other = (GetModelSnapshotsResponse) obj;
+ return count == other.count && Objects.equals(results, other.results);
+ }
+}
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 eea2531bda16a..bb4822990722e 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
@@ -39,6 +39,7 @@
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetJobRequest;
import org.elasticsearch.client.ml.GetJobStatsRequest;
+import org.elasticsearch.client.ml.GetModelSnapshotsRequest;
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
import org.elasticsearch.client.ml.GetRecordsRequest;
import org.elasticsearch.client.ml.OpenJobRequest;
@@ -391,6 +392,21 @@ public void testGetCategories() throws IOException {
}
}
+ public void testGetModelSnapshots() throws IOException {
+ String jobId = randomAlphaOfLength(10);
+ GetModelSnapshotsRequest getModelSnapshotsRequest = new GetModelSnapshotsRequest(jobId);
+ getModelSnapshotsRequest.setPageParams(new PageParams(100, 300));
+
+
+ Request request = MLRequestConverters.getModelSnapshots(getModelSnapshotsRequest);
+ assertEquals(HttpGet.METHOD_NAME, request.getMethod());
+ assertEquals("/_xpack/ml/anomaly_detectors/" + jobId + "/model_snapshots", request.getEndpoint());
+ try (XContentParser parser = createParser(JsonXContent.jsonXContent, request.getEntity().getContent())) {
+ GetModelSnapshotsRequest parsedRequest = GetModelSnapshotsRequest.PARSER.apply(parser, null);
+ assertThat(parsedRequest, equalTo(getModelSnapshotsRequest));
+ }
+ }
+
public void testGetOverallBuckets() throws IOException {
String jobId = randomAlphaOfLength(10);
GetOverallBucketsRequest getOverallBucketsRequest = new GetOverallBucketsRequest(jobId);
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 751f4cfdf0efe..2ee09b496fc85 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
@@ -25,6 +25,8 @@
import org.elasticsearch.client.ml.GetBucketsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
+import org.elasticsearch.client.ml.GetModelSnapshotsRequest;
+import org.elasticsearch.client.ml.GetModelSnapshotsResponse;
import org.elasticsearch.client.ml.GetInfluencersRequest;
import org.elasticsearch.client.ml.GetInfluencersResponse;
import org.elasticsearch.client.ml.GetOverallBucketsRequest;
@@ -36,6 +38,7 @@
import org.elasticsearch.client.ml.job.config.DataDescription;
import org.elasticsearch.client.ml.job.config.Detector;
import org.elasticsearch.client.ml.job.config.Job;
+import org.elasticsearch.client.ml.job.process.ModelSizeStats;
import org.elasticsearch.client.ml.job.results.AnomalyRecord;
import org.elasticsearch.client.ml.job.results.Bucket;
import org.elasticsearch.client.ml.job.results.Influencer;
@@ -48,6 +51,7 @@
import java.io.IOException;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import static org.hamcrest.Matchers.closeTo;
@@ -145,11 +149,384 @@ private void addCategoriesIndexRequests(BulkRequest bulkRequest) {
}
}
+ private void addModelSnapshotIndexRequests(BulkRequest bulkRequest) {
+ {
+ IndexRequest indexRequest = new IndexRequest(RESULTS_INDEX, DOC);
+ indexRequest.source("{\"job_id\":\"" + JOB_ID + "\", \"timestamp\":1541587919000, " +
+ "\"description\":\"State persisted due to job close at 2018-11-07T10:51:59+0000\", \"snapshot_id\":\"1541587919\"," +
+ "\"snapshot_doc_count\":1, \"model_size_stats\":{\"job_id\":\"" + JOB_ID + "\", \"result_type\":\"model_size_stats\"," +
+ "\"model_bytes\":51722, \"total_by_field_count\":3, \"total_over_field_count\":0, \"total_partition_field_count\":2," +
+ "\"bucket_allocation_failures_count\":0, \"memory_status\":\"ok\", \"log_time\":1541587919000," +
+ " \"timestamp\":1519930800000},\"latest_record_time_stamp\":1519931700000, \"latest_result_time_stamp\":1519930800000," +
+ " \"retain\":false }", XContentType.JSON);
+ bulkRequest.add(indexRequest);
+ }
+ {
+ IndexRequest indexRequest = new IndexRequest(RESULTS_INDEX, DOC);
+ indexRequest.source("{\"job_id\":\"" + JOB_ID + "\", \"timestamp\":1541588919000, " +
+ "\"description\":\"State persisted due to job close at 2018-11-07T11:08:39+0000\", \"snapshot_id\":\"1541588919\"," +
+ "\"snapshot_doc_count\":1, \"model_size_stats\":{\"job_id\":\"" + JOB_ID + "\", \"result_type\":\"model_size_stats\"," +
+ "\"model_bytes\":51722, \"total_by_field_count\":3, \"total_over_field_count\":0, \"total_partition_field_count\":2," +
+ "\"bucket_allocation_failures_count\":0, \"memory_status\":\"ok\", \"log_time\":1541588919000," +
+ "\"timestamp\":1519930800000},\"latest_record_time_stamp\":1519931700000, \"latest_result_time_stamp\":1519930800000, " +
+ "\"retain\":false }", XContentType.JSON);
+ bulkRequest.add(indexRequest);
+ }
+ {
+ IndexRequest indexRequest = new IndexRequest(RESULTS_INDEX, DOC);
+ indexRequest.source("{\"job_id\":\"" + JOB_ID + "\", \"timestamp\":1541589919000, " +
+ "\"description\":\"State persisted due to job close at 2018-11-07T11:25:19+0000\", \"snapshot_id\":\"1541589919\"," +
+ "\"snapshot_doc_count\":1, \"model_size_stats\":{\"job_id\":\"" + JOB_ID + "\", \"result_type\":\"model_size_stats\"," +
+ "\"model_bytes\":51722, \"total_by_field_count\":3, \"total_over_field_count\":0, \"total_partition_field_count\":2," +
+ "\"bucket_allocation_failures_count\":0, \"memory_status\":\"ok\", \"log_time\":1541589919000," +
+ "\"timestamp\":1519930800000},\"latest_record_time_stamp\":1519931700000, \"latest_result_time_stamp\":1519930800000," +
+ "\"retain\":false }", XContentType.JSON);
+ bulkRequest.add(indexRequest);
+ }
+ }
+
@After
public void deleteJob() throws IOException {
new MlTestStateCleaner(logger, highLevelClient().machineLearning()).clearMlMetadata();
}
+ public void testGetModelSnapshots() throws IOException {
+
+ // index some model_snapshot results
+ BulkRequest bulkRequest = new BulkRequest();
+ bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
+
+ addModelSnapshotIndexRequests(bulkRequest);
+
+ highLevelClient().bulk(bulkRequest, RequestOptions.DEFAULT);
+
+ MachineLearningClient machineLearningClient = highLevelClient().machineLearning();
+
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(false);
+ request.setPageParams(new PageParams(0, 10000));
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(3L));
+ assertThat(response.snapshots().size(), equalTo(3));
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541587919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T10:51:59+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541587919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+ assertThat(response.snapshots().get(1).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getSnapshotId(), equalTo("1541588919"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:08:39+0000"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getTimestamp(), equalTo(new Date(1541588919000L)));
+ assertThat(response.snapshots().get(1).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(1).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+ assertThat(response.snapshots().get(2).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(2).getSnapshotId(), equalTo("1541589919"));
+ assertThat(response.snapshots().get(2).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(2).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:25:19+0000"));
+ assertThat(response.snapshots().get(2).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(2).getTimestamp(), equalTo(new Date(1541589919000L)));
+ assertThat(response.snapshots().get(2).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(2).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(true);
+ request.setPageParams(new PageParams(0, 10000));
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(3L));
+ assertThat(response.snapshots().size(), equalTo(3));
+ assertThat(response.snapshots().get(2).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(2).getSnapshotId(), equalTo("1541587919"));
+ assertThat(response.snapshots().get(2).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(2).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T10:51:59+0000"));
+ assertThat(response.snapshots().get(2).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(2).getTimestamp(), equalTo(new Date(1541587919000L)));
+ assertThat(response.snapshots().get(2).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(2).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(2).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+ assertThat(response.snapshots().get(1).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getSnapshotId(), equalTo("1541588919"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:08:39+0000"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getTimestamp(), equalTo(new Date(1541588919000L)));
+ assertThat(response.snapshots().get(1).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(1).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541589919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:25:19+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541589919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(false);
+ request.setPageParams(new PageParams(0, 1));
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(3L));
+ assertThat(response.snapshots().size(), equalTo(1));
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541587919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T10:51:59+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541587919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(false);
+ request.setPageParams(new PageParams(1, 2));
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(3L));
+ assertThat(response.snapshots().size(), equalTo(2));
+
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541588919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:08:39+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541588919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+
+ assertThat(response.snapshots().get(1).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getSnapshotId(), equalTo("1541589919"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:25:19+0000"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getTimestamp(), equalTo(new Date(1541589919000L)));
+ assertThat(response.snapshots().get(1).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(1).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSnapshotId("1541588919");
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(1L));
+ assertThat(response.snapshots().size(), equalTo(1));
+
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541588919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:08:39+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541588919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSnapshotId("1541586919"); // request a non-existent snapshotId
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(0L));
+ assertThat(response.snapshots().size(), equalTo(0));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(false);
+ request.setStart("1541586919000");
+ request.setEnd("1541589019000");
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(2L));
+ assertThat(response.snapshots().size(), equalTo(2));
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541587919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T10:51:59+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541587919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+
+ assertThat(response.snapshots().get(1).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getSnapshotId(), equalTo("1541588919"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:08:39+0000"));
+ assertThat(response.snapshots().get(1).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(1).getTimestamp(), equalTo(new Date(1541588919000L)));
+ assertThat(response.snapshots().get(1).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(1).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(1).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(JOB_ID);
+ request.setSort("timestamp");
+ request.setDesc(false);
+ request.setStart("1541589019000");
+
+ GetModelSnapshotsResponse response = execute(request, machineLearningClient::getModelSnapshots,
+ machineLearningClient::getModelSnapshotsAsync);
+
+ assertThat(response.count(), equalTo(1L));
+ assertThat(response.snapshots().size(), equalTo(1));
+ assertThat(response.snapshots().get(0).getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getSnapshotId(), equalTo("1541589919"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getDescription(), equalTo("State persisted due to job close at" +
+ " 2018-11-07T11:25:19+0000"));
+ assertThat(response.snapshots().get(0).getSnapshotDocCount(), equalTo(1));
+ assertThat(response.snapshots().get(0).getTimestamp(), equalTo(new Date(1541589919000L)));
+ assertThat(response.snapshots().get(0).getLatestRecordTimeStamp(), equalTo(new Date(1519931700000L)));
+ assertThat(response.snapshots().get(0).getLatestResultTimeStamp(), equalTo(new Date(1519930800000L)));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getJobId(), equalTo(JOB_ID));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getModelBytes(), equalTo(51722L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalByFieldCount(), equalTo(3L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalOverFieldCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getTotalPartitionFieldCount(), equalTo(2L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getBucketAllocationFailuresCount(), equalTo(0L));
+ assertThat(response.snapshots().get(0).getModelSizeStats().getMemoryStatus(),
+ equalTo(ModelSizeStats.MemoryStatus.fromString("ok")));
+ }
+ }
+
public void testGetCategories() throws IOException {
// index some category results
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 47498e7ac8382..e6a8976a3c75c 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
@@ -50,6 +50,8 @@
import org.elasticsearch.client.ml.GetCalendarsResponse;
import org.elasticsearch.client.ml.GetCategoriesRequest;
import org.elasticsearch.client.ml.GetCategoriesResponse;
+import org.elasticsearch.client.ml.GetModelSnapshotsRequest;
+import org.elasticsearch.client.ml.GetModelSnapshotsResponse;
import org.elasticsearch.client.ml.GetDatafeedRequest;
import org.elasticsearch.client.ml.GetDatafeedResponse;
import org.elasticsearch.client.ml.GetDatafeedStatsRequest;
@@ -103,6 +105,7 @@
import org.elasticsearch.client.ml.job.config.Operator;
import org.elasticsearch.client.ml.job.config.RuleCondition;
import org.elasticsearch.client.ml.job.process.DataCounts;
+import org.elasticsearch.client.ml.job.process.ModelSnapshot;
import org.elasticsearch.client.ml.job.results.AnomalyRecord;
import org.elasticsearch.client.ml.job.results.Bucket;
import org.elasticsearch.client.ml.job.results.CategoryDefinition;
@@ -1863,6 +1866,102 @@ public void onFailure(Exception e) {
}
}
+ public void testGetModelSnapshots() throws IOException, InterruptedException {
+ RestHighLevelClient client = highLevelClient();
+
+ String jobId = "test-get-model-snapshots";
+ Job job = MachineLearningIT.buildJob(jobId);
+ client.machineLearning().putJob(new PutJobRequest(job), RequestOptions.DEFAULT);
+
+ // Let us index a snapshot
+ IndexRequest indexRequest = new IndexRequest(".ml-anomalies-shared", "doc");
+ indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
+ indexRequest.source("{\"job_id\":\"test-get-model-snapshots\", \"timestamp\":1541587919000, " +
+ "\"description\":\"State persisted due to job close at 2018-11-07T10:51:59+0000\", " +
+ "\"snapshot_id\":\"1541587919\", \"snapshot_doc_count\":1, \"model_size_stats\":{" +
+ "\"job_id\":\"test-get-model-snapshots\", \"result_type\":\"model_size_stats\",\"model_bytes\":51722, " +
+ "\"total_by_field_count\":3, \"total_over_field_count\":0, \"total_partition_field_count\":2," +
+ "\"bucket_allocation_failures_count\":0, \"memory_status\":\"ok\", \"log_time\":1541587919000, " +
+ "\"timestamp\":1519930800000}, \"latest_record_time_stamp\":1519931700000," +
+ "\"latest_result_time_stamp\":1519930800000, \"retain\":false}", XContentType.JSON);
+ client.index(indexRequest, RequestOptions.DEFAULT);
+
+ {
+ // tag::get-model-snapshots-request
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(jobId); // <1>
+ // end::get-model-snapshots-request
+
+ // tag::get-model-snapshots-snapshot-id
+ request.setSnapshotId("1541587919"); // <1>
+ // end::get-model-snapshots-snapshot-id
+
+ // Set snapshot id to null as it is incompatible with other args
+ request.setSnapshotId(null);
+
+ // tag::get-model-snapshots-desc
+ request.setDesc(true); // <1>
+ // end::get-model-snapshots-desc
+
+ // tag::get-model-snapshots-end
+ request.setEnd("2018-11-07T21:00:00Z"); // <1>
+ // end::get-model-snapshots-end
+
+ // tag::get-model-snapshots-page
+ request.setPageParams(new PageParams(100, 200)); // <1>
+ // end::get-model-snapshots-page
+
+ // Set page params back to null so the response contains the snapshot we indexed
+ request.setPageParams(null);
+
+ // tag::get-model-snapshots-sort
+ request.setSort("latest_result_time_stamp"); // <1>
+ // end::get-model-snapshots-sort
+
+ // tag::get-model-snapshots-start
+ request.setStart("2018-11-07T00:00:00Z"); // <1>
+ // end::get-model-snapshots-start
+
+ // tag::get-model-snapshots-execute
+ GetModelSnapshotsResponse response = client.machineLearning().getModelSnapshots(request, RequestOptions.DEFAULT);
+ // end::get-model-snapshots-execute
+
+ // tag::get-model-snapshots-response
+ long count = response.count(); // <1>
+ List modelSnapshots = response.snapshots(); // <2>
+ // end::get-model-snapshots-response
+
+ assertEquals(1, modelSnapshots.size());
+ }
+ {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(jobId);
+
+ // tag::get-model-snapshots-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(GetModelSnapshotsResponse getModelSnapshotsResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::get-model-snapshots-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::get-model-snapshots-execute-async
+ client.machineLearning().getModelSnapshotsAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::get-model-snapshots-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
public void testPutCalendar() throws IOException, InterruptedException {
RestHighLevelClient client = highLevelClient();
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsRequestTests.java
new file mode 100644
index 0000000000000..80a08f8c765ac
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsRequestTests.java
@@ -0,0 +1,67 @@
+/*
+ * 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.client.ml;
+
+import org.elasticsearch.client.ml.job.util.PageParams;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+
+
+public class GetModelSnapshotsRequestTests extends AbstractXContentTestCase {
+
+ @Override
+ protected GetModelSnapshotsRequest createTestInstance() {
+ GetModelSnapshotsRequest request = new GetModelSnapshotsRequest(randomAlphaOfLengthBetween(1, 20));
+ if (randomBoolean()) {
+ request.setSnapshotId(String.valueOf(randomNonNegativeLong()));
+ }
+ else {
+ if (randomBoolean()) {
+ request.setStart(String.valueOf(randomLong()));
+ }
+ if (randomBoolean()) {
+ request.setEnd(String.valueOf(randomLong()));
+ }
+ if (randomBoolean()) {
+ int from = randomInt(10000);
+ int size = randomInt(10000);
+ request.setPageParams(new PageParams(from, size));
+ }
+ if (randomBoolean()) {
+ request.setSort("description");
+ }
+ if (randomBoolean()) {
+ request.setDesc(randomBoolean());
+ }
+ }
+ return request;
+ }
+
+ @Override
+ protected GetModelSnapshotsRequest doParseInstance(XContentParser parser) throws IOException {
+ return GetModelSnapshotsRequest.PARSER.apply(parser, null);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return false;
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsResponseTests.java
new file mode 100644
index 0000000000000..60288233e7286
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/GetModelSnapshotsResponseTests.java
@@ -0,0 +1,51 @@
+/*
+ * 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.client.ml;
+
+import org.elasticsearch.client.ml.job.process.ModelSnapshot;
+import org.elasticsearch.client.ml.job.process.ModelSnapshotTests;
+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 GetModelSnapshotsResponseTests extends AbstractXContentTestCase {
+
+ @Override
+ protected GetModelSnapshotsResponse createTestInstance() {
+ int listSize = randomInt(10);
+ List modelSnapshots = new ArrayList<>(listSize);
+ for (int j = 0; j < listSize; j++) {
+ modelSnapshots.add(ModelSnapshotTests.createRandomizedBuilder());
+ }
+ return new GetModelSnapshotsResponse(modelSnapshots, listSize);
+ }
+
+ @Override
+ protected GetModelSnapshotsResponse doParseInstance(XContentParser parser) throws IOException {
+ return GetModelSnapshotsResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return true;
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/process/ModelSnapshotTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/process/ModelSnapshotTests.java
index 9669f9bfa4f4e..15565c28391af 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/process/ModelSnapshotTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ml/job/process/ModelSnapshotTests.java
@@ -158,6 +158,10 @@ protected ModelSnapshot createTestInstance() {
}
public static ModelSnapshot createRandomized() {
+ return createRandomizedBuilder().build();
+ }
+
+ public static ModelSnapshot.Builder createRandomizedBuilder() {
ModelSnapshot.Builder modelSnapshot = new ModelSnapshot.Builder(randomAlphaOfLengthBetween(1, 20));
modelSnapshot.setMinVersion(Version.CURRENT);
modelSnapshot.setTimestamp(new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
@@ -171,7 +175,7 @@ public static ModelSnapshot createRandomized() {
new Date(TimeValue.parseTimeValue(randomTimeValue(), "test").millis()));
modelSnapshot.setQuantiles(QuantilesTests.createRandomized());
modelSnapshot.setRetain(randomBoolean());
- return modelSnapshot.build();
+ return modelSnapshot;
}
@Override
diff --git a/docs/java-rest/high-level/ml/get-model-snapshots.asciidoc b/docs/java-rest/high-level/ml/get-model-snapshots.asciidoc
new file mode 100644
index 0000000000000..c23cdcabdf4aa
--- /dev/null
+++ b/docs/java-rest/high-level/ml/get-model-snapshots.asciidoc
@@ -0,0 +1,76 @@
+--
+:api: get-model-snapshots
+:request: GetModelSnapshotsRequest
+:response: GetModelSnapshotsResponse
+--
+[id="{upid}-{api}"]
+=== Get Model Snapshots API
+
+The Get Model Snapshots API retrieves one or more model snapshot results.
+It accepts a +{request}+ object and responds
+with a +{response}+ object.
+
+[id="{upid}-{api}-request"]
+==== Get Model Snapshots Request
+
+A +{request}+ object gets created with an existing non-null `jobId`.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> Constructing a new request referencing an existing `jobId`
+
+==== Optional Arguments
+The following arguments are optional:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-snapshot-id]
+--------------------------------------------------
+<1> The id of the snapshot to get. Otherwise it will return all snapshots.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-desc]
+--------------------------------------------------
+<1> If `true`, the snapshots are sorted in descending order. Defaults to `false`.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-end]
+--------------------------------------------------
+<1> Snapshots with timestamps earlier than this time will be returned.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-sort]
+--------------------------------------------------
+<1> The field to sort snapshots on. Defaults to `timestamp`.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-start]
+--------------------------------------------------
+<1> Snapshots with timestamps on or after this time will be returned.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-page]
+--------------------------------------------------
+<1> The page parameters `from` and `size`. `from` specifies the number of snapshots to skip.
+`size` specifies the maximum number of snapshots to retrieve. Defaults to `0` and `100` respectively.
+
+include::../execution.asciidoc[]
+
+[id="{upid}-{api}-response"]
+==== Get Model Snapshots Response
+
+The returned +{response}+ contains the requested snapshots:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> The count of snapshots that were matched
+<2> The snapshots retrieved
\ No newline at end of file
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 7deb214d29628..33810aeabe50c 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -265,6 +265,7 @@ The Java High Level REST Client supports the following Machine Learning APIs:
* <<{upid}-put-calendar>>
* <<{upid}-delete-calendar>>
* <<{upid}-put-filter>>
+* <<{upid}-get-model-snapshots>>
* <<{upid}-get-filters>>
include::ml/put-job.asciidoc[]
@@ -295,6 +296,7 @@ include::ml/get-calendars.asciidoc[]
include::ml/put-calendar.asciidoc[]
include::ml/delete-calendar.asciidoc[]
include::ml/put-filter.asciidoc[]
+include::ml/get-model-snapshots.asciidoc[]
include::ml/get-filters.asciidoc[]
== Migration APIs