Skip to content

Commit 2ffcb6e

Browse files
committed
Merge remote-tracking branch 'origin/master' into create-engine-view
2 parents 3313354 + 5f8de69 commit 2ffcb6e

File tree

45 files changed

+823
-36
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+823
-36
lines changed

docs/user/alerting/alert-types.asciidoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,13 @@ image::images/alert-types-es-query-select.png[Choosing an ES query alert type]
130130
[float]
131131
==== Defining the conditions
132132

133-
The ES query alert has 4 clauses that define the condition to detect.
133+
The ES query alert has 5 clauses that define the condition to detect.
134134

135135
[role="screenshot"]
136136
image::images/alert-types-es-query-conditions.png[Four clauses define the condition to detect]
137137

138138
Index:: This clause requires an *index or index pattern* and a *time field* that will be used for the *time window*.
139+
Size:: This clause specifies the number of documents to pass to the configured actions when the the threshold condition is met.
139140
ES query:: This clause specifies the ES DSL query to execute. The number of documents that match this query will be evaulated against the threshold
140141
condition. Aggregations are not supported at this time.
141142
Threshold:: This clause defines a threshold value and a comparison operator (`is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The number of documents that match the specified query is compared to this threshold.
10.2 KB
Loading

x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_hosts_anomalies.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const getMetricsHostsAnomaliesRequestPayloadRT = rt.type({
6262
rt.type({
6363
// the ID of the source configuration
6464
sourceId: rt.string,
65+
anomalyThreshold: rt.number,
6566
// the time range to fetch the log entry anomalies from
6667
timeRange: timeRangeRT,
6768
}),

x-pack/plugins/infra/common/http_api/infra_ml/results/metrics_k8s_anomalies.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export const getMetricsK8sAnomaliesRequestPayloadRT = rt.type({
6262
rt.type({
6363
// the ID of the source configuration
6464
sourceId: rt.string,
65+
anomalyThreshold: rt.number,
6566
// the time range to fetch the log entry anomalies from
6667
timeRange: timeRangeRT,
6768
}),

x-pack/plugins/infra/common/http_api/source_api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export const SavedSourceConfigurationRuntimeType = rt.partial({
9090
metricsExplorerDefaultView: rt.string,
9191
fields: SavedSourceConfigurationFieldsRuntimeType,
9292
logColumns: rt.array(SavedSourceConfigurationColumnRuntimeType),
93+
anomalyThreshold: rt.number,
9394
});
9495

9596
export interface InfraSavedSourceConfiguration
@@ -107,6 +108,7 @@ export const pickSavedSourceConfiguration = (
107108
inventoryDefaultView,
108109
metricsExplorerDefaultView,
109110
logColumns,
111+
anomalyThreshold,
110112
} = value;
111113
const { container, host, pod, tiebreaker, timestamp } = fields;
112114

@@ -119,6 +121,7 @@ export const pickSavedSourceConfiguration = (
119121
metricsExplorerDefaultView,
120122
fields: { container, host, pod, tiebreaker, timestamp },
121123
logColumns,
124+
anomalyThreshold,
122125
};
123126
};
124127

@@ -140,6 +143,7 @@ export const StaticSourceConfigurationRuntimeType = rt.partial({
140143
metricsExplorerDefaultView: rt.string,
141144
fields: StaticSourceConfigurationFieldsRuntimeType,
142145
logColumns: rt.array(SavedSourceConfigurationColumnRuntimeType),
146+
anomalyThreshold: rt.number,
143147
});
144148

145149
export interface InfraStaticSourceConfiguration

x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ describe('ExpressionChart', () => {
6464
pod: 'kubernetes.pod.uid',
6565
tiebreaker: '_doc',
6666
},
67+
anomalyThreshold: 20,
6768
},
6869
};
6970

x-pack/plugins/infra/public/components/source_configuration/indices_configuration_form_state.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
import { ReactNode, useCallback, useMemo, useState } from 'react';
99

10-
import { createInputFieldProps, validateInputFieldNotEmpty } from './input_fields';
10+
import {
11+
createInputFieldProps,
12+
createInputRangeFieldProps,
13+
validateInputFieldNotEmpty,
14+
} from './input_fields';
1115

1216
interface FormState {
1317
name: string;
@@ -20,6 +24,7 @@ interface FormState {
2024
podField: string;
2125
tiebreakerField: string;
2226
timestampField: string;
27+
anomalyThreshold: number;
2328
}
2429

2530
type FormStateChanges = Partial<FormState>;
@@ -124,6 +129,17 @@ export const useIndicesConfigurationFormState = ({
124129
}),
125130
[formState.timestampField]
126131
);
132+
const anomalyThresholdFieldProps = useMemo(
133+
() =>
134+
createInputRangeFieldProps({
135+
errors: validateInputFieldNotEmpty(formState.anomalyThreshold),
136+
name: 'anomalyThreshold',
137+
onChange: (anomalyThreshold) =>
138+
setFormStateChanges((changes) => ({ ...changes, anomalyThreshold })),
139+
value: formState.anomalyThreshold,
140+
}),
141+
[formState.anomalyThreshold]
142+
);
127143

128144
const fieldProps = useMemo(
129145
() => ({
@@ -135,6 +151,7 @@ export const useIndicesConfigurationFormState = ({
135151
podField: podFieldFieldProps,
136152
tiebreakerField: tiebreakerFieldFieldProps,
137153
timestampField: timestampFieldFieldProps,
154+
anomalyThreshold: anomalyThresholdFieldProps,
138155
}),
139156
[
140157
nameFieldProps,
@@ -145,6 +162,7 @@ export const useIndicesConfigurationFormState = ({
145162
podFieldFieldProps,
146163
tiebreakerFieldFieldProps,
147164
timestampFieldFieldProps,
165+
anomalyThresholdFieldProps,
148166
]
149167
);
150168

@@ -183,4 +201,5 @@ const defaultFormState: FormState = {
183201
podField: '',
184202
tiebreakerField: '',
185203
timestampField: '',
204+
anomalyThreshold: 0,
186205
};

x-pack/plugins/infra/public/components/source_configuration/input_fields.tsx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* 2.0.
66
*/
77

8-
import React from 'react';
8+
import React, { ReactText } from 'react';
99

1010
import { FormattedMessage } from '@kbn/i18n/react';
1111

@@ -43,7 +43,47 @@ export const createInputFieldProps = <
4343
value,
4444
});
4545

46-
export const validateInputFieldNotEmpty = (value: string) =>
46+
export interface InputRangeFieldProps<
47+
Value extends ReactText = ReactText,
48+
FieldElement extends HTMLInputElement = HTMLInputElement,
49+
ButtonElement extends HTMLButtonElement = HTMLButtonElement
50+
> {
51+
error: React.ReactNode[];
52+
isInvalid: boolean;
53+
name: string;
54+
onChange?: (
55+
evt: React.ChangeEvent<FieldElement> | React.MouseEvent<ButtonElement>,
56+
isValid: boolean
57+
) => void;
58+
value: Value;
59+
}
60+
61+
export const createInputRangeFieldProps = <
62+
Value extends ReactText = ReactText,
63+
FieldElement extends HTMLInputElement = HTMLInputElement,
64+
ButtonElement extends HTMLButtonElement = HTMLButtonElement
65+
>({
66+
errors,
67+
name,
68+
onChange,
69+
value,
70+
}: {
71+
errors: FieldErrorMessage[];
72+
name: string;
73+
onChange: (newValue: number, isValid: boolean) => void;
74+
value: Value;
75+
}): InputRangeFieldProps<Value, FieldElement, ButtonElement> => ({
76+
error: errors,
77+
isInvalid: errors.length > 0,
78+
name,
79+
onChange: (
80+
evt: React.ChangeEvent<FieldElement> | React.MouseEvent<ButtonElement>,
81+
isValid: boolean
82+
) => onChange(+evt.currentTarget.value, isValid),
83+
value,
84+
});
85+
86+
export const validateInputFieldNotEmpty = (value: React.ReactText) =>
4787
value === ''
4888
? [
4989
<FormattedMessage
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { EuiTitle } from '@elastic/eui';
9+
import { EuiSpacer } from '@elastic/eui';
10+
import { EuiFormRow } from '@elastic/eui';
11+
import { EuiRange } from '@elastic/eui';
12+
import { EuiDescribedFormGroup } from '@elastic/eui';
13+
import { EuiForm } from '@elastic/eui';
14+
import React from 'react';
15+
import { FormattedMessage } from 'react-intl';
16+
import { InputRangeFieldProps } from './input_fields';
17+
18+
interface MLConfigurationPanelProps {
19+
isLoading: boolean;
20+
readOnly: boolean;
21+
anomalyThresholdFieldProps: InputRangeFieldProps;
22+
}
23+
24+
export const MLConfigurationPanel = ({
25+
isLoading,
26+
readOnly,
27+
anomalyThresholdFieldProps,
28+
}: MLConfigurationPanelProps) => {
29+
return (
30+
<EuiForm>
31+
<EuiTitle size="s">
32+
<h3>
33+
<FormattedMessage
34+
id="xpack.infra.sourceConfiguration.mlSectionTitle"
35+
defaultMessage="Machine Learning"
36+
/>
37+
</h3>
38+
</EuiTitle>
39+
<EuiSpacer size="m" />
40+
<EuiDescribedFormGroup
41+
title={
42+
<h4>
43+
<FormattedMessage
44+
id="xpack.infra.sourceConfiguration.anomalyThresholdTitle"
45+
defaultMessage="Anomaly Severity Threshold"
46+
/>
47+
</h4>
48+
}
49+
description={
50+
<FormattedMessage
51+
id="xpack.infra.sourceConfiguration.anomalyThresholdDescription"
52+
defaultMessage="Sets the minimum severity score required to show anomalies in the Metrics application."
53+
/>
54+
}
55+
>
56+
<EuiFormRow
57+
error={anomalyThresholdFieldProps.error}
58+
fullWidth
59+
isInvalid={anomalyThresholdFieldProps.isInvalid}
60+
label={
61+
<FormattedMessage
62+
id="xpack.infra.sourceConfiguration.anomalyThresholdLabel"
63+
defaultMessage="Minimum severity score"
64+
/>
65+
}
66+
>
67+
<EuiRange
68+
min={0}
69+
max={100}
70+
data-test-subj="anomalyThresholdInput"
71+
showInput
72+
showTicks
73+
showRange
74+
tickInterval={20}
75+
aria-label="Minimum severity score"
76+
disabled={isLoading}
77+
readOnly={readOnly}
78+
isLoading={isLoading}
79+
{...anomalyThresholdFieldProps}
80+
/>
81+
</EuiFormRow>
82+
</EuiDescribedFormGroup>
83+
</EuiForm>
84+
);
85+
};

x-pack/plugins/infra/public/components/source_configuration/source_configuration_form_state.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi
2727
podField: configuration.fields.pod,
2828
tiebreakerField: configuration.fields.tiebreaker,
2929
timestampField: configuration.fields.timestamp,
30+
anomalyThreshold: configuration.anomalyThreshold,
3031
}
3132
: undefined,
3233
[configuration]
@@ -79,6 +80,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi
7980
timestamp: indicesConfigurationFormState.formState.timestampField,
8081
},
8182
logColumns: logColumnsConfigurationFormState.formState.logColumns,
83+
anomalyThreshold: indicesConfigurationFormState.formState.anomalyThreshold,
8284
}),
8385
[indicesConfigurationFormState.formState, logColumnsConfigurationFormState.formState]
8486
);
@@ -97,6 +99,7 @@ export const useSourceConfigurationFormState = (configuration?: InfraSourceConfi
9799
timestamp: indicesConfigurationFormState.formStateChanges.timestampField,
98100
},
99101
logColumns: logColumnsConfigurationFormState.formStateChanges.logColumns,
102+
anomalyThreshold: indicesConfigurationFormState.formStateChanges.anomalyThreshold,
100103
}),
101104
[
102105
indicesConfigurationFormState.formStateChanges,

0 commit comments

Comments
 (0)