Skip to content

Commit

Permalink
[APM] Add transaction error rate alert (#76933) (#77824)
Browse files Browse the repository at this point in the history
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
sorenlouv and elasticmachine authored Sep 18, 2020
1 parent 668316b commit 5bcc433
Show file tree
Hide file tree
Showing 26 changed files with 726 additions and 438 deletions.
86 changes: 31 additions & 55 deletions x-pack/plugins/apm/common/alert_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,82 +7,58 @@
import { i18n } from '@kbn/i18n';

export enum AlertType {
ErrorRate = 'apm.error_rate',
ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat.
TransactionErrorRate = 'apm.transaction_error_rate',
TransactionDuration = 'apm.transaction_duration',
TransactionDurationAnomaly = 'apm.transaction_duration_anomaly',
}

const THRESHOLD_MET_GROUP = {
id: 'threshold_met',
name: i18n.translate('xpack.apm.a.thresholdMet', {
defaultMessage: 'Threshold met',
}),
};

export const ALERT_TYPES_CONFIG = {
[AlertType.ErrorRate]: {
name: i18n.translate('xpack.apm.errorRateAlert.name', {
defaultMessage: 'Error rate',
[AlertType.ErrorCount]: {
name: i18n.translate('xpack.apm.errorCountAlert.name', {
defaultMessage: 'Error count threshold',
}),
actionGroups: [
{
id: 'threshold_met',
name: i18n.translate('xpack.apm.errorRateAlert.thresholdMet', {
defaultMessage: 'Threshold met',
}),
},
],
actionGroups: [THRESHOLD_MET_GROUP],
defaultActionGroupId: 'threshold_met',
producer: 'apm',
},
[AlertType.TransactionDuration]: {
name: i18n.translate('xpack.apm.transactionDurationAlert.name', {
defaultMessage: 'Transaction duration',
defaultMessage: 'Transaction duration threshold',
}),
actionGroups: [
{
id: 'threshold_met',
name: i18n.translate(
'xpack.apm.transactionDurationAlert.thresholdMet',
{
defaultMessage: 'Threshold met',
}
),
},
],
actionGroups: [THRESHOLD_MET_GROUP],
defaultActionGroupId: 'threshold_met',
producer: 'apm',
},
[AlertType.TransactionDurationAnomaly]: {
name: i18n.translate('xpack.apm.transactionDurationAnomalyAlert.name', {
defaultMessage: 'Transaction duration anomaly',
}),
actionGroups: [
{
id: 'threshold_met',
name: i18n.translate(
'xpack.apm.transactionDurationAlert.thresholdMet',
{
defaultMessage: 'Threshold met',
}
),
},
],
actionGroups: [THRESHOLD_MET_GROUP],
defaultActionGroupId: 'threshold_met',
producer: 'apm',
},
[AlertType.TransactionErrorRate]: {
name: i18n.translate('xpack.apm.transactionErrorRateAlert.name', {
defaultMessage: 'Transaction error rate threshold',
}),
actionGroups: [THRESHOLD_MET_GROUP],
defaultActionGroupId: 'threshold_met',
producer: 'apm',
},
};

export const TRANSACTION_ALERT_AGGREGATION_TYPES = {
avg: i18n.translate(
'xpack.apm.transactionDurationAlert.aggregationType.avg',
{
defaultMessage: 'Average',
}
),
'95th': i18n.translate(
'xpack.apm.transactionDurationAlert.aggregationType.95th',
{
defaultMessage: '95th percentile',
}
),
'99th': i18n.translate(
'xpack.apm.transactionDurationAlert.aggregationType.99th',
{
defaultMessage: '99th percentile',
}
),
};
// Server side registrations
// x-pack/plugins/apm/server/lib/alerts/<alert>.ts
// x-pack/plugins/apm/server/lib/alerts/register_apm_alerts.ts

// Client side registrations:
// x-pack/plugins/apm/public/components/alerting/<alert>/index.tsx
// x-pack/plugins/apm/public/components/alerting/register_apm_alerts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

import { storiesOf } from '@storybook/react';
import React from 'react';
import { ErrorRateAlertTrigger } from '.';
import { ErrorCountAlertTrigger } from '.';
import { ApmPluginContextValue } from '../../../context/ApmPluginContext';
import {
mockApmPluginContextValue,
MockApmPluginContextWrapper,
} from '../../../context/ApmPluginContext/MockApmPluginContext';

storiesOf('app/ErrorRateAlertTrigger', module).add(
storiesOf('app/ErrorCountAlertTrigger', module).add(
'example',
() => {
const params = {
Expand All @@ -26,7 +26,7 @@ storiesOf('app/ErrorRateAlertTrigger', module).add(
value={(mockApmPluginContextValue as unknown) as ApmPluginContextValue}
>
<div style={{ width: 400 }}>
<ErrorRateAlertTrigger
<ErrorCountAlertTrigger
alertParams={params as any}
setAlertParams={() => undefined}
setAlertProperty={() => undefined}
Expand All @@ -37,7 +37,7 @@ storiesOf('app/ErrorRateAlertTrigger', module).add(
},
{
info: {
propTablesExclude: [ErrorRateAlertTrigger, MockApmPluginContextWrapper],
propTablesExclude: [ErrorCountAlertTrigger, MockApmPluginContextWrapper],
source: false,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,33 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiFieldNumber, EuiSelect } from '@elastic/eui';

import { i18n } from '@kbn/i18n';
import { isFinite } from 'lodash';
import React from 'react';
import { useParams } from 'react-router-dom';
import { ForLastExpression } from '../../../../../triggers_actions_ui/public';
import { ALERT_TYPES_CONFIG } from '../../../../common/alert_types';
import {
ENVIRONMENT_ALL,
getEnvironmentLabel,
} from '../../../../common/environment_filter_values';
import { ALERT_TYPES_CONFIG, AlertType } from '../../../../common/alert_types';
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
import { useEnvironments } from '../../../hooks/useEnvironments';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { EnvironmentField, ServiceField, IsAboveField } from '../fields';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { PopoverExpression } from '../ServiceAlertTrigger/PopoverExpression';

export interface ErrorRateAlertTriggerParams {
export interface AlertParams {
windowSize: number;
windowUnit: string;
threshold: number;
serviceName: string;
environment: string;
}

interface Props {
alertParams: ErrorRateAlertTriggerParams;
alertParams: AlertParams;
setAlertParams: (key: string, value: any) => void;
setAlertProperty: (key: string, value: any) => void;
}

export function ErrorRateAlertTrigger(props: Props) {
export function ErrorCountAlertTrigger(props: Props) {
const { setAlertParams, setAlertProperty, alertParams } = props;
const { serviceName } = useParams<{ serviceName?: string }>();
const { urlParams } = useUrlParams();
Expand All @@ -51,45 +48,20 @@ export function ErrorRateAlertTrigger(props: Props) {
...alertParams,
};

const threshold = isFinite(params.threshold) ? params.threshold : '';

const fields = [
<PopoverExpression
value={getEnvironmentLabel(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',
<ServiceField value={serviceName} />,
<EnvironmentField
currentValue={params.environment}
options={environmentOptions}
onChange={(e) => setAlertParams('environment', e.target.value)}
/>,
<IsAboveField
value={params.threshold}
unit={i18n.translate('xpack.apm.errorCountAlertTrigger.errors', {
defaultMessage: ' errors',
})}
value={threshold.toString()}
>
<EuiFieldNumber
value={threshold}
step={0}
onChange={(e) =>
setAlertParams('threshold', parseInt(e.target.value, 10))
}
compressed
append={i18n.translate('xpack.apm.errorRateAlertTrigger.errors', {
defaultMessage: 'errors',
})}
/>
</PopoverExpression>,
onChange={(value) => setAlertParams('threshold', value)}
/>,
<ForLastExpression
onChangeWindowSize={(windowSize) =>
setAlertParams('windowSize', windowSize || '')
Expand All @@ -108,7 +80,7 @@ export function ErrorRateAlertTrigger(props: Props) {

return (
<ServiceAlertTrigger
alertTypeName={ALERT_TYPES_CONFIG['apm.error_rate'].name}
alertTypeName={ALERT_TYPES_CONFIG[AlertType.ErrorCount].name}
defaults={defaults}
fields={fields}
setAlertParams={setAlertParams}
Expand All @@ -120,4 +92,4 @@ export function ErrorRateAlertTrigger(props: Props) {
// Default export is required for React.lazy loading
//
// eslint-disable-next-line import/no-default-export
export default ErrorRateAlertTrigger;
export default ErrorCountAlertTrigger;
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ interface Props {

export function PopoverExpression(props: Props) {
const { title, value, children } = props;

const [popoverOpen, setPopoverOpen] = useState(false);

return (
Expand Down
Loading

0 comments on commit 5bcc433

Please sign in to comment.