Skip to content

Commit

Permalink
[APM] Add transaction name filter in failed transaction rate rule type (
Browse files Browse the repository at this point in the history
#155405)

part of #152329
related work #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](fce4ef8)

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 <[email protected]>
  • Loading branch information
kpatticha and kibanamachine authored Apr 24, 2023
1 parent 54457b0 commit 111d04f
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 12 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/apm/common/rules/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
});
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -78,6 +80,7 @@ export function TransactionErrorRateRuleType(props: Props) {
environment: params.environment,
serviceName: params.serviceName,
transactionType: params.transactionType,
transactionName: params.transactionName,
interval,
start,
end,
Expand All @@ -89,6 +92,7 @@ export function TransactionErrorRateRuleType(props: Props) {
},
[
params.transactionType,
params.transactionName,
params.environment,
params.serviceName,
params.windowSize,
Expand All @@ -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);
}
}}
Expand All @@ -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="%"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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[],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -86,6 +87,7 @@ export function registerTransactionErrorRateRuleType({
apmActionVariables.interval,
apmActionVariables.reason,
apmActionVariables.serviceName,
apmActionVariables.transactionName,
apmActionVariables.threshold,
apmActionVariables.transactionType,
apmActionVariables.triggerValue,
Expand Down Expand Up @@ -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),
],
},
Expand Down Expand Up @@ -232,6 +241,7 @@ export function registerTransactionErrorRateRuleType({
serviceName,
transactionType,
environment,
ruleParams.transactionName,
]
.filter((name) => name)
.join('_');
Expand All @@ -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,
Expand All @@ -272,6 +283,7 @@ export function registerTransactionErrorRateRuleType({
serviceName,
threshold: ruleParams.threshold,
transactionType,
transactionName: ruleParams.transactionName,
triggerValue: asDecimalOrInteger(errorRate),
viewInAppUrl,
});
Expand Down
55 changes: 55 additions & 0 deletions x-pack/test/apm_api_integration/tests/alerts/chart_preview.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 111d04f

Please sign in to comment.