@ -1,4 +1,5 @@
import { css , cx } from '@emotion/css' ;
import { css , cx } from '@emotion/css' ;
import { isBefore , formatDuration } from 'date-fns' ;
import React , { useCallback , useMemo } from 'react' ;
import React , { useCallback , useMemo } from 'react' ;
import {
import {
@ -17,7 +18,6 @@ import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
import { useHasRuler } from '../../hooks/useHasRuler' ;
import { useHasRuler } from '../../hooks/useHasRuler' ;
import { Annotation } from '../../utils/constants' ;
import { Annotation } from '../../utils/constants' ;
import { isGrafanaRulerRule , isGrafanaRulerRulePaused } from '../../utils/rules' ;
import { isGrafanaRulerRule , isGrafanaRulerRulePaused } from '../../utils/rules' ;
import { isNullDate } from '../../utils/time' ;
import { DynamicTable , DynamicTableColumnProps , DynamicTableItemProps } from '../DynamicTable' ;
import { DynamicTable , DynamicTableColumnProps , DynamicTableItemProps } from '../DynamicTable' ;
import { DynamicTableWithGuidelines } from '../DynamicTableWithGuidelines' ;
import { DynamicTableWithGuidelines } from '../DynamicTableWithGuidelines' ;
import { ProvisioningBadge } from '../Provisioning' ;
import { ProvisioningBadge } from '../Provisioning' ;
@ -116,21 +116,30 @@ function useColumns(showSummaryColumn: boolean, showGroupColumn: boolean, showNe
const { hasRuler , rulerRulesLoaded } = useHasRuler ( ) ;
const { hasRuler , rulerRulesLoaded } = useHasRuler ( ) ;
const calculateNextEvaluationDate = useCallback ( ( rule : CombinedRule ) = > {
const calculateNextEvaluationDate = useCallback ( ( rule : CombinedRule ) = > {
const isValidLastEvaluation =
const isValidLastEvaluation = rule . promRule ? . lastEvaluation && isValidDate ( rule . promRule . lastEvaluation ) ;
rule . promRule ? . lastEvaluation &&
! isNullDate ( rule . promRule . lastEvaluation ) &&
isValidDate ( rule . promRule . lastEvaluation ) ;
const isValidIntervalDuration = rule . group . interval && isValidDuration ( rule . group . interval ) ;
const isValidIntervalDuration = rule . group . interval && isValidDuration ( rule . group . interval ) ;
if ( ! isValidLastEvaluation || ! isValidIntervalDuration ) {
if ( ! isValidLastEvaluation || ! isValidIntervalDuration || isGrafanaRulerRulePaused ( rule ) ) {
return ;
return ;
}
}
const lastEvaluationDate = Date . parse ( rule . promRule ? . lastEvaluation || '' ) ;
const intervalDuration = parseDuration ( rule . group . interval ! ) ;
const intervalDuration = parseDuration ( rule . group . interval ! ) ;
const lastEvaluationDate = Date . parse ( rule . promRule ? . lastEvaluation || '' ) ;
const nextEvaluationDate = addDurationToDate ( lastEvaluationDate , intervalDuration ) ;
const nextEvaluationDate = addDurationToDate ( lastEvaluationDate , intervalDuration ) ;
//when `nextEvaluationDate` is a past date it means lastEvaluation was more than one evaluation interval ago.
//in this case we use the interval value to show a more generic estimate.
//See https://github.com/grafana/grafana/issues/65125
const isPastDate = isBefore ( nextEvaluationDate , new Date ( ) ) ;
if ( isPastDate ) {
return {
humanized : ` within ${ formatDuration ( intervalDuration ) } ` ,
fullDate : ` within ${ formatDuration ( intervalDuration ) } ` ,
} ;
}
return {
return {
humanized : dateTime ( nextEvaluationDate ) . locale ( 'en' ) . fromNow ( true ) ,
humanized : ` in ${ dateTime ( nextEvaluationDate ) . locale ( 'en' ) . fromNow ( true ) } ` ,
fullDate : dateTimeFormat ( nextEvaluationDate , { format : 'YYYY-MM-DD HH:mm:ss' } ) ,
fullDate : dateTimeFormat ( nextEvaluationDate , { format : 'YYYY-MM-DD HH:mm:ss' } ) ,
} ;
} ;
} , [ ] ) ;
} , [ ] ) ;
@ -211,9 +220,9 @@ function useColumns(showSummaryColumn: boolean, showGroupColumn: boolean, showNe
renderCell : ( { data : rule } ) = > {
renderCell : ( { data : rule } ) = > {
const nextEvalInfo = calculateNextEvaluationDate ( rule ) ;
const nextEvalInfo = calculateNextEvaluationDate ( rule ) ;
return (
return (
nextEvalInfo ? . fullDate && (
nextEvalInfo && (
< Tooltip placement = "top" content = { ` ${ nextEvalInfo ? . fullDate } ` } theme = "info" >
< Tooltip placement = "top" content = { ` ${ nextEvalInfo ? . fullDate } ` } theme = "info" >
< span > in { nextEvalInfo ? . humanized } < / span >
< span > { nextEvalInfo ? . humanized } < / span >
< / Tooltip >
< / Tooltip >
)
)
) ;
) ;