Skip to content

Commit

Permalink
Add proper message in case of long initialization. Issue:opendistro-f…
Browse files Browse the repository at this point in the history
  • Loading branch information
yizheliu-amazon committed May 19, 2020
1 parent 2e9a9ae commit 8886443
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,27 @@ import React from 'react';
import { EuiButton, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui';
import { Fragment } from 'react';
import { Detector } from '../../../../models/interfaces';
import {
getDetectorInitializationInfo,
IS_INIT_OVERTIME_FIELD,
INIT_DETAILS_FIELD,
INIT_ERROR_MESSAGE_FIELD,
INIT_ACTION_ITEM_FIELD,
} from '../../utils/utils';
import { get } from 'lodash';

export interface DetectorInitializingProps {
detector: Detector;
onSwitchToConfiguration(): void;
}

export const DetectorInitializing = (props: DetectorInitializingProps) => {
const initializationInfo = getDetectorInitializationInfo(props.detector);
const isInitOvertime = get(initializationInfo, IS_INIT_OVERTIME_FIELD, false);
const initDetails = get(initializationInfo, INIT_DETAILS_FIELD, {});
const initErrorMessage = get(initDetails, INIT_ERROR_MESSAGE_FIELD, '');
const initActionItem = get(initDetails, INIT_ACTION_ITEM_FIELD, '');

return (
<EuiEmptyPrompt
style={{ maxWidth: '75%' }}
Expand All @@ -34,14 +48,24 @@ export const DetectorInitializing = (props: DetectorInitializingProps) => {
}
body={
<Fragment>
<p>
Based on your latest update to the detector configuration, the
detector is collecting sufficient data to generate accurate
real-time anomalies.
</p>
<p>
The longer the detector interval is, the more time this will take.
</p>
{!isInitOvertime
? [
<p>
Based on your latest update to the detector configuration, the
detector is collecting sufficient data to generate accurate
real-time anomalies.
</p>,
<p>
The longer the detector interval is, the more time this will
take.
</p>,
]
: [
<p>
{`Detector initialization is not complete because ${initErrorMessage}.`}
</p>,
<p>{`${initActionItem}`}</p>,
]}
</Fragment>
}
actions={
Expand Down
21 changes: 19 additions & 2 deletions public/pages/DetectorResults/containers/AnomalyResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ import { BREADCRUMBS, DETECTOR_STATE } from '../../../utils/constants';
import { AnomalyResultsLiveChart } from './AnomalyResultsLiveChart';
import { AnomalyHistory } from './AnomalyHistory';
import { DetectorStateDetails } from './DetectorStateDetails';
import {
getDetectorInitializationInfo,
IS_INIT_OVERTIME_FIELD,
INIT_DETAILS_FIELD,
INIT_ERROR_MESSAGE_FIELD,
INIT_ACTION_ITEM_FIELD,
} from '../utils/utils';

interface AnomalyResultsProps extends RouteComponentProps {
detectorId: string;
Expand Down Expand Up @@ -77,6 +84,12 @@ export function AnomalyResults(props: AnomalyResultsProps) {
detector.enabled &&
detector.disabledTime;

const initializationInfo = getDetectorInitializationInfo(detector);
const isInitOvertime = get(initializationInfo, IS_INIT_OVERTIME_FIELD, false);
const initDetails = get(initializationInfo, INIT_DETAILS_FIELD, {});
const initErrorMessage = get(initDetails, INIT_ERROR_MESSAGE_FIELD, '');
const initActionItem = get(initDetails, INIT_ACTION_ITEM_FIELD, '');

return (
<Fragment>
<EuiPage style={{ marginTop: '16px', paddingTop: '0px' }}>
Expand All @@ -93,7 +106,9 @@ export function AnomalyResults(props: AnomalyResultsProps) {
title={
isDetectorUpdated
? 'There are change(s) to the detector configuration after the detector is stopped.'
: 'The detector is being re-initialized based on the latest configuration changes.'
: !isInitOvertime
? 'The detector is being re-initialized based on the latest configuration changes.'
: `Detector initialization is not complete because ${initErrorMessage}.`
}
color="warning"
iconType="alert"
Expand All @@ -104,12 +119,14 @@ export function AnomalyResults(props: AnomalyResultsProps) {
Restart the detector to see accurate anomalies based
on your latest configuration.
</p>
) : (
) : !isInitOvertime ? (
<p>
After the initialization is complete, you will see the
anomaly results based on your latest configuration
changes.
</p>
) : (
<p>{`${initActionItem}`}</p>
)}
<EuiButton
onClick={props.onSwitchToConfiguration}
Expand Down
10 changes: 10 additions & 0 deletions public/pages/DetectorResults/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,13 @@ export const LIVE_ANOMALY_CHART_THEME = [
},
},
];

//https://github.com/opendistro-for-elasticsearch/anomaly-detection/blob/master/src/main/java/com/amazon/opendistroforelasticsearch/ad/transport/AnomalyResultTransportAction.java#L307
export const NO_FULL_SHINGLE_ERROR_MESSAGE =
'No full shingle in current detection window';
//https://github.com/opendistro-for-elasticsearch/anomaly-detection/blob/master/src/main/java/com/amazon/opendistroforelasticsearch/ad/transport/AnomalyResultTransportAction.java#L295
export const NO_DATA_IN_WINDOW_ERROR_MESSAGE =
'No data in current detection window';
//https://github.com/opendistro-for-elasticsearch/anomaly-detection/blob/master/src/main/java/com/amazon/opendistroforelasticsearch/ad/transport/AnomalyResultTransportAction.java#L81
export const NO_RCF_MODEL_ERROR_MESSAGE =
'No RCF models are available either because RCF models are not ready or all nodes are unresponsive or the system might have bugs';
81 changes: 81 additions & 0 deletions public/pages/DetectorResults/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import { Detector } from '../../../models/interfaces';
import {
NO_FULL_SHINGLE_ERROR_MESSAGE,
NO_DATA_IN_WINDOW_ERROR_MESSAGE,
NO_RCF_MODEL_ERROR_MESSAGE,
} from './constants';
import { DETECTOR_STATE, SHINGLE_SIZE } from '../../../utils/constants';
import { DETECTOR_INIT_FAILURES } from '../../../pages/DetectorDetail/utils/constants';
import moment, { Moment } from 'moment';

export const IS_INIT_OVERTIME_FIELD = 'isInitOvertime';
export const INIT_DETAILS_FIELD = 'initDetails';
export const INIT_ERROR_MESSAGE_FIELD = 'initErrorMessage';
export const INIT_ACTION_ITEM_FIELD = 'initActionItem';

export const getDetectorInitializationInfo = (detector: Detector) => {
const currentTime = moment();

let result = {
[IS_INIT_OVERTIME_FIELD]: false,
[INIT_DETAILS_FIELD]: {},
};
if (isDetectorInitOverTime(currentTime, detector)) {
result[IS_INIT_OVERTIME_FIELD] = true;
result[INIT_DETAILS_FIELD] = getInitOverTimeDetails(detector);
}
return result;
};

const isDetectorInitOverTime = (currentTime: Moment, detector: Detector) => {
return (
detector &&
detector.curState === DETECTOR_STATE.INIT &&
detector.initializationError &&
!detector.initializationError.includes(NO_RCF_MODEL_ERROR_MESSAGE) &&
//@ts-ignore
currentTime
.subtract(
SHINGLE_SIZE * detector.detectionInterval.period.interval,
detector.detectionInterval.period.unit.toLowerCase()
)
//@ts-ignore
.valueOf() > detector.enabledTime
);
};

const getInitOverTimeDetails = (detector: Detector) => {
let result = {
[INIT_ERROR_MESSAGE_FIELD]: '',
[INIT_ACTION_ITEM_FIELD]: '',
};
if (!detector.initializationError) {
return result;
}
if (detector.initializationError.includes(NO_FULL_SHINGLE_ERROR_MESSAGE)) {
result[INIT_ERROR_MESSAGE_FIELD] = 'collected data is insufficient';
result[INIT_ACTION_ITEM_FIELD] =
DETECTOR_INIT_FAILURES.NO_TRAINING_DATA.actionItem;
} else if (
detector.initializationError.includes(NO_DATA_IN_WINDOW_ERROR_MESSAGE)
) {
result[INIT_ERROR_MESSAGE_FIELD] = 'no data exists in current time window';
result[INIT_ACTION_ITEM_FIELD] =
'Make sure data exists in data source index in current time window.';
}
return result;
};
3 changes: 3 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ export const MAX_FEATURE_NUM = 5;
export const MAX_FEATURE_NAME_SIZE = 64;

export const NAME_REGEX = RegExp('^[a-zA-Z0-9._-]+$');

//https://github.com/opendistro-for-elasticsearch/anomaly-detection/blob/master/src/main/java/com/amazon/opendistroforelasticsearch/ad/settings/AnomalyDetectorSettings.java#L186
export const SHINGLE_SIZE = 8;

0 comments on commit 8886443

Please sign in to comment.