[ML] advanced settings validators

This commit is contained in:
Dima Arnautov 2021-04-15 10:20:43 +02:00
parent 75de64f3c3
commit 8dc6d5b6ca
5 changed files with 25 additions and 13 deletions

View file

@ -8,20 +8,31 @@
import { CombinedJobWithStats } from '../types/anomaly_detection_jobs';
import { resolveMaxTimeInterval } from './job_utils';
import { isDefined } from '../types/guards';
import { parseInterval } from './parse_interval';
const narrowBucketLength = 60;
/**
* Resolved the lookback interval for the rule
* using the formula max(2m, 2 * bucket_span) + query_delay + 1s
*/
export function getLookbackInterval(jobs: CombinedJobWithStats[]): number {
const narrowBucketLength = 60;
const bucketSpanInSeconds = Math.round(
const bucketSpanInSeconds = Math.ceil(
resolveMaxTimeInterval(jobs.map((v) => v.analysis_config.bucket_span)) ?? 0
);
const queryDelayInSeconds = Math.round(
const queryDelayInSeconds = Math.ceil(
resolveMaxTimeInterval(jobs.map((v) => v.datafeed_config.query_delay).filter(isDefined)) ?? 0
);
return Math.max(2 * narrowBucketLength, 2 * bucketSpanInSeconds) + queryDelayInSeconds + 1;
}
export function getTopNBuckets(job: CombinedJobWithStats): number {
const bucketSpan = parseInterval(job.analysis_config.bucket_span);
if (bucketSpan === null) {
throw new Error('Unable to resolve a bucket span length');
}
return Math.ceil(narrowBucketLength / bucketSpan.asSeconds());
}

View file

@ -86,6 +86,10 @@ export function memoryInputValidator(allowedUnits = ALLOWED_DATA_UNITS) {
export function timeIntervalInputValidator() {
return (value: string) => {
if (value === '') {
return null;
}
const r = parseInterval(value);
if (r === null) {
return {

View file

@ -27,7 +27,7 @@ import { InterimResultsControl } from './interim_results_control';
import { ConfigValidator } from './config_validator';
import { CombinedJobWithStats } from '../../common/types/anomaly_detection_jobs';
import { AdvancedSettings } from './advanced_settings';
import { getLookbackInterval } from '../../common/util/alerts';
import { getLookbackInterval, getTopNBuckets } from '../../common/util/alerts';
interface MlAnomalyAlertTriggerProps {
alertParams: MlAnomalyDetectionAlertParams;
@ -121,11 +121,11 @@ const MlAnomalyAlertTrigger: FC<MlAnomalyAlertTriggerProps> = ({
const advancedSettings = useMemo(() => {
let { lookbackInterval, topNBuckets } = alertParams;
if (lookbackInterval === undefined && jobConfigs.length > 0) {
if ((lookbackInterval === undefined || lookbackInterval === '') && jobConfigs.length > 0) {
lookbackInterval = `${getLookbackInterval(jobConfigs)}s`;
}
if (topNBuckets === undefined && jobConfigs.length > 0) {
topNBuckets = 1;
topNBuckets = getTopNBuckets(jobConfigs[0]);
}
return {
lookbackInterval,

View file

@ -67,7 +67,7 @@ export const SeverityControl: FC<SeveritySelectorProps> = React.memo(({ value, o
value={value ?? ANOMALY_THRESHOLD.LOW}
onChange={(e) => {
// @ts-ignore Property 'value' does not exist on type 'EventTarget' | (EventTarget & HTMLInputElement)
onChange(e.target.value);
onChange(Number(e.target.value));
}}
showLabels
showValue

View file

@ -9,7 +9,7 @@ import { EuiFieldText, EuiFormRow } from '@elastic/eui';
import React, { FC, ReactNode, useMemo } from 'react';
import { invalidTimeIntervalMessage } from '../application/jobs/new_job/common/job_validator/util';
import { composeValidators } from '../../common';
import { requiredValidator, timeIntervalInputValidator } from '../../common/util/validators';
import { timeIntervalInputValidator } from '../../common/util/validators';
interface TimeIntervalControlProps {
label: string | ReactNode;
@ -18,10 +18,7 @@ interface TimeIntervalControlProps {
}
export const TimeIntervalControl: FC<TimeIntervalControlProps> = ({ value, onChange, label }) => {
const validators = useMemo(
() => composeValidators(requiredValidator(), timeIntervalInputValidator()),
[]
);
const validators = useMemo(() => composeValidators(timeIntervalInputValidator()), []);
const validationErrors = useMemo(() => validators(value), [value]);