Skip to content

Commit a46eef9

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 35f0566 commit a46eef9

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;
@@ -131,7 +133,7 @@ public void testFullPolicySnapshot() throws Exception {
131133
assertHistoryIsPresent(policyName, true, repoId, CREATE_OPERATION);
132134

133135
Map<String, Object> stats = getSLMStats();
134-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
136+
Map<String, Object> policyStats = policyStatsAsMap(stats);
135137
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
136138
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
137139
int totalTaken = (int) stats.get(SnapshotLifecycleStats.TOTAL_TAKEN.getPreferredName());
@@ -180,7 +182,7 @@ public void testPolicyFailure() throws Exception {
180182
assertHistoryIsPresent(policyName, false, repoName, CREATE_OPERATION);
181183

182184
Map<String, Object> stats = getSLMStats();
183-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
185+
Map<String, Object> policyStats = policyStatsAsMap(stats);
184186
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
185187
int snapsFailed = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_FAILED.getPreferredName());
186188
int totalFailed = (int) stats.get(SnapshotLifecycleStats.TOTAL_FAILED.getPreferredName());
@@ -229,7 +231,7 @@ public void testPolicyManualExecution() throws Exception {
229231
}
230232

231233
Map<String, Object> stats = getSLMStats();
232-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
234+
Map<String, Object> policyStats = policyStatsAsMap(stats);
233235
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
234236
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
235237
int totalTaken = (int) stats.get(SnapshotLifecycleStats.TOTAL_TAKEN.getPreferredName());
@@ -301,7 +303,7 @@ public void testBasicTimeBasedRetenion() throws Exception {
301303
assertHistoryIsPresent(policyName, true, repoId, DELETE_OPERATION);
302304

303305
Map<String, Object> stats = getSLMStats();
304-
Map<String, Object> policyStats = (Map<String, Object>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName());
306+
Map<String, Object> policyStats = policyStatsAsMap(stats);
305307
Map<String, Object> policyIdStats = (Map<String, Object>) policyStats.get(policyName);
306308
int snapsTaken = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_TAKEN.getPreferredName());
307309
int snapsDeleted = (int) policyIdStats.get(SnapshotLifecycleStats.SnapshotPolicyStats.SNAPSHOTS_DELETED.getPreferredName());
@@ -482,4 +484,13 @@ private static void index(RestClient client, String index, String id, Object...
482484
request.setJsonEntity(Strings.toString(document));
483485
assertOK(client.performRequest(request));
484486
}
487+
488+
@SuppressWarnings("unchecked")
489+
private static Map<String, Object> policyStatsAsMap(Map<String, Object> stats) {
490+
return ((List<Map<String, Object>>) stats.get(SnapshotLifecycleStats.POLICY_STATS.getPreferredName()))
491+
.stream()
492+
.collect(Collectors.toMap(
493+
m -> (String) m.get(SnapshotLifecycleStats.SnapshotPolicyStats.POLICY_ID.getPreferredName()),
494+
Function.identity()));
495+
}
485496
}

0 commit comments

Comments
 (0)