[APM] Add transaction error rate alert (#76933)

This commit is contained in:
Søren Louv-Jansen 2020-09-17 22:38:14 +02:00 committed by GitHub
parent becb137835
commit fb6292965b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 726 additions and 438 deletions

View file

@ -7,42 +7,33 @@
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',
},
@ -50,39 +41,24 @@ export const ALERT_TYPES_CONFIG = {
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

View file

@ -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 = {
@ -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}
@ -37,7 +37,7 @@ storiesOf('app/ErrorRateAlertTrigger', module).add(
},
{
info: {
propTablesExclude: [ErrorRateAlertTrigger, MockApmPluginContextWrapper],
propTablesExclude: [ErrorCountAlertTrigger, MockApmPluginContextWrapper],
source: false,
},
}

View file

@ -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();
@ -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',
<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',
})}
>
<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',
})}
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 || '')
@ -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}
@ -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;

View file

@ -15,7 +15,6 @@ interface Props {
export function PopoverExpression(props: Props) {
const { title, value, children } = props;
const [popoverOpen, setPopoverOpen] = useState(false);
return (

View file

@ -3,26 +3,27 @@
* 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 { EuiSelect } from '@elastic/eui';
import { useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { map } from 'lodash';
import React from 'react';
import { ForLastExpression } from '../../../../../triggers_actions_ui/public';
import {
ALERT_TYPES_CONFIG,
TRANSACTION_ALERT_AGGREGATION_TYPES,
} from '../../../../common/alert_types';
import { ALERT_TYPES_CONFIG } from '../../../../common/alert_types';
import { useEnvironments } from '../../../hooks/useEnvironments';
import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { PopoverExpression } from '../ServiceAlertTrigger/PopoverExpression';
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
import {
ENVIRONMENT_ALL,
getEnvironmentLabel,
} from '../../../../common/environment_filter_values';
EnvironmentField,
ServiceField,
TransactionTypeField,
IsAboveField,
} from '../fields';
interface Params {
interface AlertParams {
windowSize: number;
windowUnit: string;
threshold: number;
@ -32,23 +33,42 @@ interface Params {
environment: string;
}
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',
}
),
};
interface Props {
alertParams: Params;
alertParams: AlertParams;
setAlertParams: (key: string, value: any) => void;
setAlertProperty: (key: string, value: any) => void;
}
export function TransactionDurationAlertTrigger(props: Props) {
const { setAlertParams, alertParams, setAlertProperty } = props;
const { serviceName } = alertParams;
const { urlParams } = useUrlParams();
const transactionTypes = useServiceTransactionTypes(urlParams);
const { start, end } = urlParams;
const { serviceName } = useParams<{ serviceName?: string }>();
const { start, end, transactionType } = urlParams;
const { environmentOptions } = useEnvironments({ serviceName, start, end });
if (!transactionTypes.length) {
if (!transactionTypes.length || !serviceName) {
return null;
}
@ -57,7 +77,9 @@ export function TransactionDurationAlertTrigger(props: Props) {
aggregationType: 'avg',
windowSize: 5,
windowUnit: 'm',
transactionType: transactionTypes[0],
// use the current transaction type or default to the first in the list
transactionType: transactionType || transactionTypes[0],
environment: urlParams.environment || ENVIRONMENT_ALL.value,
};
@ -67,47 +89,17 @@ export function TransactionDurationAlertTrigger(props: Props) {
};
const fields = [
<PopoverExpression
value={getEnvironmentLabel(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', {
defaultMessage: 'Type',
})}
>
<EuiSelect
value={params.transactionType}
options={transactionTypes.map((key) => {
return {
text: key,
value: key,
};
})}
onChange={(e) =>
setAlertParams(
'transactionType',
e.target.value as Params['transactionType']
)
}
compressed
/>
</PopoverExpression>,
<ServiceField value={serviceName} />,
<EnvironmentField
currentValue={params.environment}
options={environmentOptions}
onChange={(e) => setAlertParams('environment', e.target.value)}
/>,
<TransactionTypeField
currentValue={params.transactionType}
options={transactionTypes.map((key) => ({ text: key, value: key }))}
onChange={(e) => setAlertParams('transactionType', e.target.value)}
/>,
<PopoverExpression
value={params.aggregationType}
title={i18n.translate('xpack.apm.transactionDurationAlertTrigger.when', {
@ -122,33 +114,17 @@ export function TransactionDurationAlertTrigger(props: Props) {
value: key,
};
})}
onChange={(e) =>
setAlertParams(
'aggregationType',
e.target.value as Params['aggregationType']
)
}
compressed
/>
</PopoverExpression>,
<PopoverExpression
value={params.threshold ? `${params.threshold}ms` : ''}
title={i18n.translate(
'xpack.apm.transactionDurationAlertTrigger.isAbove',
{
defaultMessage: 'is above',
}
)}
>
<EuiFieldNumber
value={params.threshold ?? ''}
onChange={(e) => setAlertParams('threshold', e.target.value)}
append={i18n.translate('xpack.apm.transactionDurationAlertTrigger.ms', {
defaultMessage: 'ms',
})}
onChange={(e) => setAlertParams('aggregationType', e.target.value)}
compressed
/>
</PopoverExpression>,
<IsAboveField
value={params.threshold}
unit={i18n.translate('xpack.apm.transactionDurationAlertTrigger.ms', {
defaultMessage: 'ms',
})}
onChange={(value) => setAlertParams('threshold', value)}
/>,
<ForLastExpression
onChangeWindowSize={(timeWindowSize) =>
setAlertParams('windowSize', timeWindowSize || '')

View file

@ -3,7 +3,8 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiExpression, EuiSelect } from '@elastic/eui';
import { useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { ALERT_TYPES_CONFIG } from '../../../../common/alert_types';
@ -16,14 +17,16 @@ import {
AnomalySeverity,
SelectAnomalySeverity,
} from './SelectAnomalySeverity';
import {
ENVIRONMENT_ALL,
getEnvironmentLabel,
} from '../../../../common/environment_filter_values';
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
import {
TRANSACTION_PAGE_LOAD,
TRANSACTION_REQUEST,
} from '../../../../common/transaction_types';
import {
EnvironmentField,
ServiceField,
TransactionTypeField,
} from '../fields';
interface Params {
windowSize: number;
@ -42,9 +45,9 @@ interface Props {
export function TransactionDurationAnomalyAlertTrigger(props: Props) {
const { setAlertParams, alertParams, setAlertProperty } = props;
const { serviceName } = alertParams;
const { urlParams } = useUrlParams();
const transactionTypes = useServiceTransactionTypes(urlParams);
const { serviceName } = useParams<{ serviceName?: string }>();
const { start, end } = urlParams;
const { environmentOptions } = useEnvironments({ serviceName, start, end });
const supportedTransactionTypes = transactionTypes.filter((transactionType) =>
@ -55,10 +58,13 @@ export function TransactionDurationAnomalyAlertTrigger(props: Props) {
return null;
}
// 'page-load' for RUM, 'request' otherwise
const transactionType = supportedTransactionTypes[0];
const defaults: Params = {
windowSize: 15,
windowUnit: 'm',
transactionType: supportedTransactionTypes[0], // 'page-load' for RUM, 'request' otherwise
transactionType,
serviceName,
environment: urlParams.environment || ENVIRONMENT_ALL.value,
anomalyScore: 75,
@ -70,31 +76,13 @@ export function TransactionDurationAnomalyAlertTrigger(props: Props) {
};
const fields = [
<EuiExpression
description={i18n.translate(
'xpack.apm.transactionDurationAnomalyAlertTrigger.service',
{
defaultMessage: 'Service',
}
)}
value={serviceName}
<ServiceField value={serviceName} />,
<TransactionTypeField currentValue={transactionType} />,
<EnvironmentField
currentValue={params.environment}
options={environmentOptions}
onChange={(e) => setAlertParams('environment', e.target.value)}
/>,
<PopoverExpression
value={getEnvironmentLabel(params.environment)}
title={i18n.translate(
'xpack.apm.transactionDurationAnomalyAlertTrigger.environment',
{
defaultMessage: 'Environment',
}
)}
>
<EuiSelect
value={params.environment}
options={environmentOptions}
onChange={(e) => setAlertParams('environment', e.target.value)}
compressed
/>
</PopoverExpression>,
<PopoverExpression
value={<AnomalySeverity severityScore={params.anomalyScore} />}
title={i18n.translate(

View file

@ -0,0 +1,110 @@
/*
* 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 { useParams } from 'react-router-dom';
import React from 'react';
import { ForLastExpression } from '../../../../../triggers_actions_ui/public';
import { ALERT_TYPES_CONFIG, AlertType } from '../../../../common/alert_types';
import { useEnvironments } from '../../../hooks/useEnvironments';
import { useServiceTransactionTypes } from '../../../hooks/useServiceTransactionTypes';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { ServiceAlertTrigger } from '../ServiceAlertTrigger';
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
import {
ServiceField,
TransactionTypeField,
EnvironmentField,
IsAboveField,
} from '../fields';
interface AlertParams {
windowSize: number;
windowUnit: string;
threshold: number;
serviceName: string;
transactionType: string;
environment: string;
}
interface Props {
alertParams: AlertParams;
setAlertParams: (key: string, value: any) => void;
setAlertProperty: (key: string, value: any) => void;
}
export function TransactionErrorRateAlertTrigger(props: Props) {
const { setAlertParams, alertParams, setAlertProperty } = props;
const { urlParams } = useUrlParams();
const transactionTypes = useServiceTransactionTypes(urlParams);
const { serviceName } = useParams<{ serviceName?: string }>();
const { start, end, transactionType } = urlParams;
const { environmentOptions } = useEnvironments({ serviceName, start, end });
if (!transactionTypes.length || !serviceName) {
return null;
}
const defaultParams = {
threshold: 30,
windowSize: 5,
windowUnit: 'm',
transactionType: transactionType || transactionTypes[0],
environment: urlParams.environment || ENVIRONMENT_ALL.value,
};
const params = {
...defaultParams,
...alertParams,
};
const fields = [
<ServiceField value={serviceName} />,
<EnvironmentField
currentValue={params.environment}
options={environmentOptions}
onChange={(e) => setAlertParams('environment', e.target.value)}
/>,
<TransactionTypeField
currentValue={params.transactionType}
options={transactionTypes.map((key) => ({ text: key, value: key }))}
onChange={(e) => setAlertParams('transactionType', e.target.value)}
/>,
<IsAboveField
value={params.threshold}
unit="%"
onChange={(value) => setAlertParams('threshold', value)}
/>,
<ForLastExpression
onChangeWindowSize={(timeWindowSize) =>
setAlertParams('windowSize', timeWindowSize || '')
}
onChangeWindowUnit={(timeWindowUnit) =>
setAlertParams('windowUnit', timeWindowUnit)
}
timeWindowSize={params.windowSize}
timeWindowUnit={params.windowUnit}
errors={{
timeWindowSize: [],
timeWindowUnit: [],
}}
/>,
];
return (
<ServiceAlertTrigger
alertTypeName={ALERT_TYPES_CONFIG[AlertType.TransactionErrorRate].name}
fields={fields}
defaults={defaultParams}
setAlertParams={setAlertParams}
setAlertProperty={setAlertProperty}
/>
);
}
// Default export is required for React.lazy loading
//
// eslint-disable-next-line import/no-default-export
export default TransactionErrorRateAlertTrigger;

View file

@ -0,0 +1,108 @@
/*
* 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 { EuiSelect, EuiExpression, EuiFieldNumber } from '@elastic/eui';
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiSelectOption } from '@elastic/eui';
import { getEnvironmentLabel } from '../../../common/environment_filter_values';
import { PopoverExpression } from './ServiceAlertTrigger/PopoverExpression';
export function ServiceField({ value }: { value?: string }) {
return (
<EuiExpression
description={i18n.translate('xpack.apm.alerting.fields.service', {
defaultMessage: 'Service',
})}
value={value}
/>
);
}
export function EnvironmentField({
currentValue,
options,
onChange,
}: {
currentValue: string;
options: EuiSelectOption[];
onChange: (event: React.ChangeEvent<HTMLSelectElement>) => void;
}) {
return (
<PopoverExpression
value={getEnvironmentLabel(currentValue)}
title={i18n.translate('xpack.apm.alerting.fields.environment', {
defaultMessage: 'Environment',
})}
>
<EuiSelect
value={currentValue}
options={options}
onChange={onChange}
compressed
/>
</PopoverExpression>
);
}
export function TransactionTypeField({
currentValue,
options,
onChange,
}: {
currentValue: string;
options?: EuiSelectOption[];
onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
}) {
const label = i18n.translate('xpack.apm.alerting.fields.type', {
defaultMessage: 'Type',
});
if (!options || options.length === 1) {
return <EuiExpression description={label} value={currentValue} />;
}
return (
<PopoverExpression value={currentValue} title={label}>
<EuiSelect
value={currentValue}
options={options}
onChange={onChange}
compressed
/>
</PopoverExpression>
);
}
export function IsAboveField({
value,
unit,
onChange,
step,
}: {
value: number;
unit: string;
onChange: (value: number) => void;
step?: number;
}) {
return (
<PopoverExpression
value={value ? `${value.toString()}${unit}` : ''}
title={i18n.translate(
'xpack.apm.transactionErrorRateAlertTrigger.isAbove',
{ defaultMessage: 'is above' }
)}
>
<EuiFieldNumber
value={value ?? ''}
onChange={(e) => onChange(parseInt(e.target.value, 10))}
append={unit}
compressed
step={step}
/>
</PopoverExpression>
);
}

View file

@ -0,0 +1,72 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { lazy } from 'react';
import { AlertType } from '../../../common/alert_types';
import { ApmPluginStartDeps } from '../../plugin';
export function registerApmAlerts(
alertTypeRegistry: ApmPluginStartDeps['triggers_actions_ui']['alertTypeRegistry']
) {
alertTypeRegistry.register({
id: AlertType.ErrorCount,
name: i18n.translate('xpack.apm.alertTypes.errorCount', {
defaultMessage: 'Error count threshold',
}),
iconClass: 'bell',
alertParamsExpression: lazy(() => import('./ErrorCountAlertTrigger')),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
alertTypeRegistry.register({
id: AlertType.TransactionDuration,
name: i18n.translate('xpack.apm.alertTypes.transactionDuration', {
defaultMessage: 'Transaction duration threshold',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() => import('./TransactionDurationAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
alertTypeRegistry.register({
id: AlertType.TransactionErrorRate,
name: i18n.translate('xpack.apm.alertTypes.transactionErrorRate', {
defaultMessage: 'Transaction error rate threshold',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() => import('./TransactionErrorRateAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
alertTypeRegistry.register({
id: AlertType.TransactionDurationAnomaly,
name: i18n.translate('xpack.apm.alertTypes.transactionDurationAnomaly', {
defaultMessage: 'Transaction duration anomaly',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() => import('./TransactionDurationAnomalyAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
}

View file

@ -24,9 +24,13 @@ const transactionDurationLabel = i18n.translate(
'xpack.apm.serviceDetails.alertsMenu.transactionDuration',
{ defaultMessage: 'Transaction duration' }
);
const errorRateLabel = i18n.translate(
'xpack.apm.serviceDetails.alertsMenu.errorRate',
{ defaultMessage: 'Error rate' }
const transactionErrorRateLabel = i18n.translate(
'xpack.apm.serviceDetails.alertsMenu.transactionErrorRate',
{ defaultMessage: 'Transaction error rate' }
);
const errorCountLabel = i18n.translate(
'xpack.apm.serviceDetails.alertsMenu.errorCount',
{ defaultMessage: 'Error count' }
);
const createThresholdAlertLabel = i18n.translate(
'xpack.apm.serviceDetails.alertsMenu.createThresholdAlert',
@ -38,8 +42,10 @@ const createAnomalyAlertAlertLabel = i18n.translate(
);
const CREATE_TRANSACTION_DURATION_ALERT_PANEL_ID =
'create_transaction_duration';
const CREATE_ERROR_RATE_ALERT_PANEL_ID = 'create_error_rate';
'create_transaction_duration_panel';
const CREATE_TRANSACTION_ERROR_RATE_ALERT_PANEL_ID =
'create_transaction_error_rate_panel';
const CREATE_ERROR_COUNT_ALERT_PANEL_ID = 'create_error_count_panel';
interface Props {
canReadAlerts: boolean;
@ -77,7 +83,14 @@ export function AlertIntegrations(props: Props) {
name: transactionDurationLabel,
panel: CREATE_TRANSACTION_DURATION_ALERT_PANEL_ID,
},
{ name: errorRateLabel, panel: CREATE_ERROR_RATE_ALERT_PANEL_ID },
{
name: transactionErrorRateLabel,
panel: CREATE_TRANSACTION_ERROR_RATE_ALERT_PANEL_ID,
},
{
name: errorCountLabel,
panel: CREATE_ERROR_COUNT_ALERT_PANEL_ID,
},
]
: []),
...(canReadAlerts
@ -96,10 +109,13 @@ export function AlertIntegrations(props: Props) {
: []),
],
},
// transaction duration panel
{
id: CREATE_TRANSACTION_DURATION_ALERT_PANEL_ID,
title: transactionDurationLabel,
items: [
// threshold alerts
{
name: createThresholdAlertLabel,
onClick: () => {
@ -107,6 +123,8 @@ export function AlertIntegrations(props: Props) {
setPopoverOpen(false);
},
},
// anomaly alerts
...(canReadAnomalies
? [
{
@ -120,14 +138,32 @@ export function AlertIntegrations(props: Props) {
: []),
],
},
// transaction error rate panel
{
id: CREATE_ERROR_RATE_ALERT_PANEL_ID,
title: errorRateLabel,
id: CREATE_TRANSACTION_ERROR_RATE_ALERT_PANEL_ID,
title: transactionErrorRateLabel,
items: [
// threshold alerts
{
name: createThresholdAlertLabel,
onClick: () => {
setAlertType(AlertType.TransactionErrorRate);
setPopoverOpen(false);
},
},
],
},
// error alerts panel
{
id: CREATE_ERROR_COUNT_ALERT_PANEL_ID,
title: errorCountLabel,
items: [
{
name: createThresholdAlertLabel,
onClick: () => {
setAlertType(AlertType.ErrorRate);
setAlertType(AlertType.ErrorCount);
setPopoverOpen(false);
},
},

View file

@ -4,8 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { lazy } from 'react';
import { ConfigSchema } from '.';
import {
FetchDataParams,
@ -34,10 +32,10 @@ import {
TriggersAndActionsUIPublicPluginSetup,
TriggersAndActionsUIPublicPluginStart,
} from '../../triggers_actions_ui/public';
import { AlertType } from '../common/alert_types';
import { featureCatalogueEntry } from './featureCatalogueEntry';
import { toggleAppLinkInNav } from './toggleAppLinkInNav';
import { EmbeddableStart } from '../../../../src/plugins/embeddable/public';
import { registerApmAlerts } from './components/alerting/register_apm_alerts';
export type ApmPluginSetup = void;
export type ApmPluginStart = void;
@ -147,51 +145,6 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
}
public start(core: CoreStart, plugins: ApmPluginStartDeps) {
toggleAppLinkInNav(core, this.initializerContext.config.get());
plugins.triggers_actions_ui.alertTypeRegistry.register({
id: AlertType.ErrorRate,
name: i18n.translate('xpack.apm.alertTypes.errorRate', {
defaultMessage: 'Error rate',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() => import('./components/shared/ErrorRateAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
plugins.triggers_actions_ui.alertTypeRegistry.register({
id: AlertType.TransactionDuration,
name: i18n.translate('xpack.apm.alertTypes.transactionDuration', {
defaultMessage: 'Transaction duration',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() => import('./components/shared/TransactionDurationAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
plugins.triggers_actions_ui.alertTypeRegistry.register({
id: AlertType.TransactionDurationAnomaly,
name: i18n.translate('xpack.apm.alertTypes.transactionDurationAnomaly', {
defaultMessage: 'Transaction duration anomaly',
}),
iconClass: 'bell',
alertParamsExpression: lazy(
() =>
import('./components/shared/TransactionDurationAnomalyAlertTrigger')
),
validate: () => ({
errors: [],
}),
requiresAppContext: true,
});
registerApmAlerts(plugins.triggers_actions_ui.alertTypeRegistry);
}
}

View file

@ -0,0 +1,48 @@
/*
* 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 { i18n } from '@kbn/i18n';
export const apmActionVariables = {
serviceName: {
description: i18n.translate(
'xpack.apm.alerts.action_variables.serviceName',
{ defaultMessage: 'The service the alert is created for' }
),
name: 'serviceName',
},
transactionType: {
description: i18n.translate(
'xpack.apm.alerts.action_variables.transactionType',
{ defaultMessage: 'The transaction type the alert is created for' }
),
name: 'transactionType',
},
environment: {
description: i18n.translate(
'xpack.apm.alerts.action_variables.environment',
{ defaultMessage: 'The transaction type the alert is created for' }
),
name: 'environment',
},
threshold: {
description: i18n.translate('xpack.apm.alerts.action_variables.threshold', {
defaultMessage:
'Any trigger value above this value will cause the alert to fire',
}),
name: 'threshold',
},
triggerValue: {
description: i18n.translate(
'xpack.apm.alerts.action_variables.triggerValue',
{
defaultMessage:
'The value that breached the threshold and triggered the alert',
}
),
name: 'triggerValue',
},
};

View file

@ -9,9 +9,10 @@ import { AlertingPlugin } from '../../../../alerts/server';
import { ActionsPlugin } from '../../../../actions/server';
import { registerTransactionDurationAlertType } from './register_transaction_duration_alert_type';
import { registerTransactionDurationAnomalyAlertType } from './register_transaction_duration_anomaly_alert_type';
import { registerErrorRateAlertType } from './register_error_rate_alert_type';
import { registerErrorCountAlertType } from './register_error_count_alert_type';
import { APMConfig } from '../..';
import { MlPluginSetup } from '../../../../ml/server';
import { registerTransactionErrorRateAlertType } from './register_transaction_error_rate_alert_type';
interface Params {
alerts: AlertingPlugin['setup'];
@ -30,7 +31,11 @@ export function registerApmAlerts(params: Params) {
ml: params.ml,
config$: params.config$,
});
registerErrorRateAlertType({
registerErrorCountAlertType({
alerts: params.alerts,
config$: params.config$,
});
registerTransactionErrorRateAlertType({
alerts: params.alerts,
config$: params.config$,
});

View file

@ -4,11 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema } 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 { ProcessorEvent } from '../../../common/processor_event';
import { getEnvironmentUiFilterES } from '../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import {
ESSearchResponse,
@ -17,11 +17,11 @@ import {
import {
PROCESSOR_EVENT,
SERVICE_NAME,
SERVICE_ENVIRONMENT,
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerts/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import { APMConfig } from '../..';
import { apmActionVariables } from './action_variables';
interface RegisterAlertParams {
alerts: AlertingPlugin['setup'];
@ -29,21 +29,21 @@ interface RegisterAlertParams {
}
const paramsSchema = schema.object({
serviceName: schema.string(),
windowSize: schema.number(),
windowUnit: schema.string(),
threshold: schema.number(),
serviceName: schema.string(),
environment: schema.string(),
});
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.ErrorRate];
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.ErrorCount];
export function registerErrorRateAlertType({
export function registerErrorCountAlertType({
alerts,
config$,
}: RegisterAlertParams) {
alerts.registerType({
id: AlertType.ErrorRate,
id: AlertType.ErrorCount,
name: alertTypeConfig.name,
actionGroups: alertTypeConfig.actionGroups,
defaultActionGroupId: alertTypeConfig.defaultActionGroupId,
@ -52,37 +52,26 @@ export function registerErrorRateAlertType({
},
actionVariables: {
context: [
{
description: i18n.translate(
'xpack.apm.registerErrorRateAlertType.variables.serviceName',
{
defaultMessage: 'Service name',
}
),
name: 'serviceName',
},
apmActionVariables.serviceName,
apmActionVariables.environment,
apmActionVariables.threshold,
apmActionVariables.triggerValue,
],
},
producer: 'apm',
executor: async ({ services, params }) => {
const config = await config$.pipe(take(1)).toPromise();
const alertParams = params as TypeOf<typeof paramsSchema>;
const alertParams = params;
const indices = await getApmIndices({
config,
savedObjectsClient: services.savedObjectsClient,
});
const environmentTerm =
alertParams.environment === ENVIRONMENT_ALL.value
? []
: [{ term: { [SERVICE_ENVIRONMENT]: alertParams.environment } }];
const searchParams = {
index: indices['apm_oss.errorIndices'],
size: 0,
body: {
track_total_hits: true,
query: {
bool: {
filter: [
@ -93,21 +82,12 @@ export function registerErrorRateAlertType({
},
},
},
{
term: {
[PROCESSOR_EVENT]: 'error',
},
},
{
term: {
[SERVICE_NAME]: alertParams.serviceName,
},
},
...environmentTerm,
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.error } },
{ term: { [SERVICE_NAME]: alertParams.serviceName } },
...getEnvironmentUiFilterES(alertParams.environment),
],
},
},
track_total_hits: true,
},
};
@ -116,18 +96,19 @@ export function registerErrorRateAlertType({
ESSearchRequest
> = await services.callCluster('search', searchParams);
const value = response.hits.total.value;
const errorCount = response.hits.total.value;
if (value && value > alertParams.threshold) {
if (errorCount > alertParams.threshold) {
const alertInstance = services.alertInstanceFactory(
AlertType.ErrorRate
AlertType.ErrorCount
);
alertInstance.scheduleActions(alertTypeConfig.defaultActionGroupId, {
serviceName: alertParams.serviceName,
environment: alertParams.environment,
threshold: alertParams.threshold,
triggerValue: errorCount,
});
}
return {};
},
});
}

View file

@ -4,11 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema } 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 { ProcessorEvent } from '../../../common/processor_event';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import { ESSearchResponse } from '../../../typings/elasticsearch';
import {
@ -16,11 +15,12 @@ import {
SERVICE_NAME,
TRANSACTION_TYPE,
TRANSACTION_DURATION,
SERVICE_ENVIRONMENT,
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerts/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import { APMConfig } from '../..';
import { getEnvironmentUiFilterES } from '../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { apmActionVariables } from './action_variables';
interface RegisterAlertParams {
alerts: AlertingPlugin['setup'];
@ -57,42 +57,22 @@ export function registerTransactionDurationAlertType({
},
actionVariables: {
context: [
{
description: i18n.translate(
'xpack.apm.registerTransactionDurationAlertType.variables.serviceName',
{
defaultMessage: 'Service name',
}
),
name: 'serviceName',
},
{
description: i18n.translate(
'xpack.apm.registerTransactionDurationAlertType.variables.transactionType',
{
defaultMessage: 'Transaction type',
}
),
name: 'transactionType',
},
apmActionVariables.serviceName,
apmActionVariables.transactionType,
apmActionVariables.environment,
apmActionVariables.threshold,
apmActionVariables.triggerValue,
],
},
producer: 'apm',
executor: async ({ services, params }) => {
const config = await config$.pipe(take(1)).toPromise();
const alertParams = params as TypeOf<typeof paramsSchema>;
const alertParams = params;
const indices = await getApmIndices({
config,
savedObjectsClient: services.savedObjectsClient,
});
const environmentTerm =
alertParams.environment === ENVIRONMENT_ALL.value
? []
: [{ term: { [SERVICE_ENVIRONMENT]: alertParams.environment } }];
const searchParams = {
index: indices['apm_oss.transactionIndices'],
size: 0,
@ -107,33 +87,17 @@ export function registerTransactionDurationAlertType({
},
},
},
{
term: {
[PROCESSOR_EVENT]: 'transaction',
},
},
{
term: {
[SERVICE_NAME]: alertParams.serviceName,
},
},
{
term: {
[TRANSACTION_TYPE]: alertParams.transactionType,
},
},
...environmentTerm,
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ term: { [SERVICE_NAME]: alertParams.serviceName } },
{ term: { [TRANSACTION_TYPE]: alertParams.transactionType } },
...getEnvironmentUiFilterES(alertParams.environment),
],
},
},
aggs: {
agg:
alertParams.aggregationType === 'avg'
? {
avg: {
field: TRANSACTION_DURATION,
},
}
? { avg: { field: TRANSACTION_DURATION } }
: {
percentiles: {
field: TRANSACTION_DURATION,
@ -157,19 +121,23 @@ export function registerTransactionDurationAlertType({
const { agg } = response.aggregations;
const value = 'values' in agg ? Object.values(agg.values)[0] : agg?.value;
const transactionDuration =
'values' in agg ? Object.values(agg.values)[0] : agg?.value;
if (value && value > alertParams.threshold * 1000) {
const threshold = alertParams.threshold * 1000;
if (transactionDuration && transactionDuration > threshold) {
const alertInstance = services.alertInstanceFactory(
AlertType.TransactionDuration
);
alertInstance.scheduleActions(alertTypeConfig.defaultActionGroupId, {
transactionType: alertParams.transactionType,
serviceName: alertParams.serviceName,
environment: alertParams.environment,
threshold,
triggerValue: transactionDuration,
});
}
return {};
},
});
}

View file

@ -4,15 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { schema, TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { i18n } from '@kbn/i18n';
import { KibanaRequest } from '../../../../../../src/core/server';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import { AlertingPlugin } from '../../../../alerts/server';
import { APMConfig } from '../..';
import { MlPluginSetup } from '../../../../ml/server';
import { getMLJobIds } from '../service_map/get_service_anomalies';
import { apmActionVariables } from './action_variables';
interface RegisterAlertParams {
alerts: AlertingPlugin['setup'];
@ -47,24 +47,9 @@ export function registerTransactionDurationAnomalyAlertType({
},
actionVariables: {
context: [
{
description: i18n.translate(
'xpack.apm.registerTransactionDurationAnomalyAlertType.variables.serviceName',
{
defaultMessage: 'Service name',
}
),
name: 'serviceName',
},
{
description: i18n.translate(
'xpack.apm.registerTransactionDurationAnomalyAlertType.variables.transactionType',
{
defaultMessage: 'Transaction type',
}
),
name: 'transactionType',
},
apmActionVariables.serviceName,
apmActionVariables.transactionType,
apmActionVariables.environment,
],
},
producer: 'apm',
@ -72,7 +57,7 @@ export function registerTransactionDurationAnomalyAlertType({
if (!ml) {
return;
}
const alertParams = params as TypeOf<typeof paramsSchema>;
const alertParams = params;
const request = {} as KibanaRequest;
const { mlAnomalySearch } = ml.mlSystemProvider(request);
const anomalyDetectors = ml.anomalyDetectorsProvider(request);
@ -88,6 +73,7 @@ export function registerTransactionDurationAnomalyAlertType({
const anomalySearchParams = {
body: {
terminateAfter: 1,
size: 0,
query: {
bool: {
@ -131,10 +117,10 @@ export function registerTransactionDurationAnomalyAlertType({
);
alertInstance.scheduleActions(alertTypeConfig.defaultActionGroupId, {
serviceName: alertParams.serviceName,
transactionType: alertParams.transactionType,
environment: alertParams.environment,
});
}
return {};
},
});
}

View file

@ -0,0 +1,131 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { Observable } from 'rxjs';
import { take } from 'rxjs/operators';
import { ProcessorEvent } from '../../../common/processor_event';
import { EventOutcome } from '../../../common/event_outcome';
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
import { ESSearchResponse } from '../../../typings/elasticsearch';
import {
PROCESSOR_EVENT,
SERVICE_NAME,
TRANSACTION_TYPE,
EVENT_OUTCOME,
} from '../../../common/elasticsearch_fieldnames';
import { AlertingPlugin } from '../../../../alerts/server';
import { getApmIndices } from '../settings/apm_indices/get_apm_indices';
import { APMConfig } from '../..';
import { getEnvironmentUiFilterES } from '../helpers/convert_ui_filters/get_environment_ui_filter_es';
import { apmActionVariables } from './action_variables';
interface RegisterAlertParams {
alerts: AlertingPlugin['setup'];
config$: Observable<APMConfig>;
}
const paramsSchema = schema.object({
windowSize: schema.number(),
windowUnit: schema.string(),
threshold: schema.number(),
transactionType: schema.string(),
serviceName: schema.string(),
environment: schema.string(),
});
const alertTypeConfig = ALERT_TYPES_CONFIG[AlertType.TransactionErrorRate];
export function registerTransactionErrorRateAlertType({
alerts,
config$,
}: RegisterAlertParams) {
alerts.registerType({
id: AlertType.TransactionErrorRate,
name: alertTypeConfig.name,
actionGroups: alertTypeConfig.actionGroups,
defaultActionGroupId: alertTypeConfig.defaultActionGroupId,
validate: {
params: paramsSchema,
},
actionVariables: {
context: [
apmActionVariables.transactionType,
apmActionVariables.serviceName,
apmActionVariables.environment,
apmActionVariables.threshold,
apmActionVariables.triggerValue,
],
},
producer: 'apm',
executor: async ({ services, params: alertParams }) => {
const config = await config$.pipe(take(1)).toPromise();
const indices = await getApmIndices({
config,
savedObjectsClient: services.savedObjectsClient,
});
const searchParams = {
index: indices['apm_oss.transactionIndices'],
size: 0,
body: {
track_total_hits: true,
query: {
bool: {
filter: [
{
range: {
'@timestamp': {
gte: `now-${alertParams.windowSize}${alertParams.windowUnit}`,
},
},
},
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ term: { [SERVICE_NAME]: alertParams.serviceName } },
{ term: { [TRANSACTION_TYPE]: alertParams.transactionType } },
...getEnvironmentUiFilterES(alertParams.environment),
],
},
},
aggs: {
erroneous_transactions: {
filter: { term: { [EVENT_OUTCOME]: EventOutcome.failure } },
},
},
},
};
const response: ESSearchResponse<
unknown,
typeof searchParams
> = await services.callCluster('search', searchParams);
if (!response.aggregations) {
return;
}
const errornousTransactionsCount =
response.aggregations.erroneous_transactions.doc_count;
const totalTransactionCount = response.hits.total.value;
const transactionErrorRate =
(errornousTransactionsCount / totalTransactionCount) * 100;
if (transactionErrorRate > alertParams.threshold) {
const alertInstance = services.alertInstanceFactory(
AlertType.TransactionErrorRate
);
alertInstance.scheduleActions(alertTypeConfig.defaultActionGroupId, {
serviceName: alertParams.serviceName,
transactionType: alertParams.transactionType,
environment: alertParams.environment,
threshold: alertParams.threshold,
triggerValue: transactionErrorRate,
});
}
},
});
}

View file

@ -8,6 +8,7 @@ import { Logger } from 'kibana/server';
import uuid from 'uuid/v4';
import { snakeCase } from 'lodash';
import Boom from 'boom';
import { ProcessorEvent } from '../../../common/processor_event';
import { ML_ERRORS } from '../../../common/anomaly_detection';
import { PromiseReturnType } from '../../../../observability/typings/common';
import { Setup } from '../helpers/setup_request';
@ -79,7 +80,7 @@ async function createAnomalyDetectionJob({
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ exists: { field: TRANSACTION_DURATION } },
...getEnvironmentUiFilterES(environment),
],

View file

@ -85,7 +85,7 @@ export const tasks: TelemetryTask[] = [
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
{ range: { '@timestamp': { gte: start, lt: end } } },
],
},
@ -606,7 +606,10 @@ export const tasks: TelemetryTask[] = [
timeout,
query: {
bool: {
filter: [{ term: { [PROCESSOR_EVENT]: 'error' } }, range1d],
filter: [
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.error } },
range1d,
],
},
},
aggs: {
@ -640,7 +643,7 @@ export const tasks: TelemetryTask[] = [
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
range1d,
],
},
@ -674,7 +677,7 @@ export const tasks: TelemetryTask[] = [
query: {
bool: {
filter: [
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } },
range1d,
],
must_not: {

View file

@ -5,11 +5,14 @@
*/
import { ESFilter } from '../../../../typings/elasticsearch';
import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values';
import {
ENVIRONMENT_NOT_DEFINED,
ENVIRONMENT_ALL,
} from '../../../../common/environment_filter_values';
import { SERVICE_ENVIRONMENT } from '../../../../common/elasticsearch_fieldnames';
export function getEnvironmentUiFilterES(environment?: string): ESFilter[] {
if (!environment) {
if (!environment || environment === ENVIRONMENT_ALL.value) {
return [];
}
if (environment === ENVIRONMENT_NOT_DEFINED.value) {

View file

@ -67,7 +67,7 @@ export async function getPageViewTrends({
x: xVal,
y: bCount,
};
if (breakdownItem) {
if ('breakdown' in bucket) {
const categoryBuckets = bucket.breakdown.buckets;
categoryBuckets.forEach(({ key, doc_count: docCount }) => {
if (key === 'Other') {

View file

@ -4616,7 +4616,6 @@
"xpack.apm.agentMetrics.java.threadCount": "平均カウント",
"xpack.apm.agentMetrics.java.threadCountChartTitle": "スレッド数",
"xpack.apm.agentMetrics.java.threadCountMax": "最高カウント",
"xpack.apm.alertTypes.errorRate": "エラー率",
"xpack.apm.alertTypes.transactionDuration": "トランザクション期間",
"xpack.apm.anomaly_detection.error.invalid_license": "異常検知を使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。このライセンスがあれば、機械学習を活用して、サービスを監視できます。",
"xpack.apm.anomaly_detection.error.missing_read_privileges": "異常検知ジョブを表示するには、機械学習およびAPMの「読み取り」権限が必要です",
@ -4675,11 +4674,6 @@
"xpack.apm.errorGroupDetails.relatedTransactionSample": "関連トランザクションサンプル",
"xpack.apm.errorGroupDetails.unhandledLabel": "未対応",
"xpack.apm.errorGroupDetails.viewOccurrencesInDiscoverButtonLabel": "ディスカバリで {occurrencesCount} 件の{occurrencesCount, plural, one {ドキュメント} other {ドキュメント}}を表示。",
"xpack.apm.errorRateAlert.name": "エラー率",
"xpack.apm.errorRateAlert.thresholdMet": "しきい値一致",
"xpack.apm.errorRateAlertTrigger.environment": "環境",
"xpack.apm.errorRateAlertTrigger.errors": "エラー",
"xpack.apm.errorRateAlertTrigger.isAbove": "の下限は",
"xpack.apm.errorRateChart.avgLabel": "平均",
"xpack.apm.errorRateChart.rateLabel": "レート",
"xpack.apm.errorRateChart.title": "トランザクションエラー率",
@ -4781,9 +4775,6 @@
"xpack.apm.propertiesTable.tabs.logStacktraceLabel": "スタックトレース",
"xpack.apm.propertiesTable.tabs.metadataLabel": "メタデータ",
"xpack.apm.propertiesTable.tabs.timelineLabel": "タイムライン",
"xpack.apm.registerErrorRateAlertType.variables.serviceName": "サービス名",
"xpack.apm.registerTransactionDurationAlertType.variables.serviceName": "サービス名",
"xpack.apm.registerTransactionDurationAlertType.variables.transactionType": "トランザクションタイプ",
"xpack.apm.rum.dashboard.backend": "バックエンド",
"xpack.apm.rum.dashboard.frontend": "フロントエンド",
"xpack.apm.rum.dashboard.overall.label": "全体",
@ -4801,7 +4792,6 @@
"xpack.apm.selectPlaceholder": "オプションを選択:",
"xpack.apm.serviceDetails.alertsMenu.alerts": "アラート",
"xpack.apm.serviceDetails.alertsMenu.createThresholdAlert": "しきい値アラートを作成",
"xpack.apm.serviceDetails.alertsMenu.errorRate": "エラー率",
"xpack.apm.serviceDetails.alertsMenu.transactionDuration": "トランザクション期間",
"xpack.apm.serviceDetails.alertsMenu.viewActiveAlerts": "アクティブアラートを表示",
"xpack.apm.serviceDetails.errorsTabLabel": "エラー",
@ -5031,11 +5021,7 @@
"xpack.apm.transactionDurationAlert.aggregationType.99th": "99 パーセンタイル",
"xpack.apm.transactionDurationAlert.aggregationType.avg": "平均",
"xpack.apm.transactionDurationAlert.name": "トランザクション期間",
"xpack.apm.transactionDurationAlert.thresholdMet": "しきい値一致",
"xpack.apm.transactionDurationAlertTrigger.environment": "環境",
"xpack.apm.transactionDurationAlertTrigger.isAbove": "の下限は",
"xpack.apm.transactionDurationAlertTrigger.ms": "ms",
"xpack.apm.transactionDurationAlertTrigger.type": "タイプ",
"xpack.apm.transactionDurationAlertTrigger.when": "タイミング",
"xpack.apm.transactionDurationLabel": "期間",
"xpack.apm.transactions.chart.95thPercentileLabel": "95 パーセンタイル",

View file

@ -4617,7 +4617,6 @@
"xpack.apm.agentMetrics.java.threadCount": "平均计数",
"xpack.apm.agentMetrics.java.threadCountChartTitle": "线程计数",
"xpack.apm.agentMetrics.java.threadCountMax": "最大计数",
"xpack.apm.alertTypes.errorRate": "错误率",
"xpack.apm.alertTypes.transactionDuration": "事务持续时间",
"xpack.apm.anomaly_detection.error.invalid_license": "要使用异常检测,必须订阅 Elastic 白金级许可证。有了该许可证,您便可借助 Machine Learning 监测服务。",
"xpack.apm.anomaly_detection.error.missing_read_privileges": "必须对 Machine Learning 和 APM 具有“读”权限,才能查看“异常检测”作业",
@ -4676,11 +4675,6 @@
"xpack.apm.errorGroupDetails.relatedTransactionSample": "相关的事务样本",
"xpack.apm.errorGroupDetails.unhandledLabel": "未处理",
"xpack.apm.errorGroupDetails.viewOccurrencesInDiscoverButtonLabel": "在 Discover 查看 {occurrencesCount} 个 {occurrencesCount, plural, one {匹配项} other {匹配项}}。",
"xpack.apm.errorRateAlert.name": "错误率",
"xpack.apm.errorRateAlert.thresholdMet": "阈值已达到",
"xpack.apm.errorRateAlertTrigger.environment": "环境",
"xpack.apm.errorRateAlertTrigger.errors": "错误",
"xpack.apm.errorRateAlertTrigger.isAbove": "高于",
"xpack.apm.errorRateChart.avgLabel": "平均",
"xpack.apm.errorRateChart.rateLabel": "比率",
"xpack.apm.errorRateChart.title": "事务错误率",
@ -4784,9 +4778,6 @@
"xpack.apm.propertiesTable.tabs.logStacktraceLabel": "日志堆栈跟踪",
"xpack.apm.propertiesTable.tabs.metadataLabel": "元数据",
"xpack.apm.propertiesTable.tabs.timelineLabel": "时间线",
"xpack.apm.registerErrorRateAlertType.variables.serviceName": "服务名称",
"xpack.apm.registerTransactionDurationAlertType.variables.serviceName": "服务名称",
"xpack.apm.registerTransactionDurationAlertType.variables.transactionType": "事务类型",
"xpack.apm.rum.dashboard.backend": "后端",
"xpack.apm.rum.dashboard.frontend": "前端",
"xpack.apm.rum.dashboard.overall.label": "总体",
@ -4804,7 +4795,6 @@
"xpack.apm.selectPlaceholder": "选择选项:",
"xpack.apm.serviceDetails.alertsMenu.alerts": "告警",
"xpack.apm.serviceDetails.alertsMenu.createThresholdAlert": "创建阈值告警",
"xpack.apm.serviceDetails.alertsMenu.errorRate": "错误率",
"xpack.apm.serviceDetails.alertsMenu.transactionDuration": "事务持续时间",
"xpack.apm.serviceDetails.alertsMenu.viewActiveAlerts": "查看活动的告警",
"xpack.apm.serviceDetails.errorsTabLabel": "错误",
@ -5034,11 +5024,7 @@
"xpack.apm.transactionDurationAlert.aggregationType.99th": "第 99 个百分位",
"xpack.apm.transactionDurationAlert.aggregationType.avg": "平均值",
"xpack.apm.transactionDurationAlert.name": "事务持续时间",
"xpack.apm.transactionDurationAlert.thresholdMet": "阈值已达到",
"xpack.apm.transactionDurationAlertTrigger.environment": "环境",
"xpack.apm.transactionDurationAlertTrigger.isAbove": "高于",
"xpack.apm.transactionDurationAlertTrigger.ms": "ms",
"xpack.apm.transactionDurationAlertTrigger.type": "类型",
"xpack.apm.transactionDurationAlertTrigger.when": "当",
"xpack.apm.transactionDurationLabel": "持续时间",
"xpack.apm.transactions.chart.95thPercentileLabel": "第 95 个百分位",