Skip to content

Commit 1572080

Browse files
authored
[ML] Add DatafeedTimingStats to datafeed GetDatafeedStatsAction.Response (#43045)
1 parent dbe8d64 commit 1572080

File tree

53 files changed

+1731
-239
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1731
-239
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/ml/datafeed/DatafeedStats.java

+18-4
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ public class DatafeedStats implements ToXContentObject {
4141
private final NodeAttributes node;
4242
@Nullable
4343
private final String assignmentExplanation;
44+
@Nullable
45+
private final DatafeedTimingStats timingStats;
4446

4547
public static final ParseField ASSIGNMENT_EXPLANATION = new ParseField("assignment_explanation");
4648
public static final ParseField NODE = new ParseField("node");
49+
public static final ParseField TIMING_STATS = new ParseField("timing_stats");
4750

4851
public static final ConstructingObjectParser<DatafeedStats, Void> PARSER = new ConstructingObjectParser<>("datafeed_stats",
4952
true,
@@ -52,22 +55,25 @@ public class DatafeedStats implements ToXContentObject {
5255
DatafeedState datafeedState = DatafeedState.fromString((String)a[1]);
5356
NodeAttributes nodeAttributes = (NodeAttributes)a[2];
5457
String assignmentExplanation = (String)a[3];
55-
return new DatafeedStats(datafeedId, datafeedState, nodeAttributes, assignmentExplanation);
58+
DatafeedTimingStats timingStats = (DatafeedTimingStats)a[4];
59+
return new DatafeedStats(datafeedId, datafeedState, nodeAttributes, assignmentExplanation, timingStats);
5660
} );
5761

5862
static {
5963
PARSER.declareString(ConstructingObjectParser.constructorArg(), DatafeedConfig.ID);
6064
PARSER.declareString(ConstructingObjectParser.constructorArg(), DatafeedState.STATE);
6165
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), NodeAttributes.PARSER, NODE);
6266
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), ASSIGNMENT_EXPLANATION);
67+
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), DatafeedTimingStats.PARSER, TIMING_STATS);
6368
}
6469

6570
public DatafeedStats(String datafeedId, DatafeedState datafeedState, @Nullable NodeAttributes node,
66-
@Nullable String assignmentExplanation) {
71+
@Nullable String assignmentExplanation, @Nullable DatafeedTimingStats timingStats) {
6772
this.datafeedId = Objects.requireNonNull(datafeedId);
6873
this.datafeedState = Objects.requireNonNull(datafeedState);
6974
this.node = node;
7075
this.assignmentExplanation = assignmentExplanation;
76+
this.timingStats = timingStats;
7177
}
7278

7379
public String getDatafeedId() {
@@ -86,6 +92,10 @@ public String getAssignmentExplanation() {
8692
return assignmentExplanation;
8793
}
8894

95+
public DatafeedTimingStats getDatafeedTimingStats() {
96+
return timingStats;
97+
}
98+
8999
@Override
90100
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
91101
builder.startObject();
@@ -110,13 +120,16 @@ public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params par
110120
if (assignmentExplanation != null) {
111121
builder.field(ASSIGNMENT_EXPLANATION.getPreferredName(), assignmentExplanation);
112122
}
123+
if (timingStats != null) {
124+
builder.field(TIMING_STATS.getPreferredName(), timingStats);
125+
}
113126
builder.endObject();
114127
return builder;
115128
}
116129

117130
@Override
118131
public int hashCode() {
119-
return Objects.hash(datafeedId, datafeedState.toString(), node, assignmentExplanation);
132+
return Objects.hash(datafeedId, datafeedState.toString(), node, assignmentExplanation, timingStats);
120133
}
121134

122135
@Override
@@ -131,6 +144,7 @@ public boolean equals(Object obj) {
131144
return Objects.equals(datafeedId, other.datafeedId) &&
132145
Objects.equals(this.datafeedState, other.datafeedState) &&
133146
Objects.equals(this.node, other.node) &&
134-
Objects.equals(this.assignmentExplanation, other.assignmentExplanation);
147+
Objects.equals(this.assignmentExplanation, other.assignmentExplanation) &&
148+
Objects.equals(this.timingStats, other.timingStats);
135149
}
136150
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml.datafeed;
20+
21+
import org.elasticsearch.common.Nullable;
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.Strings;
24+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
25+
import org.elasticsearch.common.xcontent.ToXContent;
26+
import org.elasticsearch.common.xcontent.ToXContentObject;
27+
import org.elasticsearch.common.xcontent.XContentBuilder;
28+
29+
import java.io.IOException;
30+
import java.util.Objects;
31+
32+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
33+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
34+
35+
public class DatafeedTimingStats implements ToXContentObject {
36+
37+
public static final ParseField JOB_ID = new ParseField("job_id");
38+
public static final ParseField SEARCH_COUNT = new ParseField("search_count");
39+
public static final ParseField TOTAL_SEARCH_TIME_MS = new ParseField("total_search_time_ms");
40+
41+
public static final ParseField TYPE = new ParseField("datafeed_timing_stats");
42+
43+
public static final ConstructingObjectParser<DatafeedTimingStats, Void> PARSER = createParser();
44+
45+
private static ConstructingObjectParser<DatafeedTimingStats, Void> createParser() {
46+
ConstructingObjectParser<DatafeedTimingStats, Void> parser =
47+
new ConstructingObjectParser<>(
48+
"datafeed_timing_stats",
49+
true,
50+
args -> {
51+
String jobId = (String) args[0];
52+
Long searchCount = (Long) args[1];
53+
Double totalSearchTimeMs = (Double) args[2];
54+
return new DatafeedTimingStats(jobId, getOrDefault(searchCount, 0L), getOrDefault(totalSearchTimeMs, 0.0));
55+
});
56+
parser.declareString(constructorArg(), JOB_ID);
57+
parser.declareLong(optionalConstructorArg(), SEARCH_COUNT);
58+
parser.declareDouble(optionalConstructorArg(), TOTAL_SEARCH_TIME_MS);
59+
return parser;
60+
}
61+
62+
private final String jobId;
63+
private long searchCount;
64+
private double totalSearchTimeMs;
65+
66+
public DatafeedTimingStats(String jobId, long searchCount, double totalSearchTimeMs) {
67+
this.jobId = Objects.requireNonNull(jobId);
68+
this.searchCount = searchCount;
69+
this.totalSearchTimeMs = totalSearchTimeMs;
70+
}
71+
72+
public String getJobId() {
73+
return jobId;
74+
}
75+
76+
public long getSearchCount() {
77+
return searchCount;
78+
}
79+
80+
public double getTotalSearchTimeMs() {
81+
return totalSearchTimeMs;
82+
}
83+
84+
@Override
85+
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
86+
builder.startObject();
87+
builder.field(JOB_ID.getPreferredName(), jobId);
88+
builder.field(SEARCH_COUNT.getPreferredName(), searchCount);
89+
builder.field(TOTAL_SEARCH_TIME_MS.getPreferredName(), totalSearchTimeMs);
90+
builder.endObject();
91+
return builder;
92+
}
93+
94+
@Override
95+
public boolean equals(Object obj) {
96+
if (this == obj) {
97+
return true;
98+
}
99+
if (obj == null || getClass() != obj.getClass()) {
100+
return false;
101+
}
102+
103+
DatafeedTimingStats other = (DatafeedTimingStats) obj;
104+
return Objects.equals(this.jobId, other.jobId)
105+
&& this.searchCount == other.searchCount
106+
&& this.totalSearchTimeMs == other.totalSearchTimeMs;
107+
}
108+
109+
@Override
110+
public int hashCode() {
111+
return Objects.hash(jobId, searchCount, totalSearchTimeMs);
112+
}
113+
114+
@Override
115+
public String toString() {
116+
return Strings.toString(this);
117+
}
118+
119+
private static <T> T getOrDefault(@Nullable T value, T defaultValue) {
120+
return value != null ? value : defaultValue;
121+
}
122+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/ml/datafeed/DatafeedStatsTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public static DatafeedStats createRandomInstance() {
5050
attributes);
5151
}
5252
String assignmentReason = randomBoolean() ? randomAlphaOfLength(10) : null;
53-
return new DatafeedStats(datafeedId, datafeedState, nodeAttributes, assignmentReason);
53+
DatafeedTimingStats timingStats = DatafeedTimingStatsTests.createRandomInstance();
54+
return new DatafeedStats(datafeedId, datafeedState, nodeAttributes, assignmentReason, timingStats);
5455
}
5556

5657
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.elasticsearch.client.ml.datafeed;
20+
21+
import org.elasticsearch.common.xcontent.DeprecationHandler;
22+
import org.elasticsearch.common.xcontent.XContentFactory;
23+
import org.elasticsearch.common.xcontent.XContentParser;
24+
import org.elasticsearch.common.xcontent.XContentType;
25+
import org.elasticsearch.test.AbstractXContentTestCase;
26+
27+
import java.io.IOException;
28+
29+
import static org.hamcrest.Matchers.equalTo;
30+
31+
public class DatafeedTimingStatsTests extends AbstractXContentTestCase<DatafeedTimingStats> {
32+
33+
private static final String JOB_ID = "my-job-id";
34+
35+
public static DatafeedTimingStats createRandomInstance() {
36+
return new DatafeedTimingStats(randomAlphaOfLength(10), randomLong(), randomDouble());
37+
}
38+
39+
@Override
40+
protected DatafeedTimingStats createTestInstance() {
41+
return createRandomInstance();
42+
}
43+
44+
@Override
45+
protected DatafeedTimingStats doParseInstance(XContentParser parser) throws IOException {
46+
return DatafeedTimingStats.PARSER.apply(parser, null);
47+
}
48+
49+
@Override
50+
protected boolean supportsUnknownFields() {
51+
return true;
52+
}
53+
54+
public void testParse_OptionalFieldsAbsent() throws IOException {
55+
String json = "{\"job_id\": \"my-job-id\"}";
56+
try (XContentParser parser =
57+
XContentFactory.xContent(XContentType.JSON).createParser(
58+
xContentRegistry(), DeprecationHandler.THROW_UNSUPPORTED_OPERATION, json)) {
59+
DatafeedTimingStats stats = DatafeedTimingStats.PARSER.apply(parser, null);
60+
assertThat(stats.getJobId(), equalTo(JOB_ID));
61+
assertThat(stats.getSearchCount(), equalTo(0L));
62+
assertThat(stats.getTotalSearchTimeMs(), equalTo(0.0));
63+
}
64+
}
65+
66+
public void testEquals() {
67+
DatafeedTimingStats stats1 = new DatafeedTimingStats(JOB_ID, 5, 100.0);
68+
DatafeedTimingStats stats2 = new DatafeedTimingStats(JOB_ID, 5, 100.0);
69+
DatafeedTimingStats stats3 = new DatafeedTimingStats(JOB_ID, 5, 200.0);
70+
71+
assertTrue(stats1.equals(stats1));
72+
assertTrue(stats1.equals(stats2));
73+
assertFalse(stats2.equals(stats3));
74+
}
75+
76+
public void testHashCode() {
77+
DatafeedTimingStats stats1 = new DatafeedTimingStats(JOB_ID, 5, 100.0);
78+
DatafeedTimingStats stats2 = new DatafeedTimingStats(JOB_ID, 5, 100.0);
79+
DatafeedTimingStats stats3 = new DatafeedTimingStats(JOB_ID, 5, 200.0);
80+
81+
assertEquals(stats1.hashCode(), stats1.hashCode());
82+
assertEquals(stats1.hashCode(), stats2.hashCode());
83+
assertNotEquals(stats2.hashCode(), stats3.hashCode());
84+
}
85+
86+
public void testConstructorAndGetters() {
87+
DatafeedTimingStats stats = new DatafeedTimingStats(JOB_ID, 5, 123.456);
88+
assertThat(stats.getJobId(), equalTo(JOB_ID));
89+
assertThat(stats.getSearchCount(), equalTo(5L));
90+
assertThat(stats.getTotalSearchTimeMs(), equalTo(123.456));
91+
}
92+
}

docs/reference/ml/apis/datafeedresource.asciidoc

+7
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,10 @@ update their values:
143143
`started`::: The {dfeed} is actively receiving data.
144144
`stopped`::: The {dfeed} is stopped and will not receive data until it is
145145
re-started.
146+
147+
`timing_stats`::
148+
(object) An object that provides statistical information about timing aspect of this datafeed. +
149+
`job_id`::: A numerical character string that uniquely identifies the job.
150+
`search_count`::: Number of searches performed by this datafeed.
151+
`total_search_time_ms`::: Total time the datafeed spent searching in milliseconds.
152+

docs/reference/ml/apis/get-datafeed-stats.asciidoc

+6-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,12 @@ The API returns the following results:
9090
"ml.max_open_jobs": "20"
9191
}
9292
},
93-
"assignment_explanation": ""
93+
"assignment_explanation": "",
94+
"timing_stats": {
95+
"job_id": "job-total-requests",
96+
"search_count": 20,
97+
"total_search_time_ms": 120.5
98+
}
9499
}
95100
]
96101
}

0 commit comments

Comments
 (0)