mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
feat(slo): remove worst performing for no data group' (#182849)
This commit is contained in:
parent
ef0bd2e231
commit
d529dbae98
9 changed files with 132 additions and 101 deletions
|
@ -28,7 +28,7 @@ const findSLOGroupsParamsSchema = t.partial({
|
|||
|
||||
const sloGroupWithSummaryResponseSchema = t.type({
|
||||
group: t.string,
|
||||
groupBy: t.string,
|
||||
groupBy: groupBySchema,
|
||||
summary: groupSummarySchema,
|
||||
});
|
||||
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue