Skip to content

Commit

Permalink
feat: Add slo health callout on slo details page
Browse files Browse the repository at this point in the history
  • Loading branch information
kdelemme committed Apr 22, 2024
1 parent d43a0a3 commit 0c60115
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const sloKeys = {
definitions: (search: string, page: number, perPage: number, includeOutdatedOnly: boolean) =>
[...sloKeys.all, 'definitions', search, page, perPage, includeOutdatedOnly] as const,
globalDiagnosis: () => [...sloKeys.all, 'globalDiagnosis'] as const,
health: (list: Array<{ sloId: string; sloInstanceId: string }>) =>
[...sloKeys.all, 'health', list] as const,
burnRates: (
sloId: string,
instanceId: string | undefined,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { ALL_VALUE, FetchSLOHealthResponse, SLOWithSummaryResponse } from '@kbn/slo-schema';
import { useQuery } from '@tanstack/react-query';
import { useKibana } from '../utils/kibana_react';
import { sloKeys } from './query_key_factory';

export interface UseFetchSloHealth {
data: FetchSLOHealthResponse | undefined;
isLoading: boolean;
isError: boolean;
}

export interface Params {
list: SLOWithSummaryResponse[];
}

export function useFetchSloHealth({ list }: Params): UseFetchSloHealth {
const { http } = useKibana().services;
const payload = list.map((slo) => ({
sloId: slo.id,
sloInstanceId: slo.instanceId ?? ALL_VALUE,
}));

const { isLoading, isError, data } = useQuery({
queryKey: sloKeys.health(payload),
queryFn: async ({ signal }) => {
try {
const response = await http.post<FetchSLOHealthResponse>(
'/internal/observability/slos/_health',
{
body: JSON.stringify({ list: payload }),
signal,
}
);

return response;
} catch (error) {
// ignore error
}
},
enabled: Boolean(list.length > 0),
refetchOnWindowFocus: false,
keepPreviousData: true,
});

return {
data,
isLoading,
isError,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { EventsChartPanel } from './events_chart_panel';
import { Overview } from './overview/overview';
import { SliChartPanel } from './sli_chart_panel';
import { SloDetailsAlerts } from './slo_detail_alerts';
import { SloHealthCallout } from './slo_health_callout';
import { SloRemoteCallout } from './slo_remote_callout';

export const TAB_ID_URL_PARAM = 'tabId';
Expand Down Expand Up @@ -126,6 +127,7 @@ export function SloDetails({ slo, isAutoRefreshing, selectedTabId }: Props) {
return selectedTabId === OVERVIEW_TAB_ID ? (
<EuiFlexGroup direction="column" gutterSize="xl">
<SloRemoteCallout slo={slo} />
<SloHealthCallout slo={slo} />
<EuiFlexItem>
<Overview slo={slo} />
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import {
copyToClipboard,
EuiButton,
EuiButtonIcon,
EuiCallOut,
EuiCopy,
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { SLOWithSummaryResponse } from '@kbn/slo-schema';
import React from 'react';
import { getSLOSummaryTransformId, getSLOTransformId } from '../../../../common/constants';
import { useFetchSloHealth } from '../../../hooks/use_fetch_slo_health';
import { useKibana } from '../../../utils/kibana_react';

export function SloHealthCallout({ slo }: { slo: SLOWithSummaryResponse }) {
const { http } = useKibana().services;
const { isLoading, isError, data } = useFetchSloHealth({ list: [slo] });

if (isLoading || isError || data === undefined || data?.length !== 1) {
return null;
}

const health = data[0].health;
// if (health.overall === 'healthy') {
// return null;
// }

const count = health.rollup === 'unhealthy' && health.summary === 'unhealthy' ? 2 : 1;

return (
<EuiCallOut
color="warning"
iconType="warning"
title={i18n.translate('xpack.slo.sloDetails.healthCallout.title', {
defaultMessage: 'The SLO might have some issues',
})}
>
<EuiFlexGroup direction="column" alignItems="flexStart">
<EuiFlexItem>
<FormattedMessage
id="xpack.slo.sloDetails.healthCallout.description"
defaultMessage="The following {count, plural, one {transform is} other {transforms are}
} in a bad state, please investigate the error on the transform management page."
values={{ count }}
/>
<ul>
{health.rollup !== 'unhealthy' && (
<li>
{getSLOTransformId(slo.id, slo.revision)}
<EuiCopy textToCopy={getSLOTransformId(slo.id, slo.revision)}>
{(copy) => (
<EuiButtonIcon
aria-label="Copy text to clipboard"
color="text"
iconType="copy"
onClick={copy}
/>
)}
</EuiCopy>
</li>
)}
{health.summary !== 'unhealthy' && (
<li>
{getSLOSummaryTransformId(slo.id, slo.revision)}
<EuiCopy textToCopy={getSLOSummaryTransformId(slo.id, slo.revision)}>
{(copy) => (
<EuiButtonIcon
aria-label="Copy text to clipboard"
color="text"
iconType="copy"
onClick={copy}
/>
)}
</EuiCopy>
</li>
)}
</ul>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
color="warning"
fill
href={http?.basePath.prepend('/app/management/data/transform')}
>
<FormattedMessage
id="xpack.slo.sloDetails.healthCallout.buttonTransformLabel"
defaultMessage="Inspect"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiCallOut>
);
}

0 comments on commit 0c60115

Please sign in to comment.