mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[APM] Add transaction name filter in failed transaction rate rule type (#155405)
part of https://github.com/elastic/kibana/issues/152329
related work https://github.com/elastic/kibana/pull/154241
Introduces the Transaction name filter in the failed transaction rate
rule type
https://user-images.githubusercontent.com/3369346/233386404-1875b283-0321-4bf1-a7d3-66327f7d4ec5.mov
## Fixes
The regression introduces in a previous
[PR](fce4ef8168
)
Existing rule types can have empty string in their params so we need to
make sure we don't filter empty values as it will yield no results.
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
54457b074a
commit
111d04f45a
8 changed files with 214 additions and 12 deletions
|
@ -52,6 +52,7 @@ export const transactionErrorRateParamsSchema = schema.object({
|
|||
windowUnit: schema.string(),
|
||||
threshold: schema.number(),
|
||||
transactionType: schema.maybe(schema.string()),
|
||||
transactionName: schema.maybe(schema.string()),
|
||||
serviceName: schema.maybe(schema.string()),
|
||||
environment: schema.string(),
|
||||
});
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { Story } from '@storybook/react';
|
||||
import React, { ComponentType, useState } from 'react';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public';
|
||||
import { RuleParams, TransactionErrorRateRuleType } from '.';
|
||||
import { AlertMetadata } from '../../utils/helper';
|
||||
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext({
|
||||
notifications: { toasts: { add: () => {} } },
|
||||
} as unknown as Partial<CoreStart>);
|
||||
|
||||
interface Args {
|
||||
ruleParams: RuleParams;
|
||||
metadata?: AlertMetadata;
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'alerting/TransactionErrorRateRuleType',
|
||||
component: TransactionErrorRateRuleType,
|
||||
decorators: [
|
||||
(StoryComponent: ComponentType) => {
|
||||
return (
|
||||
<KibanaReactContext.Provider>
|
||||
<div style={{ width: 400 }}>
|
||||
<StoryComponent />
|
||||
</div>
|
||||
</KibanaReactContext.Provider>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const CreatingInApmServiceOverview: Story<Args> = ({
|
||||
ruleParams,
|
||||
metadata,
|
||||
}) => {
|
||||
const [params, setParams] = useState<RuleParams>(ruleParams);
|
||||
|
||||
function setRuleParams(property: string, value: any) {
|
||||
setParams({ ...params, [property]: value });
|
||||
}
|
||||
|
||||
return (
|
||||
<TransactionErrorRateRuleType
|
||||
ruleParams={params}
|
||||
metadata={metadata}
|
||||
setRuleParams={setRuleParams}
|
||||
setRuleProperty={() => {}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CreatingInApmServiceOverview.args = {
|
||||
ruleParams: {
|
||||
environment: 'testEnvironment',
|
||||
serviceName: 'testServiceName',
|
||||
threshold: 1500,
|
||||
transactionType: 'testTransactionType',
|
||||
transactionName: 'GET /api/customer/:id',
|
||||
windowSize: 5,
|
||||
windowUnit: 'm',
|
||||
},
|
||||
metadata: {
|
||||
environment: ENVIRONMENT_ALL.value,
|
||||
serviceName: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
export const CreatingInStackManagement: Story<Args> = ({
|
||||
ruleParams,
|
||||
metadata,
|
||||
}) => {
|
||||
const [params, setParams] = useState<RuleParams>(ruleParams);
|
||||
|
||||
function setRuleParams(property: string, value: any) {
|
||||
setParams({ ...params, [property]: value });
|
||||
}
|
||||
|
||||
return (
|
||||
<TransactionErrorRateRuleType
|
||||
ruleParams={params}
|
||||
metadata={metadata}
|
||||
setRuleParams={setRuleParams}
|
||||
setRuleProperty={() => {}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CreatingInStackManagement.args = {
|
||||
ruleParams: {
|
||||
environment: 'testEnvironment',
|
||||
threshold: 1500,
|
||||
windowSize: 5,
|
||||
windowUnit: 'm',
|
||||
},
|
||||
metadata: undefined,
|
||||
};
|
|
@ -23,20 +23,22 @@ import {
|
|||
IsAboveField,
|
||||
ServiceField,
|
||||
TransactionTypeField,
|
||||
TransactionNameField,
|
||||
} from '../../utils/fields';
|
||||
import { AlertMetadata, getIntervalAndTimeRange } from '../../utils/helper';
|
||||
import { ApmRuleParamsContainer } from '../../ui_components/apm_rule_params_container';
|
||||
|
||||
interface RuleParams {
|
||||
export interface RuleParams {
|
||||
windowSize?: number;
|
||||
windowUnit?: string;
|
||||
threshold?: number;
|
||||
serviceName?: string;
|
||||
transactionType?: string;
|
||||
transactionName?: string;
|
||||
environment?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
ruleParams: RuleParams;
|
||||
metadata?: AlertMetadata;
|
||||
setRuleParams: (key: string, value: any) => void;
|
||||
|
@ -78,6 +80,7 @@ export function TransactionErrorRateRuleType(props: Props) {
|
|||
environment: params.environment,
|
||||
serviceName: params.serviceName,
|
||||
transactionType: params.transactionType,
|
||||
transactionName: params.transactionName,
|
||||
interval,
|
||||
start,
|
||||
end,
|
||||
|
@ -89,6 +92,7 @@ export function TransactionErrorRateRuleType(props: Props) {
|
|||
},
|
||||
[
|
||||
params.transactionType,
|
||||
params.transactionName,
|
||||
params.environment,
|
||||
params.serviceName,
|
||||
params.windowSize,
|
||||
|
@ -102,7 +106,8 @@ export function TransactionErrorRateRuleType(props: Props) {
|
|||
onChange={(value) => {
|
||||
if (value !== params.serviceName) {
|
||||
setRuleParams('serviceName', value);
|
||||
setRuleParams('transactionType', '');
|
||||
setRuleParams('transactionType', undefined);
|
||||
setRuleParams('transactionName', undefined);
|
||||
setRuleParams('environment', ENVIRONMENT_ALL.value);
|
||||
}
|
||||
}}
|
||||
|
@ -117,6 +122,11 @@ export function TransactionErrorRateRuleType(props: Props) {
|
|||
onChange={(value) => setRuleParams('environment', value)}
|
||||
serviceName={params.serviceName}
|
||||
/>,
|
||||
<TransactionNameField
|
||||
currentValue={params.transactionName}
|
||||
onChange={(value) => setRuleParams('transactionName', value)}
|
||||
serviceName={params.serviceName}
|
||||
/>,
|
||||
<IsAboveField
|
||||
value={params.threshold}
|
||||
unit="%"
|
||||
|
|
|
@ -113,8 +113,12 @@ export function registerErrorCountRuleType({
|
|||
},
|
||||
},
|
||||
{ term: { [PROCESSOR_EVENT]: ProcessorEvent.error } },
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName),
|
||||
...termQuery(ERROR_GROUP_ID, ruleParams.errorGroupingKey),
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...termQuery(ERROR_GROUP_ID, ruleParams.errorGroupingKey, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...environmentQuery(ruleParams.environment),
|
||||
],
|
||||
},
|
||||
|
|
|
@ -148,9 +148,15 @@ export function registerTransactionDurationRuleType({
|
|||
...getDocumentTypeFilterForTransactions(
|
||||
searchAggregatedTransactions
|
||||
),
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName),
|
||||
...termQuery(TRANSACTION_TYPE, ruleParams.transactionType),
|
||||
...termQuery(TRANSACTION_NAME, ruleParams.transactionName),
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...termQuery(TRANSACTION_TYPE, ruleParams.transactionType, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...termQuery(TRANSACTION_NAME, ruleParams.transactionName, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...environmentQuery(ruleParams.environment),
|
||||
] as QueryDslQueryContainer[],
|
||||
},
|
||||
|
|
|
@ -9,6 +9,7 @@ import { rangeQuery, termQuery } from '@kbn/observability-plugin/server';
|
|||
import {
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_TYPE,
|
||||
TRANSACTION_NAME,
|
||||
} from '../../../../../common/es_fields/apm';
|
||||
import { environmentQuery } from '../../../../../common/utils/environment_query';
|
||||
import { AlertParams } from '../../route';
|
||||
|
@ -39,8 +40,15 @@ export async function getTransactionErrorRateChartPreview({
|
|||
apmEventClient: APMEventClient;
|
||||
alertParams: AlertParams;
|
||||
}): Promise<TransactionErrorRateChartPreviewResponse> {
|
||||
const { serviceName, environment, transactionType, interval, start, end } =
|
||||
alertParams;
|
||||
const {
|
||||
serviceName,
|
||||
environment,
|
||||
transactionType,
|
||||
interval,
|
||||
start,
|
||||
end,
|
||||
transactionName,
|
||||
} = alertParams;
|
||||
|
||||
const searchAggregatedTransactions = await getSearchTransactionsEvents({
|
||||
config,
|
||||
|
@ -62,6 +70,7 @@ export async function getTransactionErrorRateChartPreview({
|
|||
filter: [
|
||||
...termQuery(SERVICE_NAME, serviceName),
|
||||
...termQuery(TRANSACTION_TYPE, transactionType),
|
||||
...termQuery(TRANSACTION_NAME, transactionName),
|
||||
...rangeQuery(start, end),
|
||||
...environmentQuery(environment),
|
||||
...getDocumentTypeFilterForTransactions(
|
||||
|
|
|
@ -32,6 +32,7 @@ import {
|
|||
SERVICE_ENVIRONMENT,
|
||||
SERVICE_NAME,
|
||||
TRANSACTION_TYPE,
|
||||
TRANSACTION_NAME,
|
||||
} from '../../../../../common/es_fields/apm';
|
||||
import { EventOutcome } from '../../../../../common/event_outcome';
|
||||
import {
|
||||
|
@ -86,6 +87,7 @@ export function registerTransactionErrorRateRuleType({
|
|||
apmActionVariables.interval,
|
||||
apmActionVariables.reason,
|
||||
apmActionVariables.serviceName,
|
||||
apmActionVariables.transactionName,
|
||||
apmActionVariables.threshold,
|
||||
apmActionVariables.transactionType,
|
||||
apmActionVariables.triggerValue,
|
||||
|
@ -142,8 +144,15 @@ export function registerTransactionErrorRateRuleType({
|
|||
],
|
||||
},
|
||||
},
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName),
|
||||
...termQuery(TRANSACTION_TYPE, ruleParams.transactionType),
|
||||
...termQuery(SERVICE_NAME, ruleParams.serviceName, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...termQuery(TRANSACTION_TYPE, ruleParams.transactionType, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...termQuery(TRANSACTION_NAME, ruleParams.transactionName, {
|
||||
queryEmptyString: false,
|
||||
}),
|
||||
...environmentQuery(ruleParams.environment),
|
||||
],
|
||||
},
|
||||
|
@ -232,6 +241,7 @@ export function registerTransactionErrorRateRuleType({
|
|||
serviceName,
|
||||
transactionType,
|
||||
environment,
|
||||
ruleParams.transactionName,
|
||||
]
|
||||
.filter((name) => name)
|
||||
.join('_');
|
||||
|
@ -255,6 +265,7 @@ export function registerTransactionErrorRateRuleType({
|
|||
[SERVICE_NAME]: serviceName,
|
||||
...getEnvironmentEsField(environment),
|
||||
[TRANSACTION_TYPE]: transactionType,
|
||||
[TRANSACTION_NAME]: ruleParams.transactionName,
|
||||
[PROCESSOR_EVENT]: ProcessorEvent.transaction,
|
||||
[ALERT_EVALUATION_VALUE]: errorRate,
|
||||
[ALERT_EVALUATION_THRESHOLD]: ruleParams.threshold,
|
||||
|
@ -272,6 +283,7 @@ export function registerTransactionErrorRateRuleType({
|
|||
serviceName,
|
||||
threshold: ruleParams.threshold,
|
||||
transactionType,
|
||||
transactionName: ruleParams.transactionName,
|
||||
triggerValue: asDecimalOrInteger(errorRate),
|
||||
viewInAppUrl,
|
||||
});
|
||||
|
|
|
@ -83,6 +83,61 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
).to.equal(true);
|
||||
});
|
||||
|
||||
it('transaction_error_rate with transaction name', async () => {
|
||||
const options = {
|
||||
params: {
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
serviceName: 'opbeans-java',
|
||||
transactionName: 'APIRestController#product',
|
||||
transactionType: 'request',
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
interval: '5m',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const response = await apmApiClient.readUser({
|
||||
endpoint: 'GET /internal/apm/rule_types/transaction_error_rate/chart_preview',
|
||||
...options,
|
||||
});
|
||||
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body.errorRateChartPreview[0]).to.eql({
|
||||
x: 1627974600000,
|
||||
y: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('transaction_error_rate with nonexistent transaction name', async () => {
|
||||
const options = {
|
||||
params: {
|
||||
query: {
|
||||
start,
|
||||
end,
|
||||
serviceName: 'opbeans-java',
|
||||
transactionName: 'foo',
|
||||
transactionType: 'request',
|
||||
environment: 'ENVIRONMENT_ALL',
|
||||
interval: '5m',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const response = await apmApiClient.readUser({
|
||||
endpoint: 'GET /internal/apm/rule_types/transaction_error_rate/chart_preview',
|
||||
...options,
|
||||
});
|
||||
|
||||
expect(response.status).to.be(200);
|
||||
expect(
|
||||
response.body.errorRateChartPreview.every(
|
||||
(item: { x: number; y: number | null }) => item.y === null
|
||||
)
|
||||
).to.equal(true);
|
||||
});
|
||||
|
||||
it('error_count (with data)', async () => {
|
||||
const options = getOptions();
|
||||
options.params.query.transactionType = undefined;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue