Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
features
/
alerting
/
unified
/
components
/
rule-viewer
/
tabs
/
File Content:
Details.tsx
import { css } from '@emotion/css'; import { formatDistanceToNowStrict } from 'date-fns'; import React, { useCallback } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { Text, Stack, useStyles2, ClipboardButton, TextLink } from '@grafana/ui'; import { CombinedRule } from 'app/types/unified-alerting'; import { Annotations } from 'app/types/unified-alerting-dto'; import { isGrafanaRulerRule, isRecordingRulerRule } from '../../../utils/rules'; import { MetaText } from '../../MetaText'; import { Tokenize } from '../../Tokenize'; interface DetailsProps { rule: CombinedRule; } enum RuleType { GrafanaManagedAlertRule = 'Grafana-managed alert rule', CloudAlertRule = 'Cloud alert rule', CloudRecordingRule = 'Cloud recording rule', } const Details = ({ rule }: DetailsProps) => { const styles = useStyles2(getStyles); let ruleType: RuleType; if (isGrafanaRulerRule(rule.rulerRule)) { ruleType = RuleType.GrafanaManagedAlertRule; } else if (isRecordingRulerRule(rule.rulerRule)) { ruleType = RuleType.CloudRecordingRule; } else { // probably not the greatest assumption ruleType = RuleType.CloudAlertRule; } const evaluationDuration = rule.promRule?.evaluationTime; const evaluationTimestamp = rule.promRule?.lastEvaluation; const copyRuleUID = useCallback(() => { if (isGrafanaRulerRule(rule.rulerRule)) { return rule.rulerRule.grafana_alert.uid; } else { return ''; } }, [rule.rulerRule]); const annotations: Annotations | undefined = !isRecordingRulerRule(rule.rulerRule) ? rule.annotations ?? [] : undefined; const hasEvaluationDuration = Number.isFinite(evaluationDuration); return ( <Stack direction="column" gap={3}> <div className={styles.metadataWrapper}> {/* type and identifier (optional) */} <MetaText direction="column"> Rule type <Text color="primary">{ruleType}</Text> </MetaText> <MetaText direction="column"> {isGrafanaRulerRule(rule.rulerRule) && ( <> Rule Identifier <Stack direction="row" alignItems="center" gap={0.5}> <Text color="primary"> {rule.rulerRule.grafana_alert.uid} <ClipboardButton fill="text" variant="secondary" icon="copy" size="sm" getText={copyRuleUID} /> </Text> </Stack> </> )} </MetaText> {/* evaluation duration and pending period */} <MetaText direction="column"> {hasEvaluationDuration && ( <> Last evaluation {evaluationTimestamp && evaluationDuration && ( <span> <Text color="primary">{formatDistanceToNowStrict(new Date(evaluationTimestamp))} ago</Text>, took{' '} <Text color="primary">{evaluationDuration}ms</Text> </span> )} </> )} </MetaText> <MetaText direction="column"> {!isRecordingRulerRule(rule.rulerRule) && ( <> Pending period <Text color="primary">{rule.rulerRule?.for ?? '0s'}</Text> </> )} </MetaText> {/* nodata and execution error state mapping */} {isGrafanaRulerRule(rule.rulerRule) && ( <> <MetaText direction="column"> Alert state if no data or all values are null <Text color="primary">{rule.rulerRule.grafana_alert.no_data_state}</Text> </MetaText> <MetaText direction="column"> Alert state if execution error or timeout <Text color="primary">{rule.rulerRule.grafana_alert.exec_err_state}</Text> </MetaText> </> )} </div> {/* annotations go here */} {annotations && ( <> <Text variant="h4">Annotations</Text> {Object.keys(annotations).length === 0 ? ( <Text variant="bodySmall" color="secondary" italic> No annotations </Text> ) : ( <div className={styles.metadataWrapper}> {Object.entries(annotations).map(([name, value]) => ( <MetaText direction="column" key={name}> {name} <AnnotationValue value={value} /> </MetaText> ))} </div> )} </> )} </Stack> ); }; interface AnnotationValueProps { value: string; } function AnnotationValue({ value }: AnnotationValueProps) { const needsExternalLink = value && value.startsWith('http'); const tokenizeValue = <Tokenize input={value} delimiter={['{{', '}}']} />; if (needsExternalLink) { return ( <TextLink variant="bodySmall" href={value} external> {value} </TextLink> ); } return <Text color="primary">{tokenizeValue}</Text>; } const getStyles = (theme: GrafanaTheme2) => ({ metadataWrapper: css({ display: 'grid', gridTemplateColumns: 'auto auto', rowGap: theme.spacing(3), columnGap: theme.spacing(12), }), }); export { Details };
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
Details.tsx
5210 bytes
0644
History.tsx
1600 bytes
0644
Instances.tsx
498 bytes
0644
Query.tsx
4604 bytes
0644
Routing.tsx
85 bytes
0644
N4ST4R_ID | Naxtarrr