Skip to content

Commit

Permalink
Rule execution log support backfill rule run types (elastic#183898)
Browse files Browse the repository at this point in the history
## Rule execution log support backfill rule run types


https://github.com/elastic/kibana/assets/7609147/38662629-d600-449b-949a-2aa0166ea3a1

### Feature flag
`manualRuleRunEnabled`

### Description

- Add new column for table with rule run type "Manual" / "Scheduled" 
- Add new switch to show column with source event time range for
backfill run
- event execution log api support `run_type_filters` filters as
parameter with values like "standard" and "backfill"
- event execution log result will return new field for backfill runs -
`backfill`

### How to test 

1 . Enable feature flag - `manualRuleRunEnabled`
2. For you rule call schedule api
`/internal/alerting/rules/backfill/_schedule` `POST`
With this body (put your values for rule id and date range):
```
[{"rule_id":"58b4b926-6348-4c23-be1f-870a461fa342","start":"2024-05-21T13:00:00.000Z","end":"2024-05-21T14:05:00.000Z"}]
```

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
nkhristinin and kibanamachine committed May 28, 2024
1 parent df910f7 commit 69b28f3
Show file tree
Hide file tree
Showing 47 changed files with 1,160 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ describe('AlertingEventLogger', () => {
saved_objects: [
// @ts-ignore
...event.kibana?.saved_objects,
{ id: 'bbb', type: 'alert', type_id: 'test' },
{ id: 'bbb', type: 'alert', type_id: 'test', rel: 'primary' },
],
},
});
Expand Down Expand Up @@ -472,7 +472,7 @@ describe('AlertingEventLogger', () => {
saved_objects: [
// @ts-ignore
...event.kibana?.saved_objects,
{ id: 'bbb', type: 'alert', type_id: 'test' },
{ id: 'bbb', type: 'alert', type_id: 'test', rel: 'primary' },
],
},
});
Expand Down Expand Up @@ -567,7 +567,7 @@ describe('AlertingEventLogger', () => {
saved_objects: [
// @ts-ignore
...event.kibana?.saved_objects,
{ id: 'bbb', type: 'alert', type_id: 'test' },
{ id: 'bbb', type: 'alert', type_id: 'test', rel: 'primary' },
],
},
});
Expand Down Expand Up @@ -754,7 +754,7 @@ describe('AlertingEventLogger', () => {
const event = createAlertRecord(
backfillContext,
ruleData,
[adHocRunSO, { id: 'bbb', type: 'alert', typeId: 'test' }],
[adHocRunSO, { id: 'bbb', type: 'alert', typeId: 'test', relation: 'primary' }],
alert
);

Expand Down Expand Up @@ -1130,7 +1130,7 @@ describe('AlertingEventLogger', () => {
saved_objects: [
// @ts-ignore
...event.kibana?.saved_objects,
{ id: 'bbb', type: 'alert', type_id: 'test' },
{ id: 'bbb', type: 'alert', type_id: 'test', rel: 'primary' },
],
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export class AlertingEventLogger {
typeId: type?.id,
type: RULE_SAVED_OBJECT_TYPE,
namespace: this.context?.namespace,
relation: SAVED_OBJECT_REL_PRIMARY,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ export * from './model/execution_result.gen';
export * from './model/execution_settings';
export * from './model/execution_status.gen';
export * from './model/execution_status';
export * from './model/execution_run_type.gen';
export * from './model/execution_summary.gen';
export * from './model/log_level';
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ export const RuleExecutionResult = z.object({
gap_duration_s: z.number().int(),
security_status: z.string(),
security_message: z.string(),
/**
* Backfill information for the rule execution result with source event date range
*/
backfill: z
.object({
from: z.string().datetime(),
to: z.string().datetime(),
})
.optional(),
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ components:
type: string
security_message:
type: string
backfill:
type: object
description: Backfill information for the rule execution result with source event date range
properties:
from:
type: string
format: date-time
to:
type: string
format: date-time
required:
- from
- to
required:
- execution_uuid
- timestamp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 { z } from 'zod';

/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Execution Run Type Schema
* version: not applicable
*/

/**
* Type of rule execution run.
*/
export type RuleRunType = z.infer<typeof RuleRunType>;
export const RuleRunType = z.enum(['backfill', 'standard']);
export type RuleRunTypeEnum = typeof RuleRunType.enum;
export const RuleRunTypeEnum = RuleRunType.enum;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
openapi: 3.0.0
info:
title: Execution Run Type Schema
version: not applicable
paths: {}
components:
x-codegen-enabled: true
schemas:
RuleRunType:
type: string
description: Type of rule execution run.
enum:
- backfill
- standard
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ArrayFromString } from '@kbn/zod-helpers';
*/

import { RuleExecutionStatus } from '../../model/execution_status.gen';
import { RuleRunType } from '../../model/execution_run_type.gen';
import {
SortFieldOfRuleExecutionResult,
RuleExecutionResult,
Expand All @@ -44,6 +45,10 @@ export const GetRuleExecutionResultsRequestQuery = z.object({
* Comma-separated list of rule execution statuses to filter results by
*/
status_filters: ArrayFromString(RuleExecutionStatus).optional().default([]),
/**
* Comma-separated list of rule run types to filter results by
*/
run_type_filters: ArrayFromString(RuleRunType).optional().default([]),
/**
* Field to sort results by
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ paths:
items:
$ref: '../../model/execution_status.schema.yaml#/components/schemas/RuleExecutionStatus'
default: []
- name: run_type_filters
in: query
required: false
description: Comma-separated list of rule run types to filter results by
schema:
type: array
items:
$ref: '../../model/execution_run_type.schema.yaml#/components/schemas/RuleRunType'
default: []
- name: sort_field
in: query
required: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ describe('Request schema of Get rule execution results', () => {
sort_order: 'desc',
start: '2021-08-01T00:00:00.000Z',
status_filters: [],
run_type_filters: [],
});
});
});
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,9 @@ export const NEW_FEATURES_TOUR_STORAGE_KEYS = {
export const RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY =
'securitySolution.ruleDetails.ruleExecutionLog.showMetrics.v8.2';

export const RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_SOURCE_EVENT_TIME_RANGE_STORAGE_KEY =
'securitySolution.ruleDetails.ruleExecutionLog.showSourceEventTimeRange.v8.15';

// TODO: https://github.com/elastic/kibana/pull/142950
/**
* Error codes that can be thrown during _bulk_action API dry_run call and be processed and displayed to end user
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 type { RuleExecutionStatus, RuleRunType } from '../../api/detection_engine/rule_monitoring';
import {
RuleExecutionStatusEnum,
RuleRunTypeEnum,
} from '../../api/detection_engine/rule_monitoring';

export const RUN_TYPE_FILTERS: RuleRunType[] = [RuleRunTypeEnum.standard, RuleRunTypeEnum.backfill];

export const STATUS_FILTERS: RuleExecutionStatus[] = [
RuleExecutionStatusEnum.succeeded,
RuleExecutionStatusEnum.failed,
RuleExecutionStatusEnum['partial failure'],
];
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ export const allowedExperimentalValues = Object.freeze({
* Enables the new rule's bulk action to manage custom highlighted fields
*/
bulkCustomHighlightedFieldsEnabled: false,

/**
* Enables the manual rule run
*/
manualRuleRunEnabled: false,
});

type ExperimentalConfigKeys = Array<keyof ExperimentalFeatures>;
Expand Down
14 changes: 14 additions & 0 deletions x-pack/plugins/security_solution/public/common/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,17 @@ export const getAgentTypeName = (agentType: ResponseActionAgentType) => {
return agentType;
}
};

export const RULE_EXECUTION_TYPE_BACKFILL = i18n.translate(
'xpack.securitySolution.detectionEngine.executionRunType.backfill',
{
defaultMessage: 'Manual',
}
);

export const RULE_EXECUTION_TYPE_STANDARD = i18n.translate(
'xpack.securitySolution.detectionEngine.executionRunType.standard',
{
defaultMessage: 'Scheduled',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export const useRuleDetailsContextMock = {
sortField: 'timestamp',
sortDirection: 'desc',
},
runTypeFilters: [],
showSourceEventTimeRange: true,
},
actions: {
setEnd: jest.fn(),
Expand All @@ -45,6 +47,8 @@ export const useRuleDetailsContextMock = {
setSortField: jest.fn(),
setStart: jest.fn(),
setStatusFilters: jest.fn(),
setRunTypeFilters: jest.fn(),
setShowSourceEventTimeRange: jest.fn(),
},
},
}),
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import type {

import { getEmptyValue } from '../../../../../common/components/empty_value';
import { FormattedDate } from '../../../../../common/components/formatted_date';
import {
RULE_EXECUTION_TYPE_BACKFILL,
RULE_EXECUTION_TYPE_STANDARD,
} from '../../../../../common/translations';
import { ExecutionStatusIndicator } from '../../../../rule_monitoring';
import { PopoverTooltip } from '../../../../rule_management_ui/components/rules_table/popover_tooltip';
import { TableHeaderTooltipCell } from '../../../../rule_management_ui/components/rules_table/table_header_tooltip_cell';
Expand Down Expand Up @@ -79,6 +83,19 @@ export const EXECUTION_LOG_COLUMNS: Array<EuiBasicTableColumn<RuleExecutionResul
truncateText: false,
width: '10%',
},
{
name: i18n.COLUMN_TYPE,
field: 'type',
sortable: false,
width: '10%',
render: (value, record) => {
return (
<EuiText size="s">
{record.backfill ? RULE_EXECUTION_TYPE_BACKFILL : RULE_EXECUTION_TYPE_STANDARD}
</EuiText>
);
},
},
{
field: 'timestamp',
name: (
Expand Down Expand Up @@ -139,6 +156,34 @@ export const getMessageColumn = (width: string) => ({
width,
});

export const getSourceEventTimeRangeColumns = () => [
{
name: (
<TableHeaderTooltipCell
title={i18n.COLUMN_SOURCE_EVENT_TIME_RANGE}
tooltipContent={i18n.COLUMN_SOURCE_EVENT_TIME_RANGE_TOOLTIP}
/>
),
field: 'backfill',
render: (backfill: { to: string; from: string }) => {
return backfill ? (
<div>
<div>
<FormattedDate value={backfill.to} fieldName="backfill.to" />
</div>
<EuiText textAlign="center">{'-'}</EuiText>
<div>
<FormattedDate value={backfill.from} fieldName="backfill.from" />
</div>
</div>
) : (
getEmptyValue()
);
},
width: '20%',
},
];

export const getExecutionLogMetricsColumns = (
docLinks: DocLinksStart
): Array<EuiBasicTableColumn<RuleExecutionResult>> => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import React from 'react';
import { ExecutionLogSearchBar } from './execution_log_search_bar';
import { noop } from 'lodash/fp';

jest.mock('../../../../../common/hooks/use_experimental_features', () => ({
useIsExperimentalFeatureEnabled: jest.fn(),
}));

/**
* NOTE: This component is currently not shown in the UI as custom search queries
* are not yet fully supported by the Rule Execution Log aggregation API since
Expand All @@ -27,6 +31,8 @@ describe('ExecutionLogSearchBar', () => {
onlyShowFilters={true}
selectedStatuses={[]}
onStatusFilterChange={noop}
selectedRunTypes={[]}
onRunTypeFilterChange={noop}
onSearch={noop}
/>
);
Expand Down
Loading

0 comments on commit 69b28f3

Please sign in to comment.