Skip to content

Commit 02fc46a

Browse files
authored
Add support for impact_areas to health impacts (#85830)
This adds an `impact_areas` section to the impacts returned by the health API. eg. the `shards_availability` indicator might be returning: ``` "impacts": [ { "severity": 1, "description":"Cannot add data to 1 index [red-index]. Searches might return incomplete results.", "impact_areas": [ "ingest","search" ] }, { "severity": 2, "description": "Searches might return slower than usual. Fewer redundant copies of the data exist on 2 indices [.ds-logslogslogs-2022.04.12-000001, my-index-000001].", "impact_areas": [ "search" ] } ] ```
1 parent 4f58cf2 commit 02fc46a

File tree

7 files changed

+97
-25
lines changed

7 files changed

+97
-25
lines changed

docs/changelog/85830.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 85830
2+
summary: Add support for `impact_areas` to health impacts
3+
area: Health
4+
type: feature
5+
issues:
6+
- 85829

server/src/main/java/org/elasticsearch/cluster/routing/allocation/ShardsAvailabilityHealthIndicatorService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.health.HealthIndicatorResult;
2424
import org.elasticsearch.health.HealthIndicatorService;
2525
import org.elasticsearch.health.HealthStatus;
26+
import org.elasticsearch.health.ImpactArea;
2627
import org.elasticsearch.health.SimpleHealthIndicatorDetails;
2728

2829
import java.util.ArrayList;
@@ -241,7 +242,7 @@ public List<HealthIndicatorImpact> getImpacts() {
241242
primaries.indicesWithUnavailableShards.size() == 1 ? "index" : "indices",
242243
getTruncatedIndicesString(primaries.indicesWithUnavailableShards, clusterMetadata)
243244
);
244-
impacts.add(new HealthIndicatorImpact(1, impactDescription));
245+
impacts.add(new HealthIndicatorImpact(1, impactDescription, List.of(ImpactArea.INGEST, ImpactArea.SEARCH)));
245246
}
246247
/*
247248
* It is possible that we're working with an intermediate cluster state, and that for an index we have no primary but a replica
@@ -258,7 +259,7 @@ public List<HealthIndicatorImpact> getImpacts() {
258259
indicesWithUnavailableReplicasOnly.size() == 1 ? "index" : "indices",
259260
getTruncatedIndicesString(indicesWithUnavailableReplicasOnly, clusterMetadata)
260261
);
261-
impacts.add(new HealthIndicatorImpact(3, impactDescription));
262+
impacts.add(new HealthIndicatorImpact(2, impactDescription, List.of(ImpactArea.SEARCH)));
262263
}
263264
return impacts;
264265
}

server/src/main/java/org/elasticsearch/health/HealthIndicatorImpact.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,37 @@
88

99
package org.elasticsearch.health;
1010

11+
import org.elasticsearch.common.Strings;
1112
import org.elasticsearch.xcontent.ToXContentObject;
1213
import org.elasticsearch.xcontent.XContentBuilder;
1314

1415
import java.io.IOException;
15-
import java.util.Objects;
16+
import java.util.List;
1617

17-
public record HealthIndicatorImpact(int severity, String impactDescription) implements ToXContentObject {
18+
public record HealthIndicatorImpact(int severity, String impactDescription, List<ImpactArea> impactAreas) implements ToXContentObject {
1819

1920
public HealthIndicatorImpact {
2021
if (severity < 0) {
2122
throw new IllegalArgumentException("Severity cannot be less than 0");
2223
}
23-
Objects.requireNonNull(impactDescription);
24+
if (Strings.isEmpty(impactDescription)) {
25+
throw new IllegalArgumentException("Impact description must be provided");
26+
}
27+
if (impactAreas == null || impactAreas.isEmpty()) {
28+
throw new IllegalArgumentException("At least one impact area must be provided");
29+
}
2430
}
2531

2632
@Override
2733
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
2834
builder.startObject();
2935
builder.field("severity", severity);
3036
builder.field("description", impactDescription);
37+
builder.startArray("impact_areas");
38+
for (ImpactArea impactArea : impactAreas) {
39+
builder.value(impactArea.displayValue());
40+
}
41+
builder.endArray();
3142
builder.endObject();
3243
return builder;
3344
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.health;
10+
11+
public enum ImpactArea {
12+
SEARCH("search"),
13+
INGEST("ingest");
14+
15+
private final String displayValue;
16+
17+
ImpactArea(String displayValue) {
18+
this.displayValue = displayValue;
19+
}
20+
21+
public String displayValue() {
22+
return displayValue;
23+
}
24+
}

server/src/test/java/org/elasticsearch/cluster/routing/allocation/ShardsAvailabilityHealthIndicatorServiceTests.java

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.elasticsearch.health.HealthIndicatorImpact;
2727
import org.elasticsearch.health.HealthIndicatorResult;
2828
import org.elasticsearch.health.HealthStatus;
29+
import org.elasticsearch.health.ImpactArea;
2930
import org.elasticsearch.health.SimpleHealthIndicatorDetails;
3031
import org.elasticsearch.index.Index;
3132
import org.elasticsearch.index.shard.ShardId;
@@ -115,8 +116,9 @@ public void testShouldBeYellowWhenThereAreUnassignedReplicas() {
115116
),
116117
List.of(
117118
new HealthIndicatorImpact(
118-
3,
119-
"Searches might return slower than usual. Fewer redundant copies of the data exist on 1 index [yellow-index]."
119+
2,
120+
"Searches might return slower than usual. Fewer redundant copies of the data exist on 1 index [yellow-index].",
121+
List.of(ImpactArea.SEARCH)
120122
)
121123
)
122124
)
@@ -139,7 +141,11 @@ public void testShouldBeRedWhenThereAreUnassignedPrimariesAndAssignedReplicas()
139141
"This cluster has 1 unavailable primary.",
140142
Map.of("unassigned_primaries", 1, "started_replicas", 1),
141143
List.of(
142-
new HealthIndicatorImpact(1, "Cannot add data to 1 index [red-index]. Searches might return incomplete results.")
144+
new HealthIndicatorImpact(
145+
1,
146+
"Cannot add data to 1 index [red-index]. Searches might return incomplete results.",
147+
List.of(ImpactArea.INGEST, ImpactArea.SEARCH)
148+
)
143149
)
144150
)
145151
)
@@ -158,7 +164,11 @@ public void testShouldBeRedWhenThereAreUnassignedPrimariesAndNoReplicas() {
158164
"This cluster has 1 unavailable primary.",
159165
Map.of("unassigned_primaries", 1),
160166
List.of(
161-
new HealthIndicatorImpact(1, "Cannot add data to 1 index [red-index]. Searches might return incomplete results.")
167+
new HealthIndicatorImpact(
168+
1,
169+
"Cannot add data to 1 index [red-index]. Searches might return incomplete results.",
170+
List.of(ImpactArea.INGEST, ImpactArea.SEARCH)
171+
)
162172
)
163173
)
164174
)
@@ -178,7 +188,11 @@ public void testShouldBeRedWhenThereAreUnassignedPrimariesAndUnassignedReplicasO
178188
assertEquals(1, result.impacts().size());
179189
assertEquals(
180190
result.impacts().get(0),
181-
new HealthIndicatorImpact(1, "Cannot add data to 1 index [red-index]. Searches might return incomplete results.")
191+
new HealthIndicatorImpact(
192+
1,
193+
"Cannot add data to 1 index [red-index]. Searches might return incomplete results.",
194+
List.of(ImpactArea.INGEST, ImpactArea.SEARCH)
195+
)
182196
);
183197
}
184198

@@ -203,16 +217,21 @@ public void testShouldBeRedWhenThereAreUnassignedPrimariesAndUnassignedReplicasO
203217
assertEquals(2, result.impacts().size());
204218
assertEquals(
205219
result.impacts().get(0),
206-
new HealthIndicatorImpact(1, "Cannot add data to 1 index [red-index]. Searches might return incomplete results.")
220+
new HealthIndicatorImpact(
221+
1,
222+
"Cannot add data to 1 index [red-index]. Searches might return incomplete results.",
223+
List.of(ImpactArea.INGEST, ImpactArea.SEARCH)
224+
)
207225
);
208226
// yellow-index-2 has the higher priority so it ought to be listed first:
209227
assertThat(
210228
result.impacts().get(1),
211229
equalTo(
212230
new HealthIndicatorImpact(
213-
3,
231+
2,
214232
"Searches might return slower than usual. Fewer redundant copies of the data exist on 2 indices [yellow-index-2, "
215-
+ "yellow-index-1]."
233+
+ "yellow-index-1].",
234+
List.of(ImpactArea.SEARCH)
216235
)
217236
)
218237
);
@@ -241,9 +260,10 @@ public void testSortByIndexPriority() {
241260
result.impacts().get(0),
242261
equalTo(
243262
new HealthIndicatorImpact(
244-
3,
263+
2,
245264
"Searches might return slower than usual. Fewer redundant copies of the data exist on 3 indices [index-2, "
246-
+ "index-1, index-3]."
265+
+ "index-1, index-3].",
266+
List.of(ImpactArea.SEARCH)
247267
)
248268
)
249269
);
@@ -317,9 +337,10 @@ public void testShouldBeYellowWhenRestartingReplicasReachedAllocationDelay() {
317337
Map.of("started_primaries", 1, "unassigned_replicas", 1),
318338
List.of(
319339
new HealthIndicatorImpact(
320-
3,
340+
2,
321341
"Searches might return slower than usual. Fewer redundant copies of the data exist on 1 index "
322-
+ "[restarting-index]."
342+
+ "[restarting-index].",
343+
List.of(ImpactArea.SEARCH)
323344
)
324345
)
325346
)
@@ -389,7 +410,8 @@ public void testShouldBeRedWhenRestartingPrimariesReachedAllocationDelayAndNoRep
389410
List.of(
390411
new HealthIndicatorImpact(
391412
1,
392-
"Cannot add data to 1 index [restarting-index]. Searches might return incomplete results."
413+
"Cannot add data to 1 index [restarting-index]. Searches might return incomplete results.",
414+
List.of(ImpactArea.INGEST, ImpactArea.SEARCH)
393415
)
394416
)
395417
)

server/src/test/java/org/elasticsearch/health/HealthIndicatorResultTests.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ public void testToXContent() throws Exception {
3232
List<HealthIndicatorImpact> impacts = new ArrayList<>();
3333
int impact1Severity = randomIntBetween(1, 5);
3434
String impact1Description = randomAlphaOfLength(30);
35-
impacts.add(new HealthIndicatorImpact(impact1Severity, impact1Description));
35+
ImpactArea firstImpactArea = randomFrom(ImpactArea.values());
36+
impacts.add(new HealthIndicatorImpact(impact1Severity, impact1Description, List.of(firstImpactArea)));
3637
int impact2Severity = randomIntBetween(1, 5);
3738
String impact2Description = randomAlphaOfLength(30);
38-
impacts.add(new HealthIndicatorImpact(impact2Severity, impact2Description));
39+
ImpactArea secondImpactArea = randomFrom(ImpactArea.values());
40+
impacts.add(new HealthIndicatorImpact(impact2Severity, impact2Description, List.of(secondImpactArea)));
3941
HealthIndicatorResult result = new HealthIndicatorResult(name, component, status, summary, details, impacts);
4042
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
4143
result.toXContent(builder, ToXContent.EMPTY_PARAMS);
@@ -47,9 +49,11 @@ public void testToXContent() throws Exception {
4749
Map<String, Object> expectedImpact1 = new HashMap<>();
4850
expectedImpact1.put("severity", impact1Severity);
4951
expectedImpact1.put("description", impact1Description);
52+
expectedImpact1.put("impact_areas", List.of(firstImpactArea.displayValue()));
5053
Map<String, Object> expectedImpact2 = new HashMap<>();
5154
expectedImpact2.put("severity", impact2Severity);
5255
expectedImpact2.put("description", impact2Description);
56+
expectedImpact2.put("impact_areas", List.of(secondImpactArea.displayValue()));
5357
expectedImpacts.add(expectedImpact1);
5458
expectedImpacts.add(expectedImpact2);
5559
assertEquals(expectedImpacts, xContentMap.get("impacts"));

server/src/test/java/org/elasticsearch/health/HealthIndicatorServiceTests.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@ public void testImpactsOrderAndLimit() {
2222
HealthStatus status = randomFrom(HealthStatus.RED, HealthStatus.YELLOW, HealthStatus.GREEN);
2323
Set<HealthIndicatorImpact> impacts = new HashSet<>();
2424
for (int i = 0; i < 10; i++) {
25-
impacts.add(new HealthIndicatorImpact(randomIntBetween(5, 20), randomAlphaOfLength(20)));
25+
impacts.add(
26+
new HealthIndicatorImpact(randomIntBetween(5, 20), randomAlphaOfLength(20), List.of(randomFrom(ImpactArea.values())))
27+
);
2628
}
27-
HealthIndicatorImpact impact1 = new HealthIndicatorImpact(1, randomAlphaOfLength(20));
28-
HealthIndicatorImpact impact2 = new HealthIndicatorImpact(2, randomAlphaOfLength(20));
29-
HealthIndicatorImpact impact3 = new HealthIndicatorImpact(3, randomAlphaOfLength(20));
29+
HealthIndicatorImpact impact1 = new HealthIndicatorImpact(1, randomAlphaOfLength(20), List.of(randomFrom(ImpactArea.values())));
30+
HealthIndicatorImpact impact2 = new HealthIndicatorImpact(2, randomAlphaOfLength(20), List.of(randomFrom(ImpactArea.values())));
31+
HealthIndicatorImpact impact3 = new HealthIndicatorImpact(3, randomAlphaOfLength(20), List.of(randomFrom(ImpactArea.values())));
3032
impacts.add(impact2);
3133
impacts.add(impact1);
3234
impacts.add(impact3);
3335
for (int i = 0; i < 10; i++) {
34-
impacts.add(new HealthIndicatorImpact(randomIntBetween(5, 20), randomAlphaOfLength(20)));
36+
impacts.add(
37+
new HealthIndicatorImpact(randomIntBetween(5, 20), randomAlphaOfLength(20), List.of(randomFrom(ImpactArea.values())))
38+
);
3539
}
3640
HealthIndicatorResult result = service.createIndicator(status, randomAlphaOfLength(20), HealthIndicatorDetails.EMPTY, impacts);
3741
List<HealthIndicatorImpact> outputImpacts = result.impacts();

0 commit comments

Comments
 (0)