StateTimeline: Show more precise duration (#44046)

* StateTimeline: Show more precise duration

* Add Leon's calculation

* Change to 30 days

Remove console logs. Add more tests.
pull/44355/merge
Zoltán Bedi 3 years ago committed by GitHub
parent ed7552db79
commit f16047660a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      public/app/plugins/panel/state-timeline/StateTimelineTooltip.tsx
  2. 40
      public/app/plugins/panel/state-timeline/utils.test.ts
  3. 60
      public/app/plugins/panel/state-timeline/utils.ts

@ -1,15 +1,7 @@
import React from 'react';
import {
DataFrame,
FALLBACK_COLOR,
formattedValueToString,
getDisplayProcessor,
getFieldDisplayName,
getValueFormat,
TimeZone,
} from '@grafana/data';
import { DataFrame, FALLBACK_COLOR, getDisplayProcessor, getFieldDisplayName, TimeZone } from '@grafana/data';
import { SeriesTableRow, useTheme2 } from '@grafana/ui';
import { findNextStateIndex } from './utils';
import { findNextStateIndex, fmtDuration } from './utils';
interface StateTimelineTooltipProps {
data: DataFrame[];
@ -57,7 +49,7 @@ export const StateTimelineTooltip: React.FC<StateTimelineTooltipProps> = ({
let durationFragment = null;
if (nextStateTs) {
const duration = nextStateTs && formattedValueToString(getValueFormat('dtdurationms')(nextStateTs - stateTs, 0));
const duration = nextStateTs && fmtDuration(nextStateTs - stateTs);
durationFragment = (
<>
<br />

@ -1,6 +1,12 @@
import { ArrayVector, createTheme, FieldType, ThresholdsMode, toDataFrame } from '@grafana/data';
import { LegendDisplayMode } from '@grafana/schema';
import { findNextStateIndex, getThresholdItems, prepareTimelineFields, prepareTimelineLegendItems } from './utils';
import {
findNextStateIndex,
fmtDuration,
getThresholdItems,
prepareTimelineFields,
prepareTimelineLegendItems,
} from './utils';
const theme = createTheme();
@ -221,3 +227,35 @@ describe('prepareTimelineLegendItems', () => {
expect(result).toHaveLength(1);
});
});
describe('duration', () => {
it.each`
value | expected
${-1} | ${''}
${20} | ${'20ms'}
${1000} | ${'1s'}
${1020} | ${'1s 20ms'}
${60000} | ${'1m'}
${61020} | ${'1m 1s'}
${3600000} | ${'1h'}
${6600000} | ${'1h 50m'}
${86400000} | ${'1d'}
${96640000} | ${'1d 2h'}
${604800000} | ${'1w'}
${691200000} | ${'1w 1d'}
${2419200000} | ${'4w'}
${2678400000} | ${'1mo 1d'}
${3196800000} | ${'1mo 1w'}
${3456000000} | ${'1mo 1w 3d'}
${6739200000} | ${'2mo 2w 4d'}
${31536000000} | ${'1y'}
${31968000000} | ${'1y 5d'}
${32140800000} | ${'1y 1w'}
${67910400000} | ${'2y 1mo 3w 5d'}
${40420800000} | ${'1y 3mo 1w 5d'}
${9007199254740991} | ${'285616y 5mo 1d'}
`(' function should format $value ms to $expected', ({ value, expected }) => {
const result = fmtDuration(value);
expect(result).toEqual(expected);
});
});

@ -570,3 +570,63 @@ export function findNextStateIndex(field: Field, datapointIdx: number) {
return end;
}
/**
* Returns the precise duration of a time range passed in milliseconds.
* This function calculates with 30 days month and 365 days year.
* adapted from https://gist.github.com/remino/1563878
* @param milliSeconds The duration in milliseconds
* @returns A formated string of the duration
*/
export function fmtDuration(milliSeconds: number): string {
if (milliSeconds < 0 || Number.isNaN(milliSeconds)) {
return '';
}
let yr: number, mo: number, wk: number, d: number, h: number, m: number, s: number, ms: number;
s = Math.floor(milliSeconds / 1000);
m = Math.floor(s / 60);
s = s % 60;
h = Math.floor(m / 60);
m = m % 60;
d = Math.floor(h / 24);
h = h % 24;
yr = Math.floor(d / 365);
if (yr > 0) {
d = d % 365;
}
mo = Math.floor(d / 30);
if (mo > 0) {
d = d % 30;
}
wk = Math.floor(d / 7);
if (wk > 0) {
d = d % 7;
}
ms = Math.round((milliSeconds % 1000) * 1000) / 1000;
return (yr > 0
? yr + 'y ' + (mo > 0 ? mo + 'mo ' : '') + (wk > 0 ? wk + 'w ' : '') + (d > 0 ? d + 'd ' : '')
: mo > 0
? mo + 'mo ' + (wk > 0 ? wk + 'w ' : '') + (d > 0 ? d + 'd ' : '')
: wk > 0
? wk + 'w ' + (d > 0 ? d + 'd ' : '')
: d > 0
? d + 'd ' + (h > 0 ? h + 'h ' : '')
: h > 0
? h + 'h ' + (m > 0 ? m + 'm ' : '')
: m > 0
? m + 'm ' + (s > 0 ? s + 's ' : '')
: s > 0
? s + 's ' + (ms > 0 ? ms + 'ms ' : '')
: ms > 0
? ms + 'ms '
: '0'
).trim();
}

Loading…
Cancel
Save