2021-07-01 05:02:41 -05:00
|
|
|
import { css } from '@emotion/css';
|
2023-03-14 09:38:21 -05:00
|
|
|
import React from 'react';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2023-03-14 15:52:55 -05:00
|
|
|
import { GrafanaTheme2, dateTime, dateTimeFormat } from '@grafana/data';
|
|
|
|
import { useStyles2, Tooltip } from '@grafana/ui';
|
|
|
|
import { Time } from 'app/features/explore/Time';
|
2022-04-08 06:34:02 -05:00
|
|
|
import { CombinedRule } from 'app/types/unified-alerting';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2023-02-22 06:17:13 -06:00
|
|
|
import { useCleanAnnotations } from '../../utils/annotations';
|
2022-08-11 11:49:21 -05:00
|
|
|
import { isRecordingRulerRule } from '../../utils/rules';
|
2023-03-14 15:52:55 -05:00
|
|
|
import { isNullDate } from '../../utils/time';
|
2021-04-07 00:42:43 -05:00
|
|
|
import { AlertLabels } from '../AlertLabels';
|
2021-04-19 05:02:58 -05:00
|
|
|
import { DetailsField } from '../DetailsField';
|
2022-04-22 08:33:13 -05:00
|
|
|
|
2021-05-17 02:39:42 -05:00
|
|
|
import { RuleDetailsActionButtons } from './RuleDetailsActionButtons';
|
2022-04-08 06:34:02 -05:00
|
|
|
import { RuleDetailsAnnotations } from './RuleDetailsAnnotations';
|
2021-07-01 05:02:41 -05:00
|
|
|
import { RuleDetailsDataSources } from './RuleDetailsDataSources';
|
|
|
|
import { RuleDetailsExpression } from './RuleDetailsExpression';
|
2022-04-08 06:34:02 -05:00
|
|
|
import { RuleDetailsMatchingInstances } from './RuleDetailsMatchingInstances';
|
2021-04-07 00:42:43 -05:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
rule: CombinedRule;
|
|
|
|
}
|
|
|
|
|
2022-06-22 04:33:39 -05:00
|
|
|
// The limit is set to 15 in order to upkeep the good performance
|
|
|
|
// and to encourage users to go to the rule details page to see the rest of the instances
|
|
|
|
// We don't want to paginate the instances list on the alert list page
|
2023-04-25 04:19:20 -05:00
|
|
|
export const INSTANCES_DISPLAY_LIMIT = 15;
|
2022-06-22 04:33:39 -05:00
|
|
|
|
2023-03-14 09:38:21 -05:00
|
|
|
export const RuleDetails = ({ rule }: Props) => {
|
2021-06-23 01:27:47 -05:00
|
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const {
|
|
|
|
namespace: { rulesSource },
|
|
|
|
} = rule;
|
2021-04-07 00:42:43 -05:00
|
|
|
|
2023-02-22 06:17:13 -06:00
|
|
|
const annotations = useCleanAnnotations(rule.annotations);
|
2021-04-07 00:42:43 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div>
|
2023-01-03 06:08:14 -06:00
|
|
|
<RuleDetailsActionButtons rule={rule} rulesSource={rulesSource} isViewMode={false} />
|
2021-04-07 00:42:43 -05:00
|
|
|
<div className={styles.wrapper}>
|
|
|
|
<div className={styles.leftSide}>
|
2022-08-11 11:49:21 -05:00
|
|
|
{<EvaluationBehaviorSummary rule={rule} />}
|
2021-04-07 00:42:43 -05:00
|
|
|
{!!rule.labels && !!Object.keys(rule.labels).length && (
|
|
|
|
<DetailsField label="Labels" horizontal={true}>
|
|
|
|
<AlertLabels labels={rule.labels} />
|
|
|
|
</DetailsField>
|
|
|
|
)}
|
2021-07-01 05:02:41 -05:00
|
|
|
<RuleDetailsExpression rulesSource={rulesSource} rule={rule} annotations={annotations} />
|
|
|
|
<RuleDetailsAnnotations annotations={annotations} />
|
2021-04-07 00:42:43 -05:00
|
|
|
</div>
|
|
|
|
<div className={styles.rightSide}>
|
2021-07-01 05:02:41 -05:00
|
|
|
<RuleDetailsDataSources rulesSource={rulesSource} rule={rule} />
|
2021-04-07 00:42:43 -05:00
|
|
|
</div>
|
|
|
|
</div>
|
2022-06-22 04:33:39 -05:00
|
|
|
<RuleDetailsMatchingInstances rule={rule} itemsDisplayLimit={INSTANCES_DISPLAY_LIMIT} />
|
2021-04-07 00:42:43 -05:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-08-11 11:49:21 -05:00
|
|
|
interface EvaluationBehaviorSummaryProps {
|
|
|
|
rule: CombinedRule;
|
|
|
|
}
|
|
|
|
|
|
|
|
const EvaluationBehaviorSummary = ({ rule }: EvaluationBehaviorSummaryProps) => {
|
|
|
|
let forDuration: string | undefined;
|
|
|
|
let every = rule.group.interval;
|
2023-03-14 15:52:55 -05:00
|
|
|
let lastEvaluation = rule.promRule?.lastEvaluation;
|
|
|
|
let lastEvaluationDuration = rule.promRule?.evaluationTime;
|
2022-08-11 11:49:21 -05:00
|
|
|
|
|
|
|
// recording rules don't have a for duration
|
|
|
|
if (!isRecordingRulerRule(rule.rulerRule)) {
|
|
|
|
forDuration = rule.rulerRule?.for;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{every && (
|
|
|
|
<DetailsField label="Evaluate" horizontal={true}>
|
|
|
|
Every {every}
|
|
|
|
</DetailsField>
|
|
|
|
)}
|
|
|
|
{forDuration && (
|
|
|
|
<DetailsField label="For" horizontal={true}>
|
|
|
|
{forDuration}
|
|
|
|
</DetailsField>
|
|
|
|
)}
|
2023-03-14 15:52:55 -05:00
|
|
|
|
|
|
|
{lastEvaluation && !isNullDate(lastEvaluation) && (
|
|
|
|
<DetailsField label="Last evaluation" horizontal={true}>
|
|
|
|
<Tooltip
|
|
|
|
placement="top"
|
|
|
|
content={`${dateTimeFormat(lastEvaluation, { format: 'YYYY-MM-DD HH:mm:ss' })}`}
|
|
|
|
theme="info"
|
|
|
|
>
|
|
|
|
<span>{`${dateTime(lastEvaluation).locale('en').fromNow(true)} ago`}</span>
|
|
|
|
</Tooltip>
|
|
|
|
</DetailsField>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{lastEvaluation && !isNullDate(lastEvaluation) && lastEvaluationDuration !== undefined && (
|
|
|
|
<DetailsField label="Evaluation time" horizontal={true}>
|
|
|
|
<Tooltip placement="top" content={`${lastEvaluationDuration}s`} theme="info">
|
|
|
|
<span>{Time({ timeInMs: lastEvaluationDuration * 1000, humanize: true })}</span>
|
|
|
|
</Tooltip>
|
|
|
|
</DetailsField>
|
|
|
|
)}
|
2022-08-11 11:49:21 -05:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-06-23 01:27:47 -05:00
|
|
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
2021-04-07 00:42:43 -05:00
|
|
|
wrapper: css`
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row;
|
2022-06-20 08:37:05 -05:00
|
|
|
|
2021-06-23 01:27:47 -05:00
|
|
|
${theme.breakpoints.down('md')} {
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
2021-04-07 00:42:43 -05:00
|
|
|
`,
|
|
|
|
leftSide: css`
|
|
|
|
flex: 1;
|
|
|
|
`,
|
|
|
|
rightSide: css`
|
2021-06-23 01:27:47 -05:00
|
|
|
${theme.breakpoints.up('md')} {
|
|
|
|
padding-left: 90px;
|
|
|
|
width: 300px;
|
|
|
|
}
|
2021-04-07 00:42:43 -05:00
|
|
|
`,
|
|
|
|
});
|