Skip to content

Commit 82528fc

Browse files
authored
[SLO] exclude stale SLOs from group by stats (elastic#240077)
Fixes elastic#240075 Stale SLOs (SLOs not updated within the defined stale threshold under SLO > Settings) are hidden by default from the SLO overview list. However when user groups by instance id, the stale SLOs were not excluded from the group by stats shown in the accordion title. This PR excludes stale SLOs from the group by stats. **Before** <img width="600" height="681" alt="Screenshot 2025-10-22 at 14 30 32" src="https://github.com/user-attachments/assets/fba3458e-bf05-49ec-a25a-4aa64ff973a9" /> **After** <img width="600" height="623" alt="Screenshot 2025-10-22 at 14 33 37" src="https://github.com/user-attachments/assets/34f7b070-ed3c-4662-83c3-84b77048544a" /> **Note** If user wants to see the stale SLOs, they can click on the `Stale stat` number and the stale SLOs will be displayed.
1 parent c38973d commit 82528fc

4 files changed

Lines changed: 82 additions & 27 deletions

File tree

x-pack/solutions/observability/plugins/slo/server/services/find_slo_groups.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { IllegalArgumentError } from '../errors';
1313
import { typedSearch } from '../utils/queries';
1414
import type { EsSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary';
1515
import { getElasticsearchQueryOrThrow, parseStringFilters } from './transform_generators';
16+
import { excludeStaleSummaryFilter } from './summary_utils';
1617

1718
const DEFAULT_PAGE = 1;
1819
const MAX_PER_PAGE = 5000;
@@ -59,6 +60,7 @@ export class FindSLOGroups {
5960
bool: {
6061
filter: [
6162
{ term: { spaceId: this.spaceId } },
63+
...excludeStaleSummaryFilter(settings, kqlQuery, true),
6264
getElasticsearchQueryOrThrow(kqlQuery),
6365
...(parsedFilters.filter ?? []),
6466
],

x-pack/solutions/observability/plugins/slo/server/services/summary_search_client/summary_search_client.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@
55
* 2.0.
66
*/
77

8-
import type { estypes } from '@elastic/elasticsearch';
98
import type { IScopedClusterClient, Logger, SavedObjectsClientContract } from '@kbn/core/server';
109
import { isCCSRemoteIndexName } from '@kbn/es-query';
1110
import { ALL_VALUE } from '@kbn/slo-schema';
1211
import { assertNever } from '@kbn/std';
1312
import { partition } from 'lodash';
1413
import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants';
15-
import type { StoredSLOSettings } from '../../domain/models';
1614
import { toHighPrecision } from '../../utils/number';
1715
import { createEsParams, typedSearch } from '../../utils/queries';
1816
import { getSummaryIndices, getSloSettings } from '../slo_settings';
1917
import type { EsSummaryDocument } from '../summary_transform_generator/helpers/create_temp_summary';
2018
import { getElasticsearchQueryOrThrow, parseStringFilters } from '../transform_generators';
19+
import { excludeStaleSummaryFilter } from '../summary_utils';
2120
import { fromRemoteSummaryDocumentToSloDefinition } from '../unsafe_federated/remote_summary_doc_to_slo';
2221
import { getFlattenedGroupings } from '../utils';
2322
import type {
@@ -187,31 +186,7 @@ export class DefaultSummarySearchClient implements SummarySearchClient {
187186
}
188187
}
189188

190-
function excludeStaleSummaryFilter(
191-
settings: StoredSLOSettings,
192-
kqlFilter: string,
193-
hideStale?: boolean
194-
): estypes.QueryDslQueryContainer[] {
195-
if (kqlFilter.includes('summaryUpdatedAt') || !settings.staleThresholdInHours || !hideStale) {
196-
return [];
197-
}
198-
return [
199-
{
200-
bool: {
201-
should: [
202-
{ term: { isTempDoc: true } },
203-
{
204-
range: {
205-
summaryUpdatedAt: {
206-
gte: `now-${settings.staleThresholdInHours}h`,
207-
},
208-
},
209-
},
210-
],
211-
},
212-
},
213-
];
214-
}
189+
// excludeStaleSummaryFilter moved to ../summary_utils.ts
215190

216191
function getRemoteClusterName(index: string) {
217192
if (isCCSRemoteIndexName(index)) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { excludeStaleSummaryFilter } from './summary_utils';
9+
10+
describe('excludeStaleSummaryFilter', () => {
11+
it('returns empty array when kqlFilter contains summaryUpdatedAt', () => {
12+
const settings = { staleThresholdInHours: 24 } as any;
13+
const res = excludeStaleSummaryFilter(settings, 'summaryUpdatedAt:>now-1d', true);
14+
expect(res).toEqual([]);
15+
});
16+
17+
it('returns empty array when staleThresholdInHours is falsy', () => {
18+
const settings = { staleThresholdInHours: 0 } as any;
19+
const res = excludeStaleSummaryFilter(settings, '', true);
20+
expect(res).toEqual([]);
21+
});
22+
23+
it('returns empty array when hideStale is false', () => {
24+
const settings = { staleThresholdInHours: 12 } as any;
25+
const res = excludeStaleSummaryFilter(settings, '', false);
26+
expect(res).toEqual([]);
27+
});
28+
29+
it('returns the expected bool/should filter when conditions met', () => {
30+
const settings = { staleThresholdInHours: 48 } as any;
31+
const res = excludeStaleSummaryFilter(settings, '', true);
32+
expect(res).toHaveLength(1);
33+
const filt = res[0] as any;
34+
expect(filt.bool).toBeDefined();
35+
expect(Array.isArray(filt.bool.should)).toBe(true);
36+
const [termClause, rangeClause] = filt.bool.should;
37+
expect(termClause).toEqual({ term: { isTempDoc: true } });
38+
expect(rangeClause).toHaveProperty(
39+
'range.summaryUpdatedAt.gte',
40+
`now-${settings.staleThresholdInHours}h`
41+
);
42+
});
43+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { estypes } from '@elastic/elasticsearch';
9+
import type { StoredSLOSettings } from '../domain/models';
10+
11+
export function excludeStaleSummaryFilter(
12+
settings: StoredSLOSettings,
13+
kqlFilter: string,
14+
hideStale?: boolean
15+
): estypes.QueryDslQueryContainer[] {
16+
if (kqlFilter.includes('summaryUpdatedAt') || !settings.staleThresholdInHours || !hideStale) {
17+
return [];
18+
}
19+
return [
20+
{
21+
bool: {
22+
should: [
23+
{ term: { isTempDoc: true } },
24+
{
25+
range: {
26+
summaryUpdatedAt: {
27+
gte: `now-${settings.staleThresholdInHours}h`,
28+
},
29+
},
30+
},
31+
],
32+
},
33+
},
34+
];
35+
}

0 commit comments

Comments
 (0)