Skip to content

Commit

Permalink
feat(HealthCheck): show aggregated status in preview (#839)
Browse files Browse the repository at this point in the history
  • Loading branch information
ValeraS authored Jun 21, 2024
1 parent cdf36da commit 71d316c
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 163 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
@import '../../../../../styles/mixins.scss';

.healthcheck {
display: flex;

&_expanded {
// Since most of the inner containers have fixed width, we can set fixed width here as well
// Thus we will get rid of unneeded layout shift when scrollbar appear
min-width: 885px;
}

&__issue-preview {
margin-bottom: 15px;
}

&__message-container {
padding: 15px 0;
}
$block: &;

&__details {
width: 872px;
Expand All @@ -26,13 +12,10 @@
}

&__preview {
height: 100%;
}

&__preview-header {
gap: 8px;
display: flex;
flex-direction: column;

margin-bottom: var(--diagnostics-section-title-margin);
height: 100%;
}

&__preview-title {
Expand All @@ -44,9 +27,16 @@
}

&__preview-content {
margin: auto;

line-height: 24px;
}

&__preview-status-icon {
width: 64px;
height: 64px;
}

&__preview-title-wrapper {
display: flex;
align-items: center;
Expand All @@ -55,13 +45,45 @@
margin-bottom: 4px;
}

&__issues-statistics {
&__preview-issue {
position: relative;
top: -8px;

display: flex;
flex-wrap: wrap;
flex-direction: column;
align-items: center;
gap: 10px;
gap: 4px;

margin: 8px 0;
&_good {
color: var(--g-color-text-positive);
& #{$block}__self-check-status-indicator {
background-color: var(--g-color-base-positive-light);
}
}
&_degraded {
color: var(--g-color-text-info);
& #{$block}__self-check-status-indicator {
background-color: var(--g-color-base-info-light);
}
}
&_emergency {
color: var(--g-color-text-danger);
& #{$block}__self-check-status-indicator {
background-color: var(--g-color-base-danger-light);
}
}
&_unspecified {
color: var(--g-color-text-misc);
& #{$block}__self-check-status-indicator {
background-color: var(--g-color-base-misc-light);
}
}
&_maintenance_required {
color: var(--g-color-text-warning-heavy);
& #{$block}__self-check-status-indicator {
background-color: var(--g-color-base-warning-light);
}
}
}

&__self-check-status-indicator {
Expand All @@ -71,39 +93,8 @@

font-size: 13px;
line-height: 24px;
text-wrap: nowrap;

border-radius: 4px;

&_good,
&_green {
color: var(--g-color-text-positive);
background-color: var(--g-color-base-positive-light);
}
&_degraded,
&_yellow {
color: var(--g-color-text-warning);
background-color: var(--g-color-base-warning-light);
}

&_blue {
color: var(--g-color-text-info);
background-color: var(--g-color-base-info-light);
}

&_emergency,
&_red {
color: var(--g-color-text-danger);
background-color: var(--g-color-base-danger-light);
}
&_unspecified,
&_grey {
color: var(--g-color-text-misc);
background-color: var(--g-color-base-misc-light);
}
&_maintenance_required,
&_orange {
color: var(--g-color-text-warning-heavy);
background-color: var(--g-color-base-warning-light);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React from 'react';

import {ResponseError} from '../../../../../components/Errors/ResponseError';
import {Loader} from '../../../../../components/Loader';
import type {IssuesTree} from '../../../../../store/reducers/healthcheckInfo/types';
import {cn} from '../../../../../utils/cn';
import {useTypedSelector} from '../../../../../utils/hooks';
import {useHealthcheck} from '../useHealthcheck';

import IssueTree from './IssuesViewer/IssueTree';
import i18n from './i18n';
Expand All @@ -13,13 +14,12 @@ import './Healthcheck.scss';
const b = cn('healthcheck');

interface HealthcheckDetailsProps {
issueTrees?: IssuesTree[];
loading?: boolean;
error?: unknown;
tenantName: string;
}

export function HealthcheckDetails(props: HealthcheckDetailsProps) {
const {issueTrees, loading, error} = props;
export function HealthcheckDetails({tenantName}: HealthcheckDetailsProps) {
const {autorefresh} = useTypedSelector((state) => state.schema);
const {issueTrees, loading, error} = useHealthcheck(tenantName, {autorefresh});

const renderContent = () => {
if (error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import React from 'react';

import {ArrowsRotateRight} from '@gravity-ui/icons';
import {Button, Icon} from '@gravity-ui/uikit';
import {
CircleCheck,
CircleInfo,
CircleQuestion,
CircleXmark,
TriangleExclamationFill,
} from '@gravity-ui/icons';
import type {IconData} from '@gravity-ui/uikit';
import {Icon} from '@gravity-ui/uikit';

import {DiagnosticCard} from '../../../../../components/DiagnosticCard/DiagnosticCard';
import {EntityStatus} from '../../../../../components/EntityStatus/EntityStatus';
import {ResponseError} from '../../../../../components/Errors/ResponseError';
import {Loader} from '../../../../../components/Loader';
import {hcStatusToColorFlag} from '../../../../../store/reducers/healthcheckInfo/utils';
import type {SelfCheckResult, StatusFlag} from '../../../../../types/api/healthcheck';
import {healthcheckApi} from '../../../../../store/reducers/healthcheckInfo/healthcheckInfo';
import {SelfCheckResult} from '../../../../../types/api/healthcheck';
import {cn} from '../../../../../utils/cn';
import {useTypedSelector} from '../../../../../utils/hooks';

import i18n from './i18n';

Expand All @@ -18,43 +23,39 @@ import './Healthcheck.scss';
const b = cn('healthcheck');

interface HealthcheckPreviewProps {
selfCheckResult: SelfCheckResult;
issuesStatistics?: [StatusFlag, number][];
loading?: boolean;
onUpdate: VoidFunction;
error?: unknown;
tenantName: string;
active?: boolean;
}

export function HealthcheckPreview(props: HealthcheckPreviewProps) {
const {selfCheckResult, issuesStatistics, loading, onUpdate, error, active} = props;
const icons: Record<SelfCheckResult, IconData> = {
[SelfCheckResult.UNSPECIFIED]: CircleQuestion,
[SelfCheckResult.GOOD]: CircleCheck,
[SelfCheckResult.DEGRADED]: CircleInfo,
[SelfCheckResult.MAINTENANCE_REQUIRED]: CircleXmark,
[SelfCheckResult.EMERGENCY]: TriangleExclamationFill,
};

const renderHeader = () => {
const modifier = selfCheckResult.toLowerCase();
export function HealthcheckPreview(props: HealthcheckPreviewProps) {
const {tenantName, active} = props;
const {autorefresh} = useTypedSelector((state) => state.schema);
const {
currentData: data,
isFetching,
error,
} = healthcheckApi.useGetHealthcheckInfoQuery(
{database: tenantName},
{
pollingInterval: autorefresh,
},
);

if (loading) {
return null;
}
const loading = isFetching && data === undefined;

const renderHeader = () => {
return (
<div className={b('preview-header')}>
<div className={b('preview-title-wrapper')}>
<div className={b('preview-title')}>{i18n('title.healthcheck')}</div>
<Button
size="s"
onClick={(event) => {
// FIXME: refactor card to remove the button from the anchor link.
event.preventDefault();
onUpdate();
}}
loading={loading}
view="flat-secondary"
>
<Icon data={ArrowsRotateRight} size={20} />
</Button>
</div>
<div className={b('self-check-status-indicator', {[modifier]: true})}>
{selfCheckResult}
</div>
</div>
);
Expand All @@ -69,26 +70,16 @@ export function HealthcheckPreview(props: HealthcheckPreviewProps) {
return <Loader size="m" />;
}

const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
const modifier = selfCheckResult.toLowerCase();
return (
<div className={b('preview-content')}>
{!issuesStatistics || !issuesStatistics.length ? (
i18n('status_message.ok')
) : (
<React.Fragment>
<div>{i18n('label.issues')}</div>
<div className={b('issues-statistics')}>
{issuesStatistics.map(([status, count]) => (
<EntityStatus
key={status}
mode="icons"
status={hcStatusToColorFlag[status]}
label={count.toString()}
size="l"
/>
))}
</div>
</React.Fragment>
)}
<div className={b('preview-issue', {[modifier]: true})}>
<Icon className={b('preview-status-icon')} data={icons[selfCheckResult]} />
<div className={b('self-check-status-indicator')}>
{selfCheckResult.replace(/_/g, ' ')}
</div>
</div>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
memoryUsageToStatus,
storageUsageToStatus,
} from '../../../../../store/reducers/tenants/utils';
import type {SelfCheckResult, StatusFlag} from '../../../../../types/api/healthcheck';
import {cn} from '../../../../../utils/cn';
import {formatStorageValues} from '../../../../../utils/dataFormatters/dataFormatters';
import {useTypedSelector} from '../../../../../utils/hooks';
Expand Down Expand Up @@ -53,25 +52,15 @@ interface MetricsCardsProps {
memoryStats?: TenantMetricStats[];
blobStorageStats?: TenantStorageStats[];
tabletStorageStats?: TenantStorageStats[];

issuesStatistics?: [StatusFlag, number][];
selfCheckResult: SelfCheckResult;
fetchHealthcheck: VoidFunction;
healthcheckLoading?: boolean;
healthCheckWasLoaded?: boolean;
healthcheckError?: unknown;
tenantName: string;
}

export function MetricsCards({
poolsCpuStats,
memoryStats,
blobStorageStats,
tabletStorageStats,
issuesStatistics,
selfCheckResult,
fetchHealthcheck,
healthcheckLoading,
healthcheckError,
tenantName,
}: MetricsCardsProps) {
const location = useLocation();

Expand Down Expand Up @@ -130,11 +119,7 @@ export function MetricsCards({
</Link>
<Link to={tabLinks.healthcheck} className={b('tab')}>
<HealthcheckPreview
selfCheckResult={selfCheckResult}
issuesStatistics={issuesStatistics}
onUpdate={fetchHealthcheck}
loading={healthcheckLoading}
error={healthcheckError}
tenantName={tenantName}
active={metricsTab === TENANT_METRICS_TABS_IDS.healthcheck}
/>
</Link>
Expand Down
Loading

0 comments on commit 71d316c

Please sign in to comment.