[APM] Scope APM alert creation to environment (#65681)

* adding environment to alerting

* fixing translations

* addressing pr comments

* addressing PR comments

* addressing PR comments

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Cauê Marcondes 2020-05-13 09:37:56 +01:00 committed by GitHub
parent 577bf0928b
commit 9a13779c4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 174 additions and 53 deletions

View file

@ -17,14 +17,15 @@ interface Props {
export function AlertingFlyout(props: Props) {
const { addFlyoutVisible, setAddFlyoutVisibility, alertType } = props;
return alertType ? (
<AlertAdd
addFlyoutVisible={addFlyoutVisible}
setAddFlyoutVisibility={setAddFlyoutVisibility}
consumer="apm"
alertTypeId={alertType}
canChangeTrigger={false}
/>
) : null;
return (
alertType && (
<AlertAdd
addFlyoutVisible={addFlyoutVisible}
setAddFlyoutVisibility={setAddFlyoutVisibility}
consumer="apm"
alertTypeId={alertType}
canChangeTrigger={false}
/>
)
);
}

View file

@ -7,7 +7,6 @@
import { EuiSelect } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useFetcher } from '../../../hooks/useFetcher';
import { useLocation } from '../../../hooks/useLocation';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { history } from '../../../utils/history';
@ -16,6 +15,7 @@ import {
ENVIRONMENT_ALL,
ENVIRONMENT_NOT_DEFINED
} from '../../../../common/environment_filter_values';
import { useEnvironments, ALL_OPTION } from '../../../hooks/useEnvironments';
function updateEnvironmentUrl(
location: ReturnType<typeof useLocation>,
@ -32,13 +32,6 @@ function updateEnvironmentUrl(
});
}
const ALL_OPTION = {
value: ENVIRONMENT_ALL,
text: i18n.translate('xpack.apm.filter.environment.allLabel', {
defaultMessage: 'All'
})
};
const NOT_DEFINED_OPTION = {
value: ENVIRONMENT_NOT_DEFINED,
text: i18n.translate('xpack.apm.filter.environment.notDefinedLabel', {
@ -74,27 +67,15 @@ function getOptions(environments: string[]) {
export const EnvironmentFilter: React.FC = () => {
const location = useLocation();
const { urlParams, uiFilters } = useUrlParams();
const { start, end, serviceName } = urlParams;
const { uiFilters, urlParams } = useUrlParams();
const { environment } = uiFilters;
const { data: environments = [], status = 'loading' } = useFetcher(
callApmApi => {
if (start && end) {
return callApmApi({
pathname: '/api/apm/ui_filters/environments',
params: {
query: {
start,
end,
serviceName
}
}
});
}
},
[start, end, serviceName]
);
const { serviceName, start, end } = urlParams;
const { environments, status = 'loading' } = useEnvironments({
serviceName,
start,
end
});
return (
<EuiSelect

View file

@ -7,15 +7,19 @@ import React from 'react';
import { EuiFieldNumber } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { isFinite } from 'lodash';
import { EuiSelect } from '@elastic/eui';
import { ForLastExpression } from '../../../../../triggers_actions_ui/public';
import { ALERT_TYPES_CONFIG } from '../../../../common/alert_types';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { PopoverExpression } from '../ServiceAlertTrigger/PopoverExpression';
import { useEnvironments, ALL_OPTION } from '../../../hooks/useEnvironments';
import { useUrlParams } from '../../../hooks/useUrlParams';
export interface ErrorRateAlertTriggerParams {
windowSize: number;
windowUnit: string;
threshold: number;
environment: string;
}
interface Props {
@ -27,10 +31,15 @@ interface Props {
export function ErrorRateAlertTrigger(props: Props) {
const { setAlertParams, setAlertProperty, alertParams } = props;
const { urlParams } = useUrlParams();
const { serviceName, start, end } = urlParams;
const { environmentOptions } = useEnvironments({ serviceName, start, end });
const defaults = {
threshold: 25,
windowSize: 1,
windowUnit: 'm'
windowUnit: 'm',
environment: ALL_OPTION.value
};
const params = {
@ -41,6 +50,28 @@ export function ErrorRateAlertTrigger(props: Props) {
const threshold = isFinite(params.threshold) ? params.threshold : '';
const fields = [
<PopoverExpression
value={
params.environment === ALL_OPTION.value
? ALL_OPTION.text
: params.environment
}
title={i18n.translate('xpack.apm.errorRateAlertTrigger.environment', {
defaultMessage: 'Environment'
})}
>
<EuiSelect
value={params.environment}
options={environmentOptions}
onChange={e =>
setAlertParams(
'environment',
e.target.value as ErrorRateAlertTriggerParams['environment']
)
}
compressed
/>
</PopoverExpression>,
<PopoverExpression
title={i18n.translate('xpack.apm.errorRateAlertTrigger.isAbove', {
defaultMessage: 'is above'

View file

@ -3,18 +3,19 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { map } from 'lodash';
import { EuiFieldNumber, EuiSelect } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { map } from 'lodash';
import React from 'react';
import { ForLastExpression } from '../../../../../triggers_actions_ui/public';
import {
TRANSACTION_ALERT_AGGREGATION_TYPES,
ALERT_TYPES_CONFIG
ALERT_TYPES_CONFIG,
TRANSACTION_ALERT_AGGREGATION_TYPES
} from '../../../../common/alert_types';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { ALL_OPTION, useEnvironments } from '../../../hooks/useEnvironments';
import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { PopoverExpression } from '../ServiceAlertTrigger/PopoverExpression';
interface Params {
@ -24,6 +25,7 @@ interface Params {
aggregationType: 'avg' | '95th' | '99th';
serviceName: string;
transactionType: string;
environment: string;
}
interface Props {
@ -39,6 +41,9 @@ export function TransactionDurationAlertTrigger(props: Props) {
const transactionTypes = useServiceTransactionTypes(urlParams);
const { serviceName, start, end } = urlParams;
const { environmentOptions } = useEnvironments({ serviceName, start, end });
if (!transactionTypes.length) {
return null;
}
@ -48,7 +53,8 @@ export function TransactionDurationAlertTrigger(props: Props) {
aggregationType: 'avg',
windowSize: 5,
windowUnit: 'm',
transactionType: transactionTypes[0]
transactionType: transactionTypes[0],
environment: ALL_OPTION.value
};
const params = {
@ -57,6 +63,28 @@ export function TransactionDurationAlertTrigger(props: Props) {
};
const fields = [
<PopoverExpression
value={
params.environment === ALL_OPTION.value
? ALL_OPTION.text
: params.environment
}
title={i18n.translate(
'xpack.apm.transactionDurationAlertTrigger.environment',
{
defaultMessage: 'Environment'
}
)}
>
<EuiSelect
value={params.environment}
options={environmentOptions}
onChange={e =>
setAlertParams('environment', e.target.value as Params['environment'])
}
compressed
/>
</PopoverExpression>,
<PopoverExpression
value={params.transactionType}
title={i18n.translate('xpack.apm.transactionDurationAlertTrigger.type', {

View file

@ -0,0 +1,64 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { useFetcher } from './useFetcher';
import {
ENVIRONMENT_NOT_DEFINED,
ENVIRONMENT_ALL
} from '../../common/environment_filter_values';
import { callApmApi } from '../services/rest/createCallApmApi';
export const ALL_OPTION = {
value: ENVIRONMENT_ALL,
text: i18n.translate('xpack.apm.environment.allLabel', {
defaultMessage: 'All'
})
};
function getEnvironmentOptions(environments: string[]) {
const environmentOptions = environments
.filter(env => env !== ENVIRONMENT_NOT_DEFINED)
.map(environment => ({
value: environment,
text: environment
}));
return [ALL_OPTION, ...environmentOptions];
}
export function useEnvironments({
serviceName,
start,
end
}: {
serviceName?: string;
start?: string;
end?: string;
}) {
const { data: environments = [], status = 'loading' } = useFetcher(() => {
if (start && end) {
return callApmApi({
pathname: '/api/apm/ui_filters/environments',
params: {
query: {
start,
end,
serviceName
}
}
});
}
}, [start, end, serviceName]);
const environmentOptions = useMemo(
() => getEnvironmentOptions(environments),
[environments]
);
return { environments, status, environmentOptions };
}

View file

@ -8,6 +8,7 @@ import { schema, TypeOf } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';
import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import {
ESSearchResponse,
@ -15,7 +16,8 @@ import {
} from '../../../typings/elasticsearch';
import {
PROCESSOR_EVENT,
SERVICE_NAME
SERVICE_NAME,
SERVICE_ENVIRONMENT
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerting/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
@ -30,7 +32,8 @@ const paramsSchema = schema.object({
serviceName: schema.string(),
windowSize: schema.number(),
windowUnit: schema.string(),
threshold: schema.number()
threshold: schema.number(),
environment: schema.string()
});
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.ErrorRate];
@ -71,6 +74,11 @@ export function registerErrorRateAlertType({
savedObjectsClient: services.savedObjectsClient
});
const environmentTerm =
alertParams.environment === ENVIRONMENT_ALL
? []
: [{ term: { [SERVICE_ENVIRONMENT]: alertParams.environment } }];
const searchParams = {
index: indices['apm_oss.errorIndices'],
size: 0,
@ -94,7 +102,8 @@ export function registerErrorRateAlertType({
term: {
[SERVICE_NAME]: alertParams.serviceName
}
}
},
...environmentTerm
]
}
},

View file

@ -8,13 +8,15 @@ import { schema, TypeOf } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';
import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import { ESSearchResponse } from '../../../typings/elasticsearch';
import {
PROCESSOR_EVENT,
SERVICE_NAME,
TRANSACTION_TYPE,
TRANSACTION_DURATION
TRANSACTION_DURATION,
SERVICE_ENVIRONMENT
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerting/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
@ -35,7 +37,8 @@ const paramsSchema = schema.object({
schema.literal('avg'),
schema.literal('95th'),
schema.literal('99th')
])
]),
environment: schema.string()
});
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.TransactionDuration];
@ -85,6 +88,11 @@ export function registerTransactionDurationAlertType({
savedObjectsClient: services.savedObjectsClient
});
const environmentTerm =
alertParams.environment === ENVIRONMENT_ALL
? []
: [{ term: { [SERVICE_ENVIRONMENT]: alertParams.environment } }];
const searchParams = {
index: indices['apm_oss.transactionIndices'],
size: 0,
@ -113,7 +121,8 @@ export function registerTransactionDurationAlertType({
term: {
[TRANSACTION_TYPE]: alertParams.transactionType
}
}
},
...environmentTerm
]
}
},

View file

@ -4214,7 +4214,6 @@
"xpack.apm.fetcher.error.status": "エラー",
"xpack.apm.fetcher.error.title": "リソースの取得中にエラーが発生しました",
"xpack.apm.fetcher.error.url": "URL",
"xpack.apm.filter.environment.allLabel": "すべて",
"xpack.apm.filter.environment.label": "環境",
"xpack.apm.filter.environment.notDefinedLabel": "未定義",
"xpack.apm.filter.environment.selectEnvironmentLabel": "環境を選択",

View file

@ -4215,7 +4215,6 @@
"xpack.apm.fetcher.error.status": "错误",
"xpack.apm.fetcher.error.title": "提取资源时出错",
"xpack.apm.fetcher.error.url": "URL",
"xpack.apm.filter.environment.allLabel": "全部",
"xpack.apm.filter.environment.label": "环境",
"xpack.apm.filter.environment.notDefinedLabel": "未定义",
"xpack.apm.filter.environment.selectEnvironmentLabel": "选择环境",