Skip to content

Commit 3035cd3

Browse files
authored
Change SLM stats format (#46991)
Using arrays of objects with embedded IDs is preferred for new APIs over using entity IDs as JSON keys. This commit changes the SLM stats API to use the preferred format.
1 parent b269a77 commit 3035cd3

File tree

4 files changed

+68
-35
lines changed

4 files changed

+68
-35
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/slm/SnapshotLifecycleStats.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public class SnapshotLifecycleStats implements ToXContentObject {
7474
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_FAILED);
7575
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_TIMED_OUT);
7676
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_TIME_MILLIS);
77-
PARSER.declareNamedObjects(ConstructingObjectParser.constructorArg(), (p, c, n) -> SnapshotPolicyStats.parse(p, n), POLICY_STATS);
77+
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), SnapshotPolicyStats.PARSER, POLICY_STATS);
7878
}
7979

8080
// Package visible for testing
@@ -178,22 +178,25 @@ public static class SnapshotPolicyStats implements ToXContentFragment {
178178
private final long snapshotsDeleted;
179179
private final long snapshotDeleteFailures;
180180

181+
public static final ParseField POLICY_ID = new ParseField("policy");
181182
static final ParseField SNAPSHOTS_TAKEN = new ParseField("snapshots_taken");
182183
static final ParseField SNAPSHOTS_FAILED = new ParseField("snapshots_failed");
183184
static final ParseField SNAPSHOTS_DELETED = new ParseField("snapshots_deleted");
184185
static final ParseField SNAPSHOT_DELETION_FAILURES = new ParseField("snapshot_deletion_failures");
185186

186-
private static final ConstructingObjectParser<SnapshotPolicyStats, String> PARSER =
187+
private static final ConstructingObjectParser<SnapshotPolicyStats, Void> PARSER =
187188
new ConstructingObjectParser<>("snapshot_policy_stats", true,
188-
(a, id) -> {
189-
long taken = (long) a[0];
190-
long failed = (long) a[1];
191-
long deleted = (long) a[2];
192-
long deleteFailed = (long) a[3];
189+
a -> {
190+
String id = (String) a[0];
191+
long taken = (long) a[1];
192+
long failed = (long) a[2];
193+
long deleted = (long) a[3];
194+
long deleteFailed = (long) a[4];
193195
return new SnapshotPolicyStats(id, taken, failed, deleted, deleteFailed);
194196
});
195197

196198
static {
199+
PARSER.declareString(ConstructingObjectParser.constructorArg(), POLICY_ID);
197200
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_TAKEN);
198201
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_FAILED);
199202
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_DELETED);
@@ -209,7 +212,11 @@ public SnapshotPolicyStats(String policyId, long snapshotsTaken, long snapshotsF
209212
}
210213

211214
public static SnapshotPolicyStats parse(XContentParser parser, String policyId) {
212-
return PARSER.apply(parser, policyId);
215+
return PARSER.apply(parser, null);
216+
}
217+
218+
public String getPolicyId() {
219+
return policyId;
213220
}
214221

215222
public long getSnapshotsTaken() {

docs/reference/ilm/apis/slm-api.asciidoc

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ The output looks similar to the following:
142142
"retention": {}
143143
},
144144
"stats": {
145+
"policy": "daily-snapshots",
145146
"snapshots_taken": 0,
146147
"snapshots_failed": 0,
147148
"snapshots_deleted": 0,
@@ -231,6 +232,7 @@ Which, in this case shows an error because the index did not exist:
231232
"retention": {}
232233
},
233234
"stats": {
235+
"policy": "daily-snapshots",
234236
"snapshots_taken": 0,
235237
"snapshots_failed": 1,
236238
"snapshots_deleted": 0,
@@ -319,6 +321,7 @@ Which now includes the successful snapshot information:
319321
"retention": {}
320322
},
321323
"stats": {
324+
"policy": "daily-snapshots",
322325
"snapshots_taken": 1,
323326
"snapshots_failed": 1,
324327
"snapshots_deleted": 0,
@@ -371,14 +374,15 @@ Which returns a response similar to:
371374
"retention_timed_out": 0,
372375
"retention_deletion_time": "1.4s",
373376
"retention_deletion_time_millis": 1404,
374-
"policy_metrics": {
375-
"daily-snapshots": {
377+
"policy_metrics": [
378+
{
379+
"policy": "daily-snapshots",
376380
"snapshots_taken": 1,
377381
"snapshots_failed": 1,
378382
"snapshots_deleted": 0,
379383
"snapshot_deletion_failures": 0
380384
}
381-
},
385+
],
382386
"total_snapshots_taken": 1,
383387
"total_snapshots_failed": 1,
384388
"total_snapshots_deleted": 0,

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/slm/SnapshotLifecycleStats.java

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.io.IOException;
2323
import java.util.Collections;
24+
import java.util.Comparator;
2425
import java.util.HashMap;
2526
import java.util.List;
2627
import java.util.Map;
@@ -71,7 +72,7 @@ public class SnapshotLifecycleStats implements Writeable, ToXContentObject {
7172
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_FAILED);
7273
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_TIMED_OUT);
7374
PARSER.declareLong(ConstructingObjectParser.constructorArg(), RETENTION_TIME_MILLIS);
74-
PARSER.declareNamedObjects(ConstructingObjectParser.constructorArg(), (p, c, n) -> SnapshotPolicyStats.parse(p, n), POLICY_STATS);
75+
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), SnapshotPolicyStats.PARSER, POLICY_STATS);
7576
}
7677

7778
public SnapshotLifecycleStats() {
@@ -213,23 +214,25 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
213214
builder.field(RETENTION_TIME.getPreferredName(), retentionTime);
214215
builder.field(RETENTION_TIME_MILLIS.getPreferredName(), retentionTime.millis());
215216

216-
Map<String, SnapshotPolicyStats> metrics = getMetrics();
217-
long totalTaken = metrics.values().stream().mapToLong(s -> s.snapshotsTaken.count()).sum();
218-
long totalFailed = metrics.values().stream().mapToLong(s -> s.snapshotsFailed.count()).sum();
219-
long totalDeleted = metrics.values().stream().mapToLong(s -> s.snapshotsDeleted.count()).sum();
220-
long totalDeleteFailures = metrics.values().stream().mapToLong(s -> s.snapshotDeleteFailures.count()).sum();
217+
List<SnapshotPolicyStats> metrics = getMetrics().values().stream()
218+
.sorted(Comparator.comparing(SnapshotPolicyStats::getPolicyId)) // maintain a consistent order when serializing
219+
.collect(Collectors.toList());
220+
long totalTaken = metrics.stream().mapToLong(s -> s.snapshotsTaken.count()).sum();
221+
long totalFailed = metrics.stream().mapToLong(s -> s.snapshotsFailed.count()).sum();
222+
long totalDeleted = metrics.stream().mapToLong(s -> s.snapshotsDeleted.count()).sum();
223+
long totalDeleteFailures = metrics.stream().mapToLong(s -> s.snapshotDeleteFailures.count()).sum();
221224
builder.field(TOTAL_TAKEN.getPreferredName(), totalTaken);
222225
builder.field(TOTAL_FAILED.getPreferredName(), totalFailed);
223226
builder.field(TOTAL_DELETIONS.getPreferredName(), totalDeleted);
224227
builder.field(TOTAL_DELETION_FAILURES.getPreferredName(), totalDeleteFailures);
225-
builder.startObject(POLICY_STATS.getPreferredName());
226-
for (Map.Entry<String, SnapshotPolicyStats> policy : metrics.entrySet()) {
227-
SnapshotPolicyStats perPolicyMetrics = policy.getValue();
228-
builder.startObject(perPolicyMetrics.policyId);
229-
perPolicyMetrics.toXContent(builder, params);
228+
229+
builder.startArray(POLICY_STATS.getPreferredName());
230+
for (SnapshotPolicyStats stats : metrics) {
231+
builder.startObject();
232+
stats.toXContent(builder, params);
230233
builder.endObject();
231234
}
232-
builder.endObject();
235+
builder.endArray();
233236
builder.endObject();
234237
return builder;
235238
}
@@ -268,22 +271,25 @@ public static class SnapshotPolicyStats implements Writeable, ToXContentFragment
268271
private final CounterMetric snapshotsDeleted = new CounterMetric();
269272
private final CounterMetric snapshotDeleteFailures = new CounterMetric();
270273

274+
public static final ParseField POLICY_ID = new ParseField("policy");
271275
public static final ParseField SNAPSHOTS_TAKEN = new ParseField("snapshots_taken");
272276
public static final ParseField SNAPSHOTS_FAILED = new ParseField("snapshots_failed");
273277
public static final ParseField SNAPSHOTS_DELETED = new ParseField("snapshots_deleted");
274278
public static final ParseField SNAPSHOT_DELETION_FAILURES = new ParseField("snapshot_deletion_failures");
275279

276-
private static final ConstructingObjectParser<SnapshotPolicyStats, String> PARSER =
280+
static final ConstructingObjectParser<SnapshotPolicyStats, Void> PARSER =
277281
new ConstructingObjectParser<>("snapshot_policy_stats", true,
278-
(a, id) -> {
279-
long taken = (long) a[0];
280-
long failed = (long) a[1];
281-
long deleted = (long) a[2];
282-
long deleteFailed = (long) a[3];
282+
a -> {
283+
String id = (String) a[0];
284+
long taken = (long) a[1];
285+
long failed = (long) a[2];
286+
long deleted = (long) a[3];
287+
long deleteFailed = (long) a[4];
283288
return new SnapshotPolicyStats(id, taken, failed, deleted, deleteFailed);
284289
});
285290

286291
static {
292+
PARSER.declareString(ConstructingObjectParser.constructorArg(), POLICY_ID);
287293
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_TAKEN);
288294
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_FAILED);
289295
PARSER.declareLong(ConstructingObjectParser.constructorArg(), SNAPSHOTS_DELETED);
@@ -310,8 +316,8 @@ public SnapshotPolicyStats(StreamInput in) throws IOException {
310316
this.snapshotDeleteFailures.inc(in.readVLong());
311317
}
312318

313-
public static SnapshotPolicyStats parse(XContentParser parser, String policyId) {
314-
return PARSER.apply(parser, policyId);
319+
public static SnapshotPolicyStats parse(XContentParser parser) {
320+
return PARSER.apply(parser, null);
315321
}
316322

317323
public SnapshotPolicyStats merge(SnapshotPolicyStats other) {
@@ -339,6 +345,10 @@ void snapshotDeleteFailure() {
339345
snapshotDeleteFailures.inc();
340346
}
341347

348+
public String getPolicyId() {
349+
return policyId;
350+
}
351+
342352
@Override
343353
public void writeTo(StreamOutput out) throws IOException {
344354
out.writeString(policyId);
@@ -372,6 +382,7 @@ public boolean equals(Object obj) {
372382

373383
@Override
374384
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
385+
builder.field(SnapshotPolicyStats.POLICY_ID.getPreferredName(), policyId);
375386
builder.field(SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName(), snapshotsTaken.count());
376387
builder.field(SnapshotPolicyStats.SNAPSHOTS_FAILED.getPreferredName(), snapshotsFailed.count());
377388
builder.field(SnapshotPolicyStats.SNAPSHOTS_DELETED.getPreferredName(), snapshotsDeleted.count());

x-pack/plugin/ilm/qa/multi-node/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecycleRestIT.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
import java.util.List;
4242
import java.util.Map;
4343
import java.util.concurrent.TimeUnit;
44+
import java.util.function.Function;
45+
import java.util.stream.Collectors;
4446

4547
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
4648
import static org.elasticsearch.xpack.core.slm.history.SnapshotHistoryItem.CREATE_OPERATION;
@@ -134,7 +136,7 @@ public void testFullPolicySnapshot() throws Exception {
134136
assertHistoryIsPresent(policyName, true, repoId, CREATE_OPERATION);
135137

136138
Map<String, Object> stats = getSLMStats();
137-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
139+
Map<String, Object> policyStats = policyStatsAsMap(stats);
138140
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
139141
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
140142
int totalTaken = (int) stats.get(SnapshotLifecycleStats.TOTAL_TAKEN.getPreferredName());
@@ -183,7 +185,7 @@ public void testPolicyFailure() throws Exception {
183185
assertHistoryIsPresent(policyName, false, repoName, CREATE_OPERATION);
184186

185187
Map<String, Object> stats = getSLMStats();
186-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
188+
Map<String, Object> policyStats = policyStatsAsMap(stats);
187189
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
188190
int snapsFailed = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_FAILED.getPreferredName());
189191
int totalFailed = (int) stats.get(SnapshotLifecycleStats.TOTAL_FAILED.getPreferredName());
@@ -232,7 +234,7 @@ public void testPolicyManualExecution() throws Exception {
232234
}
233235

234236
Map<String, Object> stats = getSLMStats();
235-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
237+
Map<String, Object> policyStats = policyStatsAsMap(stats);
236238
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
237239
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
238240
int totalTaken = (int) stats.get(SnapshotLifecycleStats.TOTAL_TAKEN.getPreferredName());
@@ -304,7 +306,7 @@ public void testBasicTimeBasedRetenion() throws Exception {
304306
assertHistoryIsPresent(policyName, true, repoId, DELETE_OPERATION);
305307

306308
Map<String, Object> stats = getSLMStats();
307-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
309+
Map<String, Object> policyStats = policyStatsAsMap(stats);
308310
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
309311
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
310312
int snapsDeleted = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_DELETED.getPreferredName());
@@ -488,4 +490,13 @@ private static void index(RestClient client, String index, String id, Object...
488490
request.setJsonEntity(Strings.toString(document));
489491
assertOK(client.performRequest(request));
490492
}
493+
494+
@SuppressWarnings("unchecked")
495+
private static Map<String, Object> policyStatsAsMap(Map<String, Object> stats) {
496+
return ((List<Map<String, Object>>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName()))
497+
.stream()
498+
.collect(Collectors.toMap(
499+
m -> (String) m.get(SnapshotLifecycleStats.SnapshotPolicyStats.POLICY_ID.getPreferredName()),
500+
Function.identity()));
501+
}
491502
}

0 commit comments

Comments
 (0)