Skip to content

Commit 04798e2

Browse files
committed
Adds usage data for ILM (#33377)
* Adds usage data for ILM * Adds tests for IndexLifecycleFeatureSetUsage and friends * Adds tests for IndexLifecycleFeatureSet * Fixes merge errors * Add number of indices managed to usage stats Also adds more tests * Addresses Review comments
1 parent fa491b3 commit 04798e2

File tree

9 files changed

+715
-2
lines changed

9 files changed

+715
-2
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleFeatureSetUsage.java

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,201 @@
55
*/
66
package org.elasticsearch.xpack.core.indexlifecycle;
77

8+
import org.elasticsearch.common.ParseField;
9+
import org.elasticsearch.common.Strings;
810
import org.elasticsearch.common.io.stream.StreamInput;
11+
import org.elasticsearch.common.io.stream.StreamOutput;
12+
import org.elasticsearch.common.io.stream.Writeable;
13+
import org.elasticsearch.common.unit.TimeValue;
14+
import org.elasticsearch.common.xcontent.ToXContentObject;
15+
import org.elasticsearch.common.xcontent.XContentBuilder;
916
import org.elasticsearch.xpack.core.XPackFeatureSet;
1017
import org.elasticsearch.xpack.core.XPackField;
1118

1219
import java.io.IOException;
20+
import java.util.Arrays;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.Objects;
1324

1425
public class IndexLifecycleFeatureSetUsage extends XPackFeatureSet.Usage {
1526

27+
private List<PolicyStats> policyStats;
28+
1629
public IndexLifecycleFeatureSetUsage(StreamInput input) throws IOException {
1730
super(input);
31+
if (input.readBoolean()) {
32+
policyStats = input.readList(PolicyStats::new);
33+
}
34+
}
35+
36+
@Override
37+
public void writeTo(StreamOutput out) throws IOException {
38+
super.writeTo(out);
39+
boolean hasPolicyStats = policyStats != null;
40+
out.writeBoolean(hasPolicyStats);
41+
if (hasPolicyStats) {
42+
out.writeList(policyStats);
43+
}
1844
}
1945

2046
public IndexLifecycleFeatureSetUsage(boolean available, boolean enabled) {
47+
this(available, enabled, null);
48+
}
49+
50+
public IndexLifecycleFeatureSetUsage(boolean available, boolean enabled, List<PolicyStats> policyStats) {
2151
super(XPackField.INDEX_LIFECYCLE, available, enabled);
52+
this.policyStats = policyStats;
53+
}
54+
55+
@Override
56+
protected void innerXContent(XContentBuilder builder, Params params) throws IOException {
57+
if (policyStats != null) {
58+
builder.field("policy_count", policyStats.size());
59+
builder.field("policy_stats", policyStats);
60+
}
61+
}
62+
63+
public List<PolicyStats> getPolicyStats() {
64+
return policyStats;
65+
}
66+
67+
@Override
68+
public int hashCode() {
69+
return Objects.hash(available, enabled, policyStats);
70+
}
71+
72+
@Override
73+
public boolean equals(Object obj) {
74+
if (obj == null) {
75+
return false;
76+
}
77+
if (getClass() != obj.getClass()) {
78+
return false;
79+
}
80+
IndexLifecycleFeatureSetUsage other = (IndexLifecycleFeatureSetUsage) obj;
81+
return Objects.equals(available, other.available) &&
82+
Objects.equals(enabled, other.enabled) &&
83+
Objects.equals(policyStats, other.policyStats);
84+
}
85+
86+
public static final class PolicyStats implements ToXContentObject, Writeable {
87+
88+
public static final ParseField INDICES_MANAGED_FIELD = new ParseField("indices_managed");
89+
90+
private final Map<String, PhaseStats> phaseStats;
91+
private final int indicesManaged;
92+
93+
public PolicyStats(Map<String, PhaseStats> phaseStats, int numberIndicesManaged) {
94+
this.phaseStats = phaseStats;
95+
this.indicesManaged = numberIndicesManaged;
96+
}
97+
98+
public PolicyStats(StreamInput in) throws IOException {
99+
this.phaseStats = in.readMap(StreamInput::readString, PhaseStats::new);
100+
this.indicesManaged = in.readVInt();
101+
}
102+
103+
@Override
104+
public void writeTo(StreamOutput out) throws IOException {
105+
out.writeMap(phaseStats, StreamOutput::writeString, (o, p) -> p.writeTo(o));
106+
out.writeVInt(indicesManaged);
107+
}
108+
109+
@Override
110+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
111+
builder.startObject();
112+
builder.field(LifecyclePolicy.PHASES_FIELD.getPreferredName(), phaseStats);
113+
builder.field(INDICES_MANAGED_FIELD.getPreferredName(), indicesManaged);
114+
builder.endObject();
115+
return builder;
116+
}
117+
118+
public Map<String, PhaseStats> getPhaseStats() {
119+
return phaseStats;
120+
}
121+
122+
public int getIndicesManaged() {
123+
return indicesManaged;
124+
}
125+
126+
@Override
127+
public int hashCode() {
128+
return Objects.hash(phaseStats, indicesManaged);
129+
}
130+
131+
@Override
132+
public boolean equals(Object obj) {
133+
if (obj == null) {
134+
return false;
135+
}
136+
if (getClass() != obj.getClass()) {
137+
return false;
138+
}
139+
PolicyStats other = (PolicyStats) obj;
140+
return Objects.equals(phaseStats, other.phaseStats) &&
141+
Objects.equals(indicesManaged, other.indicesManaged);
142+
}
143+
144+
@Override
145+
public String toString() {
146+
return Strings.toString(this);
147+
}
148+
}
149+
150+
public static final class PhaseStats implements ToXContentObject, Writeable {
151+
private final String[] actionNames;
152+
private final TimeValue minimumAge;
153+
154+
public PhaseStats(TimeValue after, String[] actionNames) {
155+
this.actionNames = actionNames;
156+
this.minimumAge = after;
157+
}
158+
159+
public PhaseStats(StreamInput in) throws IOException {
160+
actionNames = in.readStringArray();
161+
minimumAge = in.readTimeValue();
162+
}
163+
164+
@Override
165+
public void writeTo(StreamOutput out) throws IOException {
166+
out.writeStringArray(actionNames);
167+
out.writeTimeValue(minimumAge);
168+
}
169+
170+
@Override
171+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
172+
builder.startObject();
173+
builder.field(Phase.MINIMUM_AGE.getPreferredName(), minimumAge.getMillis());
174+
builder.field(Phase.ACTIONS_FIELD.getPreferredName(), actionNames);
175+
builder.endObject();
176+
return builder;
177+
}
178+
179+
public String[] getActionNames() {
180+
return actionNames;
181+
}
182+
183+
public TimeValue getAfter() {
184+
return minimumAge;
185+
}
186+
187+
@Override
188+
public int hashCode() {
189+
return Objects.hash(Arrays.hashCode(actionNames), minimumAge);
190+
}
191+
192+
@Override
193+
public boolean equals(Object obj) {
194+
if (obj == null) {
195+
return false;
196+
}
197+
if (getClass() != obj.getClass()) {
198+
return false;
199+
}
200+
PhaseStats other = (PhaseStats) obj;
201+
return Objects.equals(minimumAge, other.minimumAge) &&
202+
Objects.deepEquals(actionNames, other.actionNames);
203+
}
22204
}
23205
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.indexlifecycle;
8+
9+
import org.elasticsearch.common.io.stream.Writeable.Reader;
10+
import org.elasticsearch.test.AbstractWireSerializingTestCase;
11+
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
12+
13+
import java.io.IOException;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
public class IndexLifecycleFeatureSetUsageTests extends AbstractWireSerializingTestCase<IndexLifecycleFeatureSetUsage> {
18+
19+
@Override
20+
protected IndexLifecycleFeatureSetUsage createTestInstance() {
21+
boolean enabled = randomBoolean();
22+
boolean available = randomBoolean();
23+
List<PolicyStats> policyStats = null;
24+
if (enabled) {
25+
int size = randomIntBetween(0, 10);
26+
policyStats = new ArrayList<>(size);
27+
for (int i = 0; i < size; i++) {
28+
policyStats.add(PolicyStatsTests.createRandomInstance());
29+
}
30+
}
31+
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
32+
}
33+
34+
@Override
35+
protected IndexLifecycleFeatureSetUsage mutateInstance(IndexLifecycleFeatureSetUsage instance) throws IOException {
36+
boolean available = instance.available();
37+
boolean enabled = instance.enabled();
38+
List<PolicyStats> policyStats = instance.getPolicyStats();
39+
switch (between(0, 2)) {
40+
case 0:
41+
available = available == false;
42+
break;
43+
case 1:
44+
enabled = enabled == false;
45+
break;
46+
case 2:
47+
if (policyStats == null) {
48+
policyStats = new ArrayList<>();
49+
policyStats.add(PolicyStatsTests.createRandomInstance());
50+
} else if (randomBoolean()) {
51+
policyStats = null;
52+
} else {
53+
policyStats = new ArrayList<>(policyStats);
54+
policyStats.add(PolicyStatsTests.createRandomInstance());
55+
}
56+
break;
57+
default:
58+
throw new AssertionError("Illegal randomisation branch");
59+
}
60+
return new IndexLifecycleFeatureSetUsage(available, enabled, policyStats);
61+
}
62+
63+
@Override
64+
protected Reader<IndexLifecycleFeatureSetUsage> instanceReader() {
65+
return IndexLifecycleFeatureSetUsage::new;
66+
}
67+
68+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.indexlifecycle;
8+
9+
import org.elasticsearch.common.io.stream.Writeable.Reader;
10+
import org.elasticsearch.common.unit.TimeValue;
11+
import org.elasticsearch.test.AbstractWireSerializingTestCase;
12+
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
13+
14+
import java.io.IOException;
15+
import java.util.Arrays;
16+
17+
public class PhaseStatsTests extends AbstractWireSerializingTestCase<PhaseStats> {
18+
19+
@Override
20+
protected PhaseStats createTestInstance() {
21+
return createRandomInstance();
22+
}
23+
24+
public static PhaseStats createRandomInstance() {
25+
TimeValue after = TimeValue.parseTimeValue(randomTimeValue(), "phase_stats_tests");
26+
String[] actionNames = randomArray(0, 20, size -> new String[size], () -> randomAlphaOfLengthBetween(1, 20));
27+
return new PhaseStats(after, actionNames);
28+
}
29+
30+
@Override
31+
protected PhaseStats mutateInstance(PhaseStats instance) throws IOException {
32+
TimeValue after = instance.getAfter();
33+
String[] actionNames = instance.getActionNames();
34+
switch (between(0, 1)) {
35+
case 0:
36+
after = randomValueOtherThan(after, () -> TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test"));
37+
break;
38+
case 1:
39+
actionNames = randomValueOtherThanMany(a -> Arrays.equals(a, instance.getActionNames()),
40+
() -> randomArray(0, 20, size -> new String[size], () -> randomAlphaOfLengthBetween(1, 20)));
41+
break;
42+
default:
43+
throw new AssertionError("Illegal randomisation branch");
44+
}
45+
return new PhaseStats(after, actionNames);
46+
}
47+
48+
@Override
49+
protected Reader<PhaseStats> instanceReader() {
50+
return PhaseStats::new;
51+
}
52+
53+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
package org.elasticsearch.xpack.core.indexlifecycle;
8+
9+
import org.elasticsearch.common.io.stream.Writeable.Reader;
10+
import org.elasticsearch.test.AbstractWireSerializingTestCase;
11+
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PhaseStats;
12+
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleFeatureSetUsage.PolicyStats;
13+
14+
import java.io.IOException;
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
public class PolicyStatsTests extends AbstractWireSerializingTestCase<PolicyStats> {
19+
20+
@Override
21+
protected PolicyStats createTestInstance() {
22+
return createRandomInstance();
23+
}
24+
25+
public static PolicyStats createRandomInstance() {
26+
int size = randomIntBetween(0, 10);
27+
Map<String, PhaseStats> phaseStats = new HashMap<>(size);
28+
for (int i = 0; i < size; i++) {
29+
phaseStats.put(randomAlphaOfLengthBetween(1, 20), PhaseStatsTests.createRandomInstance());
30+
}
31+
return new PolicyStats(phaseStats, randomIntBetween(0, 100));
32+
}
33+
34+
@Override
35+
protected PolicyStats mutateInstance(PolicyStats instance) throws IOException {
36+
Map<String, PhaseStats> phaseStats = instance.getPhaseStats();
37+
int indicesManaged = instance.getIndicesManaged();
38+
switch (between(0, 1)) {
39+
case 0:
40+
phaseStats = new HashMap<>(instance.getPhaseStats());
41+
phaseStats.put(randomAlphaOfLengthBetween(1, 20), PhaseStatsTests.createRandomInstance());
42+
break;
43+
case 1:
44+
indicesManaged = randomIntBetween(1, 50);
45+
break;
46+
default:
47+
throw new AssertionError("Illegal randomisation branch");
48+
}
49+
return new PolicyStats(phaseStats, indicesManaged);
50+
}
51+
52+
@Override
53+
protected Reader<PolicyStats> instanceReader() {
54+
return PolicyStats::new;
55+
}
56+
57+
}

0 commit comments

Comments
 (0)