Skip to content

Commit 44d5d43

Browse files
committed
Add datastream lifecycle support to indices metadata (elastic#245548)
## Summary Add [Datastream life cycle](https://www.elastic.co/docs/manage-data/lifecycle/data-stream) support to the indices metadata plugin. For data streams using DSL, the plugin now also queries the `data_retention` and includes it in the EBT document. Example document returned by `GET _data_stream/<ds name>/?filter_path=data_streams.name,data_streams.indices,data_streams.lifecycle.enabled,data_streams.lifecycle.data_retention` ```json { "data_streams": [ { "name": "dsl-test", "indices": [ { "index_name": ".ds-dsl-test-2025.12.08-000001", "index_uuid": "h9nu5fEIQJ-ObVemiXTPqg", "managed_by": "Data stream lifecycle", "prefer_ilm": true, "index_mode": "standard" }, { "index_name": ".ds-dsl-test-2025.12.08-000002", "index_uuid": "VKp5OURcTIquxTmatmNz3g", "managed_by": "Data stream lifecycle", "prefer_ilm": true, "index_mode": "standard" } ], "lifecycle": { "enabled": true, "data_retention": "1h" } } ] } ``` ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [ ] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels. (cherry picked from commit f6550e8)
1 parent 7ef375f commit 44d5d43

File tree

6 files changed

+483
-2
lines changed

6 files changed

+483
-2
lines changed

x-pack/platform/plugins/private/indices_metadata/server/lib/ebt/events.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ export const DATA_STREAM_EVENT: EventTypeOpts<DataStreams> = {
3131
type: 'keyword',
3232
_meta: { optional: true, description: 'ILM policy associated to the datastream' },
3333
},
34+
dsl: {
35+
properties: {
36+
enabled: {
37+
type: 'boolean',
38+
_meta: { description: 'Whether the data stream is enabled' },
39+
},
40+
data_retention: {
41+
type: 'text',
42+
_meta: { optional: true, description: 'Data retention period' },
43+
},
44+
},
45+
_meta: { optional: true, description: 'Data stream lifecycle settings' },
46+
},
3447
template: {
3548
type: 'keyword',
3649
_meta: { optional: true, description: 'Template associated to the datastream' },

x-pack/platform/plugins/private/indices_metadata/server/lib/services/indices_metadata.test.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ describe('Indices Metadata - IndicesMetadataService', () => {
7171
const mockDataStreams: DataStream[] = [
7272
{
7373
datastream_name: 'test-datastream',
74+
dsl: {
75+
enabled: true,
76+
data_retention: '30d',
77+
},
7478
indices: [{ index_name: 'test-index-1', ilm_policy: 'policy1' }],
7579
},
7680
];
@@ -365,6 +369,60 @@ describe('Indices Metadata - IndicesMetadataService', () => {
365369
expect(receiver.getIlmsStats).toHaveBeenCalledWith(['test-index-1']);
366370
});
367371

372+
it('should publish datastreams with DSL through full metadata flow', async () => {
373+
const datastreamsWithDsl: DataStream[] = [
374+
{
375+
datastream_name: 'logs-test',
376+
dsl: {
377+
enabled: true,
378+
data_retention: '90d',
379+
},
380+
indices: [
381+
{
382+
index_name: '.ds-logs-test-000001',
383+
ilm_policy: 'logs-policy',
384+
},
385+
],
386+
},
387+
];
388+
389+
receiver.getIndices.mockResolvedValue(mockIndexSettings);
390+
receiver.getDataStreams.mockResolvedValue(datastreamsWithDsl);
391+
receiver.getIndexTemplatesStats.mockResolvedValue(mockIndexTemplates);
392+
receiver.getIndicesStats.mockImplementation(async function* () {
393+
yield* mockIndexStats;
394+
});
395+
receiver.isIlmStatsAvailable.mockResolvedValue(true);
396+
receiver.getIlmsStats.mockImplementation(async function* () {
397+
yield {
398+
index_name: '.ds-logs-test-000001',
399+
phase: 'hot',
400+
age: '1d',
401+
policy_name: 'logs-policy',
402+
};
403+
});
404+
receiver.getIlmsPolicies.mockImplementation(async function* () {
405+
yield { policy_name: 'logs-policy', modified_date: '2023-01-01', phases: {} };
406+
});
407+
408+
await service['publishIndicesMetadata'](); // eslint-disable-line dot-notation
409+
410+
expect(sender.reportEBT).toHaveBeenCalledWith(
411+
expect.objectContaining({ eventType: DATA_STREAM_EVENT.eventType }),
412+
{
413+
items: expect.arrayContaining([
414+
expect.objectContaining({
415+
datastream_name: 'logs-test',
416+
dsl: {
417+
enabled: true,
418+
data_retention: '90d',
419+
},
420+
}),
421+
]),
422+
}
423+
);
424+
});
425+
368426
it('should throw error when not initialized', async () => {
369427
const uninitializedService = new IndicesMetadataService(logger, configurationService);
370428

@@ -438,6 +496,116 @@ describe('Indices Metadata - IndicesMetadataService', () => {
438496
expect(result).toBe(1);
439497
expect(logger.debug).toHaveBeenCalledWith('Data streams events sent', { count: 1 });
440498
});
499+
500+
it('should publish datastreams with DSL enabled and retention', () => {
501+
const datastreamsWithDsl: DataStream[] = [
502+
{
503+
datastream_name: 'logs-app-prod',
504+
dsl: {
505+
enabled: true,
506+
data_retention: '7d',
507+
},
508+
indices: [{ index_name: '.ds-logs-app-prod-000001' }],
509+
},
510+
{
511+
datastream_name: 'metrics-system',
512+
dsl: {
513+
enabled: false,
514+
data_retention: undefined,
515+
},
516+
indices: [{ index_name: '.ds-metrics-system-000001' }],
517+
},
518+
];
519+
520+
const result = service['publishDatastreamsStats'](datastreamsWithDsl); // eslint-disable-line dot-notation
521+
522+
expect(sender.reportEBT).toHaveBeenCalledWith(
523+
expect.objectContaining({ eventType: DATA_STREAM_EVENT.eventType }),
524+
{
525+
items: [
526+
expect.objectContaining({
527+
datastream_name: 'logs-app-prod',
528+
dsl: {
529+
enabled: true,
530+
data_retention: '7d',
531+
},
532+
}),
533+
expect.objectContaining({
534+
datastream_name: 'metrics-system',
535+
dsl: {
536+
enabled: false,
537+
data_retention: undefined,
538+
},
539+
}),
540+
],
541+
}
542+
);
543+
expect(result).toBe(2);
544+
});
545+
546+
it('should handle datastreams without DSL field', () => {
547+
const datastreamsWithoutDsl: DataStream[] = [
548+
{
549+
datastream_name: 'legacy-datastream',
550+
indices: [{ index_name: '.ds-legacy-000001' }],
551+
},
552+
];
553+
554+
const result = service['publishDatastreamsStats'](datastreamsWithoutDsl); // eslint-disable-line dot-notation
555+
556+
expect(sender.reportEBT).toHaveBeenCalledWith(
557+
expect.objectContaining({ eventType: DATA_STREAM_EVENT.eventType }),
558+
{
559+
items: [
560+
{
561+
datastream_name: 'legacy-datastream',
562+
indices: [{ index_name: '.ds-legacy-000001' }],
563+
},
564+
],
565+
}
566+
);
567+
expect(result).toBe(1);
568+
});
569+
570+
it('should publish mixed DSL configurations', () => {
571+
const mixedDatastreams: DataStream[] = [
572+
{
573+
datastream_name: 'with-retention',
574+
dsl: { enabled: true, data_retention: '365d' },
575+
indices: [],
576+
},
577+
{
578+
datastream_name: 'enabled-no-retention',
579+
dsl: { enabled: true, data_retention: undefined },
580+
indices: [],
581+
},
582+
{
583+
datastream_name: 'disabled',
584+
dsl: { enabled: false, data_retention: undefined },
585+
indices: [],
586+
},
587+
];
588+
589+
const result = service['publishDatastreamsStats'](mixedDatastreams); // eslint-disable-line dot-notation
590+
591+
expect(sender.reportEBT).toHaveBeenCalledWith(
592+
expect.objectContaining({ eventType: DATA_STREAM_EVENT.eventType }),
593+
{
594+
items: expect.arrayContaining([
595+
expect.objectContaining({
596+
dsl: { enabled: true, data_retention: '365d' },
597+
}),
598+
expect.objectContaining({
599+
dsl: { enabled: true, data_retention: undefined },
600+
}),
601+
expect.objectContaining({
602+
dsl: { enabled: false, data_retention: undefined },
603+
}),
604+
]),
605+
}
606+
);
607+
expect(result).toBe(3);
608+
});
441609
});
442610

443611
describe('publishIndicesSettings', () => {

x-pack/platform/plugins/private/indices_metadata/server/lib/services/indices_metadata.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ export class IndicesMetadataService {
257257
this.logger.debug('Indices settings sent', { count: indicesSettings.items.length } as LogMeta);
258258
return indicesSettings.items.length;
259259
}
260+
260261
private async publishIlmStats(indices: string[]): Promise<Set<string>> {
261262
const ilmNames = new Set<string>();
262263
const ilmsStats: IlmsStats = {

x-pack/platform/plugins/private/indices_metadata/server/lib/services/indices_metadata.types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,16 @@ export interface Index {
113113
export interface DataStreams {
114114
items: DataStream[];
115115
}
116+
117+
export interface DataStreamLifeCycle {
118+
enabled: boolean;
119+
data_retention?: string;
120+
}
121+
116122
export interface DataStream {
117123
datastream_name: string;
118124
ilm_policy?: string;
125+
dsl?: DataStreamLifeCycle;
119126
template?: string;
120127
indices?: Index[];
121128
}

0 commit comments

Comments
 (0)