瀏覽代碼

Add age_in_millis to ILM Explain Response (#128866)

* Add age_in_millis to ILM Explain Response

* Fix: Declare age_in_millis in ILM Explain Response Parser

* Add unit tests for age_in_millis field in IndexLifecycleExplainResponse

* Update docs/changelog/128866.yaml

* Update docs/changelog/128866.yaml

* Update IndexLifecycleExplainResponse.java

Fix comments; follow DRY for getAge(nowSupplier) call in IndexLifecycleExplainResponse

---------

Co-authored-by: Joe Gallo <joe.gallo@elastic.co>
Graeme Mjehovich 3 月之前
父節點
當前提交
416405877f

+ 6 - 0
docs/changelog/128866.yaml

@@ -0,0 +1,6 @@
+pr: 128866
+summary: Add `age_in_millis` to ILM Explain Response
+area: ILM+SLM
+type: enhancement
+issues:
+ - 103659

+ 7 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleExplainResponse.java

@@ -51,6 +51,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
     private static final ParseField PREVIOUS_STEP_INFO_FIELD = new ParseField("previous_step_info");
     private static final ParseField PHASE_EXECUTION_INFO = new ParseField("phase_execution");
     private static final ParseField AGE_FIELD = new ParseField("age");
+    private static final ParseField AGE_IN_MILLIS_FIELD = new ParseField("age_in_millis");
     private static final ParseField TIME_SINCE_INDEX_CREATION_FIELD = new ParseField("time_since_index_creation");
     private static final ParseField REPOSITORY_NAME = new ParseField("repository_name");
     private static final ParseField SHRINK_INDEX_NAME = new ParseField("shrink_index_name");
@@ -83,6 +84,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
             Objects.requireNonNullElse((Boolean) a[22], false)
             // a[13] == "age"
             // a[20] == "time_since_index_creation"
+            // a[23] = "age_in_millis"
         )
     );
     static {
@@ -121,6 +123,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
             return BytesReference.bytes(builder);
         }, PREVIOUS_STEP_INFO_FIELD);
         PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), SKIP_NAME);
+        PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), AGE_IN_MILLIS_FIELD);
     }
 
     private final String index;
@@ -529,7 +532,10 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
                     LIFECYCLE_DATE_FIELD.getPreferredName(),
                     lifecycleDate
                 );
-                builder.field(AGE_FIELD.getPreferredName(), getAge(nowSupplier).toHumanReadableString(2));
+
+                final TimeValue ageNow = getAge(nowSupplier);
+                builder.field(AGE_FIELD.getPreferredName(), ageNow.toHumanReadableString(2));
+                builder.field(AGE_IN_MILLIS_FIELD.getPreferredName(), ageNow.getMillis());
             }
             if (phase != null) {
                 builder.field(PHASE_FIELD.getPreferredName(), phase);

+ 47 - 1
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/IndexLifecycleExplainResponseTests.java

@@ -20,16 +20,20 @@ import org.elasticsearch.xcontent.NamedXContentRegistry;
 import org.elasticsearch.xcontent.ParseField;
 import org.elasticsearch.xcontent.ToXContentObject;
 import org.elasticsearch.xcontent.XContentBuilder;
+import org.elasticsearch.xcontent.XContentFactory;
 import org.elasticsearch.xcontent.XContentParser;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.function.Supplier;
 
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.Matchers.startsWith;
@@ -110,7 +114,7 @@ public class IndexLifecycleExplainResponseTests extends AbstractXContentSerializ
         assertThat(exception.getMessage(), containsString("=null"));
     }
 
-    public void testIndexAges() {
+    public void testIndexAges() throws IOException {
         IndexLifecycleExplainResponse unmanagedExplainResponse = randomUnmanagedIndexExplainResponse();
         assertThat(unmanagedExplainResponse.getLifecycleDate(), is(nullValue()));
         assertThat(unmanagedExplainResponse.getAge(System::currentTimeMillis), is(TimeValue.MINUS_ONE));
@@ -118,6 +122,8 @@ public class IndexLifecycleExplainResponseTests extends AbstractXContentSerializ
         assertThat(unmanagedExplainResponse.getIndexCreationDate(), is(nullValue()));
         assertThat(unmanagedExplainResponse.getTimeSinceIndexCreation(System::currentTimeMillis), is(nullValue()));
 
+        assertAgeInMillisXContentAbsentForUnmanagedResponse(unmanagedExplainResponse);
+
         IndexLifecycleExplainResponse managedExplainResponse = IndexLifecycleExplainResponse.newManagedIndexResponse(
             "indexName",
             12345L,
@@ -155,6 +161,46 @@ public class IndexLifecycleExplainResponseTests extends AbstractXContentSerializ
             is(equalTo(TimeValue.timeValueMillis(now - managedExplainResponse.getIndexCreationDate())))
         );
         assertThat(managedExplainResponse.getTimeSinceIndexCreation(() -> 0L), is(equalTo(TimeValue.ZERO)));
+
+        long expectedAgeInMillisForThisCase = Math.max(0L, now - managedExplainResponse.getLifecycleDate());
+        assertAgeInMillisXContent(managedExplainResponse, expectedAgeInMillisForThisCase, now);
+    }
+
+    protected void assertAgeInMillisXContent(
+        final IndexLifecycleExplainResponse managedExplainResponse,
+        final long expectedAgeInMillis,
+        final long now
+    ) throws IOException {
+        XContentBuilder builder = XContentFactory.jsonBuilder();
+        managedExplainResponse.nowSupplier = () -> now;
+        try (builder) {
+            managedExplainResponse.toXContent(builder, ToXContentObject.EMPTY_PARAMS);
+        }
+        final String json = Strings.toString(builder);
+
+        try (XContentParser parser = createParser(builder.contentType().xContent(), json)) {
+            Map<String, Object> parsedMap = parser.map();
+
+            assertThat(parsedMap, hasKey("age_in_millis"));
+            final long actualParsedAgeInMillis = ((Number) parsedMap.get("age_in_millis")).longValue();
+            assertThat(actualParsedAgeInMillis, equalTo((Number) expectedAgeInMillis));
+        }
+    }
+
+    protected void assertAgeInMillisXContentAbsentForUnmanagedResponse(final IndexLifecycleExplainResponse unmanagedExplainResponse)
+        throws IOException {
+        XContentBuilder builder = XContentFactory.jsonBuilder();
+        try (builder) {
+            unmanagedExplainResponse.toXContent(builder, ToXContentObject.EMPTY_PARAMS);
+        }
+        final String json = Strings.toString(builder);
+
+        try (XContentParser parser = createParser(builder.contentType().xContent(), json)) {
+            Map<String, Object> parsedMap = parser.map();
+
+            assertThat(parsedMap, not(hasKey("age_in_millis")));
+        }
+
     }
 
     @Override

+ 2 - 0
x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/ExplainLifecycleIT.java

@@ -207,6 +207,7 @@ public class ExplainLifecycleIT extends ESRestTestCase {
             assertThat(explainIndexWithMissingPolicy.get("action"), is(nullValue()));
             assertThat(explainIndexWithMissingPolicy.get("step"), is(ErrorStep.NAME));
             assertThat(explainIndexWithMissingPolicy.get("age"), is(nullValue()));
+            assertThat(explainIndexWithMissingPolicy.get("age_in_millis"), is(nullValue()));
             assertThat(explainIndexWithMissingPolicy.get("failed_step"), is(nullValue()));
             Map<String, Object> stepInfo = (Map<String, Object>) explainIndexWithMissingPolicy.get("step_info");
             assertThat(stepInfo, is(notNullValue()));
@@ -343,6 +344,7 @@ public class ExplainLifecycleIT extends ESRestTestCase {
         assertThat(explainIndexMap.get("step"), is("complete"));
         assertThat(explainIndexMap.get("phase_time_millis"), is(notNullValue()));
         assertThat(explainIndexMap.get("age"), is(notNullValue()));
+        assertThat(explainIndexMap.get("age_in_millis"), is(notNullValue()));
         assertThat(explainIndexMap.get("phase_execution"), is(notNullValue()));
         assertThat(explainIndexMap.get("failed_step"), is(nullValue()));
         assertThat(explainIndexMap.get("step_info"), is(nullValue()));