Skip to content

Commit

Permalink
refresh chart every 5 seconds and avoid flikering when fields change
Browse files Browse the repository at this point in the history
  • Loading branch information
gmmorris committed Mar 19, 2020
1 parent 7aa4651 commit 51ffd2a
Showing 1 changed file with 45 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import React, { Fragment, useEffect, useState } from 'react';
import { IUiSettingsClient, HttpSetup } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { interval } from 'rxjs';
import {
AnnotationDomainTypes,
Axis,
Expand All @@ -21,7 +22,14 @@ import {
niceTimeFormatter,
} from '@elastic/charts';
import moment from 'moment-timezone';
import { EuiCallOut, EuiLoadingChart, EuiSpacer, EuiEmptyPrompt, EuiText } from '@elastic/eui';
import {
EuiCallOut,
EuiLoadingChart,
EuiSpacer,
EuiEmptyPrompt,
EuiText,
EuiLoadingSpinner,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { getThresholdAlertVisualizationData } from '../../../../common/lib/index_threshold_api';
import { AggregationType, Comparator } from '../../../../common/types';
Expand Down Expand Up @@ -59,7 +67,7 @@ const getTimezone = (uiSettings: IUiSettingsClient) => {
return tzOffset;
};

const getDomain = (alertInterval: string) => {
const getDomain = (alertInterval: string, startAt: Date) => {
const VISUALIZE_INTERVALS = 30;
let intervalMillis: number;

Expand All @@ -69,10 +77,9 @@ const getDomain = (alertInterval: string) => {
intervalMillis = 1000 * 60; // default to one minute if not parseable
}

const now = Date.now();
return {
min: now - intervalMillis * VISUALIZE_INTERVALS,
max: now,
min: startAt.getTime() - intervalMillis * VISUALIZE_INTERVALS,
max: startAt.getTime(),
};
};

Expand All @@ -84,6 +91,15 @@ interface Props {
[key: string]: Comparator;
};
alertsContext: AlertsContextValue;
refreshRateInMilliseconds: number;
}

const DEFAULT_REFRESH_RATE = 5000;

enum LoadingStateType {
FirstLoad,
Refresh,
Idle,
}

type MetricResult = [number, number]; // [epochMillis, value]
Expand All @@ -93,6 +109,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
aggregationTypes,
comparators,
alertsContext,
refreshRateInMilliseconds = DEFAULT_REFRESH_RATE,
}) => {
const {
index,
Expand All @@ -109,14 +126,25 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
} = alertParams;
const { http, toastNotifications, charts, uiSettings, dataFieldsFormats } = alertsContext;

const [isLoading, setIsLoading] = useState(false);
const [loadingState, setLoadingState] = useState<LoadingStateType | null>(null);
const [error, setError] = useState<undefined | any>(undefined);
const [visualizationData, setVisualizationData] = useState<Record<string, MetricResult[]>>();
const [startVisualizationAt, setStartVisualizationAt] = useState<Date>(new Date());

useEffect(() => {
const source = interval(refreshRateInMilliseconds);
const subscription = source.subscribe((val: number) => {
setStartVisualizationAt(new Date());
});
return () => {
subscription.unsubscribe();
};
}, [refreshRateInMilliseconds]);

useEffect(() => {
(async () => {
try {
setIsLoading(true);
setLoadingState(loadingState ? LoadingStateType.Refresh : LoadingStateType.FirstLoad);
setVisualizationData(
await getVisualizationData(alertWithoutActions, visualizeOptions, http)
);
Expand All @@ -131,7 +159,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
}
setError(e);
} finally {
setIsLoading(false);
setLoadingState(LoadingStateType.Idle);
}
})();
/* eslint-disable react-hooks/exhaustive-deps */
Expand All @@ -147,6 +175,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
timeWindowUnit,
groupBy,
threshold,
startVisualizationAt,
]);
/* eslint-enable react-hooks/exhaustive-deps */

Expand All @@ -155,7 +184,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
}
const chartsTheme = charts.theme.useChartsTheme();

const domain = getDomain(alertInterval);
const domain = getDomain(alertInterval, startVisualizationAt);
const visualizeOptions = {
rangeFrom: new Date(domain.min).toISOString(),
rangeTo: new Date(domain.max).toISOString(),
Expand All @@ -165,7 +194,7 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
// Fetching visualization data is independent of alert actions
const alertWithoutActions = { ...alertParams, actions: [], type: 'threshold' };

if (isLoading) {
if (loadingState === LoadingStateType.FirstLoad) {
return (
<EuiEmptyPrompt
title={<EuiLoadingChart size="xl" />}
Expand Down Expand Up @@ -224,7 +253,12 @@ export const ThresholdVisualization: React.FunctionComponent<Props> = ({
const dateFormatter = niceTimeFormatter([domain.min, domain.max]);
const aggLabel = aggregationTypes[aggType].text;
return (
<div data-test-subj="alertVisualizationChart">
<div data-test-subj="alertVisualizationChart" style={{ position: 'relative' }}>
{loadingState === LoadingStateType.Refresh ? (
<EuiLoadingSpinner size="l" style={{ position: 'absolute', top: '8%', right: '5%' }} />
) : (
<Fragment />
)}
{alertVisualizationDataKeys.length ? (
<Chart size={['100%', 200]} renderer="canvas">
<Settings
Expand Down

0 comments on commit 51ffd2a

Please sign in to comment.