feat(slo): remove worst performing for no data group' (#182849)

This commit is contained in:
Kevin Delemme 2024-05-08 16:37:39 -04:00 committed by GitHub
parent ef0bd2e231
commit d529dbae98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 132 additions and 101 deletions

View file

@ -28,7 +28,7 @@ const findSLOGroupsParamsSchema = t.partial({
const sloGroupWithSummaryResponseSchema = t.type({
group: t.string,
groupBy: t.string,
groupBy: groupBySchema,
summary: groupSummarySchema,
});

View file

@ -5,19 +5,21 @@
* 2.0.
*/
import React, { useState, useEffect } from 'react';
import { Filter } from '@kbn/es-query';
import React, { useEffect, useState } from 'react';
import { Subject } from 'rxjs';
import { SLOView } from '../../../../pages/slos/components/toggle_slo_view';
import { GroupView } from '../../../../pages/slos/components/grouped_slos/group_view';
import { GroupByField } from '../../../../pages/slos/components/slo_list_group_by';
import { SLOView } from '../../../../pages/slos/components/toggle_slo_view';
import { SortField } from '../../../../pages/slos/hooks/use_url_search_state';
import { buildCombinedKqlQuery } from './helpers/build_kql_query';
interface Props {
groupBy: string;
groupBy: GroupByField;
groups?: string[];
kqlQuery?: string;
sloView: SLOView;
sort?: string;
sort?: SortField;
filters?: Filter[];
reloadSubject: Subject<boolean>;
}

View file

@ -5,10 +5,14 @@
* 2.0.
*/
import { GroupByField } from '../../../../../pages/slos/components/slo_list_group_by';
import { buildCombinedKqlQuery } from './build_kql_query';
describe('buildCombinedKqlQuery', () => {
const testData = [
const testData: Array<{
title: string;
props: { kqlQuery: string; groups: string[]; groupBy: GroupByField };
}> = [
{
title: 'no selected groups, with kql',
props: {

View file

@ -5,10 +5,12 @@
* 2.0.
*/
import { GroupByField } from '../../../../../pages/slos/components/slo_list_group_by';
interface Props {
kqlQuery: string;
groups: string[];
groupBy: string;
groupBy: GroupByField;
}
export const buildCombinedKqlQuery = ({ groups, groupBy, kqlQuery }: Props) => {

View file

@ -4,23 +4,22 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import './slo_group_filters.scss';
import React, { useState, useEffect, useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiSelect, EuiText } from '@elastic/eui';
import { Filter } from '@kbn/es-query';
import { debounce } from 'lodash';
import { EuiFormRow, EuiComboBox, EuiSelect, EuiComboBoxOptionOption, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useFetchSloGroups } from '../../../../hooks/use_fetch_slo_groups';
import { useGetSettings } from '../../../../pages/slo_settings/use_get_settings';
import { SLI_OPTIONS } from '../../../../pages/slo_edit/constants';
import { useKibana } from '../../../../utils/kibana_react';
import { useCreateDataView } from '../../../../hooks/use_create_data_view';
import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '../../../../../common/constants';
import { FormattedMessage } from '@kbn/i18n-react';
import { debounce } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { sloAppId } from '../../../../../common';
import type { GroupFilters, GroupBy } from '../types';
import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '../../../../../common/constants';
import { useCreateDataView } from '../../../../hooks/use_create_data_view';
import { useFetchSloGroups } from '../../../../hooks/use_fetch_slo_groups';
import { SLI_OPTIONS } from '../../../../pages/slo_edit/constants';
import { useGetSettings } from '../../../../pages/slo_settings/use_get_settings';
import { useKibana } from '../../../../utils/kibana_react';
import type { GroupBy, GroupFilters } from '../types';
import './slo_group_filters.scss';
interface Option {
value: string;
text: string;

View file

@ -22,11 +22,12 @@ import {
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
} from '../../common/constants';
import { SearchState } from '../pages/slos/hooks/use_url_search_state';
import { GroupByField } from '../pages/slos/components/slo_list_group_by';
interface SLOGroupsParams {
page?: number;
perPage?: number;
groupBy?: string;
groupBy?: GroupByField;
groupsFilter?: string[];
kqlQuery?: string;
tagsFilter?: SearchState['tagsFilter'];

View file

@ -10,8 +10,8 @@ import {
EuiBadge,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiHorizontalRule,
EuiLink,
EuiSpacer,
EuiTablePagination,
EuiText,
@ -19,27 +19,28 @@ import {
EuiTitle,
EuiToolTip,
} from '@elastic/eui';
import { CoreStart } from '@kbn/core-lifecycle-browser';
import { Filter } from '@kbn/es-query';
import { i18n } from '@kbn/i18n';
import React, { memo, useState } from 'react';
import { GroupSummary } from '@kbn/slo-schema';
import { CoreStart } from '@kbn/core-lifecycle-browser';
import { useKibana } from '../../../../utils/kibana_react';
import React, { memo, useState } from 'react';
import { paths } from '../../../../../common/locators/paths';
import { useFetchSloList } from '../../../../hooks/use_fetch_slo_list';
import { useKibana } from '../../../../utils/kibana_react';
import { SLI_OPTIONS } from '../../../slo_edit/constants';
import { useSloFormattedSLIValue } from '../../hooks/use_slo_summary';
import type { SortDirection, SortField } from '../../hooks/use_url_search_state';
import { SlosView } from '../slos_view';
import { GroupByField } from '../slo_list_group_by';
import { SLOView } from '../toggle_slo_view';
import type { SortDirection } from '../../hooks/use_url_search_state';
interface Props {
group: string;
kqlQuery?: string;
sloView: SLOView;
sort?: string;
sort?: SortField;
direction?: SortDirection;
groupBy: string;
groupBy: GroupByField;
summary?: GroupSummary;
filters?: Filter[];
}
@ -155,45 +156,59 @@ export function GroupListView({
})}
</EuiBadge>
</EuiFlexItem>
<EuiFlexItem>
<EuiToolTip
content={
<>
<EuiText size="s">
{i18n.translate('xpack.slo.group.totalSloViolatedTooltip', {
defaultMessage: 'SLO: {name}',
values: {
name: summary?.worst.slo?.name,
},
})}
</EuiText>
<EuiText size="s">
{i18n.translate('xpack.slo.group.totalSloViolatedTooltip.instance', {
defaultMessage: 'Instance: {instance}',
values: {
instance: summary?.worst.slo?.instanceId,
},
})}
</EuiText>
</>
}
>
<EuiLink
data-test-subj="o11yGroupListViewLink"
href={basePath.prepend(
paths.sloDetails(summary!.worst.slo?.id, summary!.worst.slo?.instanceId)
)}
>
{group === 'NO_DATA' ? (
<span>
{i18n.translate('xpack.slo.group.worstPerforming', {
defaultMessage: 'Worst performing: ',
})}
<EuiTextColor
color={summary?.worst.status !== 'HEALTHY' ? 'danger' : undefined}
<strong>
{i18n.translate('xpack.slo.group.worstPerforming.notAvailable', {
defaultMessage: 'N/A',
})}
</strong>
</span>
) : (
<EuiToolTip
content={
<>
<EuiText size="s">
{i18n.translate('xpack.slo.group.totalSloViolatedTooltip', {
defaultMessage: 'SLO: {name}',
values: {
name: summary?.worst.slo?.name,
},
})}
</EuiText>
<EuiText size="s">
{i18n.translate('xpack.slo.group.totalSloViolatedTooltip.instance', {
defaultMessage: 'Instance: {instance}',
values: {
instance: summary?.worst.slo?.instanceId,
},
})}
</EuiText>
</>
}
>
<EuiLink
data-test-subj="o11yGroupListViewLink"
href={basePath.prepend(
paths.sloDetails(summary!.worst.slo?.id, summary!.worst.slo?.instanceId)
)}
>
<strong>{worstSLI}</strong>
</EuiTextColor>
</EuiLink>
</EuiToolTip>
{i18n.translate('xpack.slo.group.worstPerforming', {
defaultMessage: 'Worst performing: ',
})}
<EuiTextColor
color={summary?.worst.status !== 'HEALTHY' ? 'danger' : undefined}
>
<strong>{worstSLI}</strong>
</EuiTextColor>
</EuiLink>
</EuiToolTip>
)}
</EuiFlexItem>
</EuiFlexGroup>
}

View file

@ -5,21 +5,22 @@
* 2.0.
*/
import { EuiEmptyPrompt, EuiFlexItem, EuiLoadingSpinner, EuiTablePagination } from '@elastic/eui';
import React, { useEffect } from 'react';
import { Filter } from '@kbn/es-query';
import React, { useEffect } from 'react';
import { useFetchSloGroups } from '../../../../hooks/use_fetch_slo_groups';
import { useUrlSearchState } from '../../hooks/use_url_search_state';
import type { SortDirection } from '../../hooks/use_url_search_state';
import { SortField, useUrlSearchState } from '../../hooks/use_url_search_state';
import { GroupByField } from '../slo_list_group_by';
import { SLOView } from '../toggle_slo_view';
import { SloGroupListEmpty } from './group_list_empty';
import { SloGroupListError } from './group_list_error';
import { GroupListView } from './group_list_view';
import type { SortDirection } from '../../hooks/use_url_search_state';
interface Props {
groupBy: string;
groupBy: GroupByField;
kqlQuery?: string;
sloView: SLOView;
sort?: string;
sort?: SortField;
direction?: SortDirection;
filters?: Filter[];
lastRefreshTime?: number;

View file

@ -4,15 +4,19 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FindSLOGroupsParams, FindSLOGroupsResponse, Pagination } from '@kbn/slo-schema';
import { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server';
import { findSLOGroupsResponseSchema } from '@kbn/slo-schema';
import { Logger } from '@kbn/core/server';
import { getListOfSummaryIndices } from './slo_settings';
import { typedSearch } from '../utils/queries';
import { IllegalArgumentError } from '../errors';
import { ElasticsearchClient, Logger, SavedObjectsClientContract } from '@kbn/core/server';
import {
FindSLOGroupsParams,
FindSLOGroupsResponse,
findSLOGroupsResponseSchema,
Pagination,
sloGroupWithSummaryResponseSchema,
} from '@kbn/slo-schema';
import { DEFAULT_SLO_GROUPS_PAGE_SIZE } from '../../common/constants';
import { Status } from '../domain/models';
import { IllegalArgumentError } from '../errors';
import { typedSearch } from '../utils/queries';
import { getListOfSummaryIndices } from './slo_settings';
import { EsSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary';
import { getElasticsearchQueryOrThrow } from './transform_generators';
const DEFAULT_PAGE = 1;
@ -32,12 +36,6 @@ function toPagination(params: FindSLOGroupsParams): Pagination {
};
}
interface SliDocument {
sliValue: number;
status: Status;
'slo.id': string;
}
export class FindSLOGroups {
constructor(
private esClient: ElasticsearchClient,
@ -151,28 +149,37 @@ export class FindSLOGroups {
});
const total = response.aggregations?.distinct_items?.value ?? 0;
const results =
response.aggregations?.groupBy?.buckets.reduce((acc, bucket) => {
const sliDocument = bucket.worst?.hits?.hits[0]?._source as SliDocument;
if (String(bucket.key).endsWith('.temp') && groupBy === '_index') {
return acc;
const results = response.aggregations?.groupBy?.buckets
.map((bucket) => {
const sourceSummaryDoc = bucket.worst?.hits?.hits[0]?._source as EsSummaryDocument;
const groupKey = String(bucket.key);
if (groupKey.endsWith('.temp') && groupBy === '_index') {
return undefined;
}
return [
...acc,
{
group: bucket.key,
groupBy,
summary: {
total: bucket.doc_count ?? 0,
worst: sliDocument,
violated: bucket.violated?.doc_count,
healthy: bucket.healthy?.doc_count,
degrading: bucket.degrading?.doc_count,
noData: bucket.noData?.doc_count,
return sloGroupWithSummaryResponseSchema.encode({
group: groupKey,
groupBy: groupBy!,
summary: {
total: bucket.doc_count ?? 0,
worst: {
sliValue: sourceSummaryDoc.sliValue,
status: sourceSummaryDoc.status,
slo: {
id: sourceSummaryDoc.slo.id,
instanceId: sourceSummaryDoc.slo.instanceId,
name: sourceSummaryDoc.slo.name,
},
},
violated: bucket.violated?.doc_count,
healthy: bucket.healthy?.doc_count,
degrading: bucket.degrading?.doc_count,
noData: bucket.noData?.doc_count,
},
];
}, [] as Array<Record<'group' | 'groupBy' | 'summary', any>>) ?? [];
});
})
.filter((result) => result !== undefined) as unknown as FindSLOGroupsResponse['results'];
return findSLOGroupsResponseSchema.encode({
page: pagination.page,
perPage: pagination.perPage,