- Notifications
You must be signed in to change notification settings - Fork 25.6k
[DSL] Introduce new endpoint to expose data stream lifecycle stats #101845
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits Select commit Hold shift + click to select a range
31a77cb
Track time related stats in DataStreamLifecycleService
gmarouli c0de8fd
Expose the data stream lifecycle stats
gmarouli 2aa2816
small fix
gmarouli 689ca11
Fix test
gmarouli b66d1aa
Add Rest test
gmarouli f8acf26
Merge branch 'main' into data-stream-lifecycle-stats
elasticmachine e7fb1d9
Add docs
gmarouli 8144ad3
Fix client in test
gmarouli 4fbf88d
Fix docs
gmarouli 2212a6e
Skip test
gmarouli aec40f1
Merge branch 'main' into data-stream-lifecycle-stats
elasticmachine 855219e
Add missing bracket
gmarouli 6e8df26
Update security privileges
gmarouli 7383c67
Update docs/changelog/101845.yaml
gmarouli 860e201
Polish
gmarouli fa2cf46
Merge branch 'main' into data-stream-lifecycle-stats
elasticmachine File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pr: 101845 | ||
summary: Introduce new endpoint to expose data stream lifecycle stats | ||
area: Data streams | ||
type: enhancement | ||
issues: [] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions 93 docs/reference/data-streams/lifecycle/apis/get-lifecycle-stats.asciidoc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
[[data-streams-get-lifecycle-stats]] | ||
=== Get data stream lifecycle stats | ||
++++ | ||
<titleabbrev>Get Data Stream Lifecycle</titleabbrev> | ||
++++ | ||
| ||
preview::[] | ||
| ||
Gets stats about the execution of data stream lifecycle. | ||
| ||
[[get-lifecycle-stats-api-prereqs]] | ||
==== {api-prereq-title} | ||
| ||
* If the {es} {security-features} are enabled, you must have the `monitor` or | ||
`manage` <<privileges-list-cluster,cluster privilege>> to use this API. | ||
| ||
[[data-streams-get-lifecycle-stats-request]] | ||
==== {api-request-title} | ||
| ||
`GET _lifecycle/stats` | ||
| ||
[[data-streams-get-lifecycle-stats-desc]] | ||
==== {api-description-title} | ||
| ||
Gets stats about the execution of the data stream lifecycle. The data stream level stats include only stats about data streams | ||
managed by the data stream lifecycle. | ||
| ||
[[get-lifecycle-stats-api-response-body]] | ||
==== {api-response-body-title} | ||
| ||
`last_run_duration_in_millis`:: | ||
(Optional, long) | ||
The duration of the last data stream lifecycle execution. | ||
`time_between_starts_in_millis`:: | ||
(Optional, long) | ||
The time passed between the start of the last two data stream lifecycle executions. This should amount approximately to | ||
<<data-streams-lifecycle-poll-interval,`data_streams.lifecycle.poll_interval`>>. | ||
`data_stream_count`:: | ||
(integer) | ||
The count of data streams currently being managed by the data stream lifecycle. | ||
`data_streams`:: | ||
(array of objects) | ||
Contains information about the retrieved data stream lifecycles. | ||
+ | ||
.Properties of objects in `data_streams` | ||
[%collapsible%open] | ||
==== | ||
`name`:: | ||
(string) | ||
The name of the data stream. | ||
`backing_indices_in_total`:: | ||
(integer) | ||
The count of the backing indices of this data stream that are managed by the data stream lifecycle. | ||
`backing_indices_in_error`:: | ||
(integer) | ||
The count of the backing indices of this data stream that are managed by the data stream lifecycle and have encountered an error. | ||
==== | ||
| ||
[[data-streams-get-lifecycle-stats-example]] | ||
==== {api-examples-title} | ||
| ||
Let's retrieve the data stream lifecycle stats of a cluster that has already executed the lifecycle more than once: | ||
| ||
[source,console] | ||
-------------------------------------------------- | ||
GET _lifecycle/stats?human&pretty | ||
-------------------------------------------------- | ||
// TEST[skip:this is for demonstration purposes only, we cannot ensure that DSL has run] | ||
| ||
The response will look like the following: | ||
| ||
[source,console-result] | ||
-------------------------------------------------- | ||
{ | ||
"last_run_duration_in_millis": 2, | ||
"last_run_duration": "2ms", | ||
"time_between_starts_in_millis": 9998, | ||
"time_between_starts": "9.99s", | ||
"data_streams_count": 2, | ||
"data_streams": [ | ||
{ | ||
"name": "my-data-stream", | ||
"backing_indices_in_total": 2, | ||
"backing_indices_in_error": 0 | ||
}, | ||
{ | ||
"name": "my-other-stream", | ||
"backing_indices_in_total": 2, | ||
"backing_indices_in_error": 1 | ||
} | ||
] | ||
} | ||
-------------------------------------------------- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
| @@ -622,35 +622,6 @@ public void testDataLifecycleServiceConfiguresTheMergePolicy() throws Exception | |
}); | ||
} | ||
| ||
private static List<String> getBackingIndices(String dataStreamName) { | ||
GetDataStreamAction.Request getDataStreamRequest = new GetDataStreamAction.Request(new String[] { dataStreamName }); | ||
GetDataStreamAction.Response getDataStreamResponse = client().execute(GetDataStreamAction.INSTANCE, getDataStreamRequest) | ||
.actionGet(); | ||
assertThat(getDataStreamResponse.getDataStreams().size(), equalTo(1)); | ||
assertThat(getDataStreamResponse.getDataStreams().get(0).getDataStream().getName(), equalTo(dataStreamName)); | ||
return getDataStreamResponse.getDataStreams().get(0).getDataStream().getIndices().stream().map(Index::getName).toList(); | ||
} | ||
| ||
static void indexDocs(String dataStream, int numDocs) { | ||
BulkRequest bulkRequest = new BulkRequest(); | ||
for (int i = 0; i < numDocs; i++) { | ||
String value = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.formatMillis(System.currentTimeMillis()); | ||
bulkRequest.add( | ||
new IndexRequest(dataStream).opType(DocWriteRequest.OpType.CREATE) | ||
.source(String.format(Locale.ROOT, "{\"%s\":\"%s\"}", DEFAULT_TIMESTAMP_FIELD, value), XContentType.JSON) | ||
); | ||
} | ||
BulkResponse bulkResponse = client().bulk(bulkRequest).actionGet(); | ||
assertThat(bulkResponse.getItems().length, equalTo(numDocs)); | ||
String backingIndexPrefix = DataStream.BACKING_INDEX_PREFIX + dataStream; | ||
for (BulkItemResponse itemResponse : bulkResponse) { | ||
assertThat(itemResponse.getFailureMessage(), nullValue()); | ||
assertThat(itemResponse.status(), equalTo(RestStatus.CREATED)); | ||
assertThat(itemResponse.getIndex(), startsWith(backingIndexPrefix)); | ||
} | ||
indicesAdmin().refresh(new RefreshRequest(dataStream)).actionGet(); | ||
} | ||
| ||
public void testReenableDataStreamLifecycle() throws Exception { | ||
// start with a lifecycle that's not enabled | ||
DataStreamLifecycle lifecycle = new DataStreamLifecycle(null, null, false); | ||
| @@ -700,6 +671,35 @@ public void testReenableDataStreamLifecycle() throws Exception { | |
}); | ||
} | ||
| ||
private static List<String> getBackingIndices(String dataStreamName) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just moved this helper function in the bottom to be after all the test cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for this note, this is really helpful when reviewing ❤️ | ||
GetDataStreamAction.Request getDataStreamRequest = new GetDataStreamAction.Request(new String[] { dataStreamName }); | ||
GetDataStreamAction.Response getDataStreamResponse = client().execute(GetDataStreamAction.INSTANCE, getDataStreamRequest) | ||
.actionGet(); | ||
assertThat(getDataStreamResponse.getDataStreams().size(), equalTo(1)); | ||
assertThat(getDataStreamResponse.getDataStreams().get(0).getDataStream().getName(), equalTo(dataStreamName)); | ||
return getDataStreamResponse.getDataStreams().get(0).getDataStream().getIndices().stream().map(Index::getName).toList(); | ||
} | ||
| ||
static void indexDocs(String dataStream, int numDocs) { | ||
BulkRequest bulkRequest = new BulkRequest(); | ||
for (int i = 0; i < numDocs; i++) { | ||
String value = DateFieldMapper.DEFAULT_DATE_TIME_FORMATTER.formatMillis(System.currentTimeMillis()); | ||
bulkRequest.add( | ||
new IndexRequest(dataStream).opType(DocWriteRequest.OpType.CREATE) | ||
.source(String.format(Locale.ROOT, "{\"%s\":\"%s\"}", DEFAULT_TIMESTAMP_FIELD, value), XContentType.JSON) | ||
); | ||
} | ||
BulkResponse bulkResponse = client().bulk(bulkRequest).actionGet(); | ||
assertThat(bulkResponse.getItems().length, equalTo(numDocs)); | ||
String backingIndexPrefix = DataStream.BACKING_INDEX_PREFIX + dataStream; | ||
for (BulkItemResponse itemResponse : bulkResponse) { | ||
assertThat(itemResponse.getFailureMessage(), nullValue()); | ||
assertThat(itemResponse.status(), equalTo(RestStatus.CREATED)); | ||
assertThat(itemResponse.getIndex(), startsWith(backingIndexPrefix)); | ||
} | ||
indicesAdmin().refresh(new RefreshRequest(dataStream)).actionGet(); | ||
} | ||
| ||
static void putComposableIndexTemplate( | ||
String id, | ||
@Nullable String mappings, | ||
|
86 changes: 86 additions & 0 deletions 86 ...javaRestTest/java/org/elasticsearch/datastreams/lifecycle/DataStreamLifecycleStatsIT.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
package org.elasticsearch.datastreams.lifecycle; | ||
| ||
import org.elasticsearch.client.Request; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.datastreams.DisabledSecurityDataStreamTestCase; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
| ||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Map; | ||
| ||
import static org.hamcrest.Matchers.greaterThanOrEqualTo; | ||
import static org.hamcrest.Matchers.is; | ||
| ||
public class DataStreamLifecycleStatsIT extends DisabledSecurityDataStreamTestCase { | ||
| ||
@Before | ||
public void updateClusterSettings() throws IOException { | ||
updateClusterSettings( | ||
Settings.builder() | ||
.put("data_streams.lifecycle.poll_interval", "1s") | ||
.put("cluster.lifecycle.default.rollover", "min_docs=1,max_docs=1") | ||
.build() | ||
); | ||
} | ||
| ||
@After | ||
public void cleanUp() throws IOException { | ||
adminClient().performRequest(new Request("DELETE", "_data_stream/*?expand_wildcards=hidden")); | ||
} | ||
| ||
@SuppressWarnings("unchecked") | ||
public void testStats() throws Exception { | ||
// Check empty stats and wait until we have 2 executions | ||
assertBusy(() -> { | ||
Request request = new Request("GET", "/_lifecycle/stats"); | ||
Map<String, Object> response = entityAsMap(client().performRequest(request)); | ||
assertThat(response.get("data_stream_count"), is(0)); | ||
assertThat(response.get("data_streams"), is(List.of())); | ||
assertThat(response.containsKey("last_run_duration_in_millis"), is(true)); | ||
assertThat(response.containsKey("time_between_starts_in_millis"), is(true)); | ||
}); | ||
| ||
// Create a template | ||
Request putComposableIndexTemplateRequest = new Request("POST", "/_index_template/1"); | ||
putComposableIndexTemplateRequest.setJsonEntity(""" | ||
{ | ||
"index_patterns": ["my-data-stream-*"], | ||
"data_stream": {}, | ||
"template": { | ||
"lifecycle": {} | ||
} | ||
} | ||
"""); | ||
assertOK(client().performRequest(putComposableIndexTemplateRequest)); | ||
| ||
// Create two data streams with one doc each | ||
Request createDocRequest = new Request("POST", "/my-data-stream-1/_doc?refresh=true"); | ||
createDocRequest.setJsonEntity("{ \"@timestamp\": \"2022-12-12\"}"); | ||
assertOK(client().performRequest(createDocRequest)); | ||
createDocRequest = new Request("POST", "/my-data-stream-2/_doc?refresh=true"); | ||
createDocRequest.setJsonEntity("{ \"@timestamp\": \"2022-12-12\"}"); | ||
assertOK(client().performRequest(createDocRequest)); | ||
| ||
Request request = new Request("GET", "/_lifecycle/stats"); | ||
Map<String, Object> response = entityAsMap(client().performRequest(request)); | ||
assertThat(response.get("data_stream_count"), is(2)); | ||
List<Map<String, Object>> dataStreams = (List<Map<String, Object>>) response.get("data_streams"); | ||
assertThat(dataStreams.get(0).get("name"), is("my-data-stream-1")); | ||
assertThat((Integer) dataStreams.get(0).get("backing_indices_in_total"), greaterThanOrEqualTo(1)); | ||
assertThat((Integer) dataStreams.get(0).get("backing_indices_in_error"), is(0)); | ||
assertThat(dataStreams.get(1).get("name"), is("my-data-stream-2")); | ||
assertThat((Integer) dataStreams.get(1).get("backing_indices_in_total"), greaterThanOrEqualTo(1)); | ||
assertThat((Integer) dataStreams.get(0).get("backing_indices_in_error"), is(0)); | ||
assertThat(response.containsKey("last_run_duration_in_millis"), is(true)); | ||
assertThat(response.containsKey("time_between_starts_in_millis"), is(true)); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice ! ❤️