Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add KQL filtering in APM rules #163825

Merged
merged 28 commits into from Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d11276c
add kql filter in latency threshold rule
benakansara Aug 3, 2023
bc2f191
add kql filter in error count/rate rules
benakansara Aug 7, 2023
4e75f7d
add tests for preview chart
benakansara Aug 7, 2023
892a49d
added integration tests
benakansara Aug 7, 2023
94ca133
added integration tests
benakansara Aug 7, 2023
fd2b1c9
added tests
benakansara Aug 8, 2023
877902e
fix test
benakansara Aug 8, 2023
20afbce
fix test
benakansara Aug 8, 2023
85b315a
fix test
benakansara Aug 8, 2023
ab776d6
fix tests
benakansara Aug 8, 2023
2444acc
fix tests
benakansara Aug 8, 2023
6c0bf67
remove commented code
benakansara Aug 9, 2023
5d98cac
renaming
benakansara Aug 10, 2023
50ec1a9
remove useKqlFilter from server
benakansara Aug 10, 2023
ec167cd
renaming
benakansara Aug 10, 2023
c69e95c
pr feedback
benakansara Aug 10, 2023
8ee04ce
refactoring to reuse KQL filter from observability
benakansara Aug 11, 2023
d19160f
refactoring to reuse getParsedFilterQuery from observability
benakansara Aug 11, 2023
b3ef493
update data-test-subject
benakansara Aug 11, 2023
c70dcc4
fix tests
benakansara Aug 11, 2023
87760ca
use getErrorGroupingKey
benakansara Aug 11, 2023
d6706d2
Merge branch 'main' into feat/add-kql-filtering-in-apm-rules
benakansara Aug 14, 2023
e01c3e3
pr feedback
benakansara Aug 14, 2023
04fd593
fix error
benakansara Aug 14, 2023
55e5235
Merge branch 'main' into feat/kql-filter-in-apm-rules
benakansara Aug 14, 2023
8a53532
add technical preview
benakansara Aug 15, 2023
f3f895e
Merge branch 'main' into feat/kql-filter-in-apm-rules
benakansara Aug 15, 2023
b129a8c
Merge branch 'main' into feat/kql-filter-in-apm-rules
benakansara Aug 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions x-pack/plugins/apm/common/rules/schema.ts
Expand Up @@ -17,6 +17,8 @@ export const errorCountParamsSchema = schema.object({
environment: schema.string(),
groupBy: schema.maybe(schema.arrayOf(schema.string())),
errorGroupingKey: schema.maybe(schema.string()),
useKqlFilter: schema.maybe(schema.boolean()),
kqlFilter: schema.maybe(schema.string()),
});

export const transactionDurationParamsSchema = schema.object({
Expand All @@ -33,6 +35,8 @@ export const transactionDurationParamsSchema = schema.object({
]),
environment: schema.string(),
groupBy: schema.maybe(schema.arrayOf(schema.string())),
useKqlFilter: schema.maybe(schema.boolean()),
kqlFilter: schema.maybe(schema.string()),
});

export const anomalyParamsSchema = schema.object({
Expand All @@ -58,6 +62,8 @@ export const transactionErrorRateParamsSchema = schema.object({
serviceName: schema.maybe(schema.string()),
environment: schema.string(),
groupBy: schema.maybe(schema.arrayOf(schema.string())),
useKqlFilter: schema.maybe(schema.boolean()),
kqlFilter: schema.maybe(schema.string()),
});

type ErrorCountParamsType = TypeOf<typeof errorCountParamsSchema>;
Expand Down
Expand Up @@ -11,7 +11,7 @@ import { CoreStart } from '@kbn/core/public';
import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public';
import { TIME_UNITS } from '@kbn/triggers-actions-ui-plugin/public';
import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';
import { RuleParams, ErrorCountRuleType } from '.';
import { ErrorCountRuleParams, ErrorCountRuleType } from '.';
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
import { createCallApmApi } from '../../../../services/rest/create_call_apm_api';
import { AlertMetadata } from '../../utils/helper';
Expand All @@ -22,10 +22,15 @@ const coreMock = {
uiSettings: { get: () => {} },
} as unknown as CoreStart;

const KibanaReactContext = createKibanaReactContext(coreMock);
const KibanaReactContext = createKibanaReactContext({
...coreMock,
dataViews: {
create: async () => {},
},
});

interface Args {
ruleParams: RuleParams;
ruleParams: ErrorCountRuleParams;
metadata?: AlertMetadata;
}

Expand Down Expand Up @@ -54,7 +59,7 @@ export const CreatingInApmFromInventory: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorCountRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down Expand Up @@ -83,7 +88,7 @@ export const CreatingInApmFromService: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorCountRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down Expand Up @@ -112,7 +117,7 @@ export const EditingInStackManagement: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorCountRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down Expand Up @@ -142,7 +147,7 @@ export const CreatingInStackManagement: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorCountRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down
Expand Up @@ -16,6 +16,7 @@ import {
} from '@kbn/triggers-actions-ui-plugin/public';
import { EuiFormRow } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { EuiSwitchEvent } from '@elastic/eui';
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
import { asInteger } from '../../../../../common/utils/formatters';
import {
Expand Down Expand Up @@ -46,19 +47,22 @@ import {
LoadingState,
NoDataState,
} from '../../ui_components/chart_preview/chart_preview_helper';
import { ApmRuleKqlFilter } from '../../ui_components/apm_rule_kql_filter';

export interface RuleParams {
export interface ErrorCountRuleParams {
windowSize?: number;
windowUnit?: TIME_UNITS;
threshold?: number;
serviceName?: string;
environment?: string;
groupBy?: string[] | undefined;
errorGroupingKey?: string;
useKqlFilter?: boolean;
kqlFilter?: string;
}

interface Props {
ruleParams: RuleParams;
ruleParams: ErrorCountRuleParams;
metadata?: AlertMetadata;
setRuleParams: (key: string, value: any) => void;
setRuleProperty: (key: string, value: any) => void;
Expand Down Expand Up @@ -101,6 +105,7 @@ export function ErrorCountRuleType(props: Props) {
start,
end,
groupBy: params.groupBy,
kqlFilter: params.kqlFilter,
},
},
}
Expand All @@ -114,6 +119,7 @@ export function ErrorCountRuleType(props: Props) {
params.serviceName,
params.errorGroupingKey,
params.groupBy,
params.kqlFilter,
]
);

Expand All @@ -124,7 +130,7 @@ export function ErrorCountRuleType(props: Props) {
[setRuleParams]
);

const fields = [
const filterFields = [
<ServiceField
currentValue={params.serviceName}
onChange={(value) => {
Expand All @@ -150,7 +156,9 @@ export function ErrorCountRuleType(props: Props) {
onChange={(value) => setRuleParams('errorGroupingKey', value)}
serviceName={params.serviceName}
/>,
];

const criteriaFields = [
<IsAboveField
value={params.threshold}
unit={i18n.translate('xpack.apm.errorCountRuleType.errors', {
Expand All @@ -174,6 +182,11 @@ export function ErrorCountRuleType(props: Props) {
/>,
];

const fields = [
...(!ruleParams.useKqlFilter ? filterFields : []),
...criteriaFields,
];

const errorCountChartPreview = data?.errorCountChartPreview;
const series = errorCountChartPreview?.series ?? [];
const hasData = series.length > 0;
Expand Down Expand Up @@ -227,12 +240,31 @@ export function ErrorCountRuleType(props: Props) {
</>
);

const onToggleKqlFilter = (e: EuiSwitchEvent) => {
setRuleParams('serviceName', undefined);
setRuleParams('errorGroupingKey', undefined);
setRuleParams('environment', ENVIRONMENT_ALL.value);
setRuleParams('kqlFilter', undefined);
setRuleParams('useKqlFilter', e.target.checked);
};

const kqlFilter = (
<>
<ApmRuleKqlFilter
ruleParams={ruleParams}
setRuleParams={setRuleParams}
onToggleKqlFilter={onToggleKqlFilter}
/>
</>
);

return (
<ApmRuleParamsContainer
minimumWindowSize={{ value: 5, unit: TIME_UNITS.MINUTE }}
defaultParams={params}
fields={fields}
groupAlertsBy={groupAlertsBy}
kqlFilter={kqlFilter}
setRuleParams={setRuleParams}
setRuleProperty={setRuleProperty}
chartPreview={chartPreview}
Expand Down
Expand Up @@ -9,7 +9,7 @@ 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, TransactionDurationRuleType } from '.';
import { TransactionDurationRuleParams, TransactionDurationRuleType } from '.';
import { AggregationType } from '../../../../../common/rules/apm_rule_types';
import { AlertMetadata } from '../../utils/helper';
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
Expand All @@ -19,7 +19,7 @@ const KibanaReactContext = createKibanaReactContext({
} as unknown as Partial<CoreStart>);

interface Args {
ruleParams: RuleParams;
ruleParams: TransactionDurationRuleParams;
metadata?: AlertMetadata;
}

Expand All @@ -43,7 +43,8 @@ export const CreatingInApmServiceOverview: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] =
useState<TransactionDurationRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down Expand Up @@ -80,7 +81,8 @@ export const CreatingInStackManagement: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] =
useState<TransactionDurationRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down
Expand Up @@ -17,6 +17,7 @@ import {
} from '@kbn/triggers-actions-ui-plugin/public';
import { EuiFormRow } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { EuiSwitchEvent } from '@elastic/eui';
import { AggregationType } from '../../../../../common/rules/apm_rule_types';
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';
import { getDurationFormatter } from '../../../../../common/utils/formatters';
Expand Down Expand Up @@ -53,8 +54,9 @@ import {
LoadingState,
NoDataState,
} from '../../ui_components/chart_preview/chart_preview_helper';
import { ApmRuleKqlFilter } from '../../ui_components/apm_rule_kql_filter';

export interface RuleParams {
export interface TransactionDurationRuleParams {
aggregationType: AggregationType;
environment: string;
threshold: number;
Expand All @@ -64,6 +66,8 @@ export interface RuleParams {
windowSize: number;
windowUnit: string;
groupBy?: string[] | undefined;
useKqlFilter?: boolean;
kqlFilter?: string;
}

const TRANSACTION_ALERT_AGGREGATION_TYPES: Record<AggregationType, string> = {
Expand All @@ -82,7 +86,7 @@ const TRANSACTION_ALERT_AGGREGATION_TYPES: Record<AggregationType, string> = {
};

interface Props {
ruleParams: RuleParams;
ruleParams: TransactionDurationRuleParams;
metadata?: AlertMetadata;
setRuleParams: (key: string, value: any) => void;
setRuleProperty: (key: string, value: any) => void;
Expand Down Expand Up @@ -131,6 +135,7 @@ export function TransactionDurationRuleType(props: Props) {
start,
end,
groupBy: params.groupBy,
kqlFilter: params.kqlFilter,
},
},
}
Expand All @@ -146,6 +151,7 @@ export function TransactionDurationRuleType(props: Props) {
params.windowSize,
params.windowUnit,
params.groupBy,
params.kqlFilter,
]
);

Expand Down Expand Up @@ -186,7 +192,7 @@ export function TransactionDurationRuleType(props: Props) {
[setRuleParams]
);

const fields = [
const filterFields = [
<ServiceField
allowAll={false}
currentValue={params.serviceName}
Expand Down Expand Up @@ -219,6 +225,9 @@ export function TransactionDurationRuleType(props: Props) {
onChange={(value) => setRuleParams('transactionName', value)}
serviceName={params.serviceName}
/>,
];

const criteriaFields = [
<PopoverExpression
value={params.aggregationType}
title={i18n.translate('xpack.apm.transactionDurationRuleType.when', {
Expand Down Expand Up @@ -261,6 +270,11 @@ export function TransactionDurationRuleType(props: Props) {
/>,
];

const fields = [
...(!ruleParams.useKqlFilter ? filterFields : []),
...criteriaFields,
];

const groupAlertsBy = (
<>
<EuiFormRow
Expand Down Expand Up @@ -295,13 +309,33 @@ export function TransactionDurationRuleType(props: Props) {
</>
);

const onToggleKqlFilter = (e: EuiSwitchEvent) => {
setRuleParams('serviceName', undefined);
setRuleParams('transactionType', undefined);
setRuleParams('transactionName', undefined);
setRuleParams('environment', ENVIRONMENT_ALL.value);
setRuleParams('kqlFilter', undefined);
setRuleParams('useKqlFilter', e.target.checked);
};

const kqlFilter = (
<>
<ApmRuleKqlFilter
ruleParams={ruleParams}
setRuleParams={setRuleParams}
onToggleKqlFilter={onToggleKqlFilter}
/>
</>
);

return (
<ApmRuleParamsContainer
minimumWindowSize={{ value: 5, unit: TIME_UNITS.MINUTE }}
chartPreview={chartPreview}
defaultParams={params}
fields={fields}
groupAlertsBy={groupAlertsBy}
kqlFilter={kqlFilter}
setRuleParams={setRuleParams}
setRuleProperty={setRuleProperty}
/>
Expand Down
Expand Up @@ -9,7 +9,7 @@ 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 { ErrorRateRuleParams, TransactionErrorRateRuleType } from '.';
import { AlertMetadata } from '../../utils/helper';
import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values';

Expand All @@ -18,7 +18,7 @@ const KibanaReactContext = createKibanaReactContext({
} as unknown as Partial<CoreStart>);

interface Args {
ruleParams: RuleParams;
ruleParams: ErrorRateRuleParams;
metadata?: AlertMetadata;
}

Expand All @@ -42,7 +42,7 @@ export const CreatingInApmServiceOverview: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorRateRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down Expand Up @@ -78,7 +78,7 @@ export const CreatingInStackManagement: Story<Args> = ({
ruleParams,
metadata,
}) => {
const [params, setParams] = useState<RuleParams>(ruleParams);
const [params, setParams] = useState<ErrorRateRuleParams>(ruleParams);

function setRuleParams(property: string, value: any) {
setParams({ ...params, [property]: value });
Expand Down