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

[Security Solution][Detections] Rule Execution Log Feedback and Fixes Part Deux #130072

Merged
merged 39 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5e93888
Adds toast for resetting global search filters
spong Apr 13, 2022
ead5ad4
Mocks the missing mocks merrily
spong Apr 13, 2022
0b27bad
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 13, 2022
b61afbd
More missed mocks
spong Apr 13, 2022
c40fa6d
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 13, 2022
dfb6374
Last mock to update it looks like...
spong Apr 13, 2022
3cc941a
Removes RuleExecutionStatusType
spong Apr 14, 2022
a8f16c3
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 14, 2022
068ccd8
Adds RuleDetailsContextProvider to maintain state between tab selection
spong Apr 15, 2022
3ec3084
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 15, 2022
a77a303
Fixing new type constraints
spong Apr 15, 2022
9c8ea5a
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 18, 2022
3c4df6c
Fixing default statusFilter param to support receiving emptystring
spong Apr 18, 2022
a1a5247
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 18, 2022
2126a03
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Apr 19, 2022
9d393f5
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 19, 2022
8207539
Merge branch 'rule-execution-log-feedback-part-deux' of github.com:sp…
spong Apr 20, 2022
22a9ca7
Fixes RuleDurationFormat bugs and adds test coverage
spong Apr 20, 2022
f51c6eb
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 20, 2022
30daac6
Merge branch 'main' into rule-execution-log-feedback-part-deux
kibanamachine Apr 21, 2022
3623419
Adds support for disabled while running rule execution error
spong Apr 21, 2022
c858f64
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 21, 2022
5744372
Fixes aggs test and ensures keepPreviousData is set on useQuery hook
spong Apr 21, 2022
0ffd2de
Skips flakey test for time being...
spong Apr 21, 2022
b507344
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 27, 2022
d413637
Improving test integrity
spong Apr 27, 2022
ab736db
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 27, 2022
bdadcd8
Improving test integrity Part Deux
spong Apr 27, 2022
8704188
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 28, 2022
76e222f
Fixes cypress flake, adds table ui tests, fixes partial failure filte…
spong Apr 29, 2022
db4ca85
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong Apr 29, 2022
1bda037
Merge branch 'main' into rule-execution-log-feedback-part-deux
kibanamachine Apr 29, 2022
9581b83
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong May 2, 2022
22cc0c8
Fixes absolute-relative datepicker replacement, fixes showing 0 gap_d…
spong May 2, 2022
917d9cf
Removes scrollpane from exceptions viewer
spong May 2, 2022
32e12d3
Reverts gap duration empty value render change and renames gap_durati…
spong May 3, 2022
7f6ae5d
Merge branch 'main' of github.com:elastic/kibana into rule-execution-…
spong May 3, 2022
f8d0266
Merge branch 'main' into rule-execution-log-feedback-part-deux
spong May 3, 2022
5dc0da7
Merge branch 'main' into rule-execution-log-feedback-part-deux
spong May 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ export enum RuleExecutionStatus {

export const ruleExecutionStatus = enumeration('RuleExecutionStatus', RuleExecutionStatus);

export type RuleExecutionStatusType = t.TypeOf<typeof ruleExecutionStatus>;

export const ruleExecutionStatusOrder = PositiveInteger;
export type RuleExecutionStatusOrder = t.TypeOf<typeof ruleExecutionStatusOrder>;

Expand Down Expand Up @@ -130,7 +128,7 @@ export const aggregateRuleExecutionEvent = t.type({
timed_out: t.boolean,
indexing_duration_ms: t.number,
search_duration_ms: t.number,
gap_duration_ms: t.number,
gap_duration_s: t.number,
security_status: t.string,
security_message: t.string,
});
Expand All @@ -140,7 +138,7 @@ export type AggregateRuleExecutionEvent = t.TypeOf<typeof aggregateRuleExecution
export const executionLogTableSortColumns = t.keyof({
timestamp: IsoDateString,
duration_ms: t.number,
gap_duration_ms: t.number,
gap_duration_s: t.number,
indexing_duration_ms: t.number,
search_duration_ms: t.number,
schedule_delay_ms: t.number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,30 @@ import {
ExecutionLogTableSortColumns,
executionLogTableSortColumns,
ruleExecutionStatus,
RuleExecutionStatusType,
RuleExecutionStatus,
} from '../common';

/**
* Types the DefaultStatusFiltersStringArray as:
* - If undefined, then a default array will be set
* - If an array is sent in, then the array will be validated to ensure all elements are a ruleExecutionStatus
* - If an array is sent in, then the array will be validated to ensure all elements are a ruleExecutionStatus (or that the array is empty)
*/
export const DefaultStatusFiltersStringArray = new t.Type<
RuleExecutionStatusType[],
RuleExecutionStatusType[],
RuleExecutionStatus[],
RuleExecutionStatus[],
unknown
>(
'DefaultStatusFiltersStringArray',
t.array(ruleExecutionStatus).is,
(input, context): Either<t.Errors, RuleExecutionStatusType[]> => {
(input, context): Either<t.Errors, RuleExecutionStatus[]> => {
if (input == null) {
return t.success([]);
} else if (typeof input === 'string') {
return t.array(ruleExecutionStatus).validate(input.split(','), context);
if (input === '') {
return t.success([]);
} else {
return t.array(ruleExecutionStatus).validate(input.split(','), context);
}
} else {
return t.array(ruleExecutionStatus).validate(input, context);
}
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/security_solution/cypress/tasks/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const closeAlerts = () => {

export const expandFirstAlertActions = () => {
cy.get(TIMELINE_CONTEXT_MENU_BTN).should('be.visible');
cy.get(TIMELINE_CONTEXT_MENU_BTN).find('svg').should('have.class', 'euiIcon-isLoaded');
cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true });
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ const MyFlexItem = styled(EuiFlexItem)`
}
`;

const MyExceptionsContainer = styled(EuiFlexGroup)`
height: 600px;
overflow: hidden;
`;

const MyExceptionItemContainer = styled(EuiFlexGroup)`
margin: ${({ theme }) => `0 ${theme.eui.euiSize} ${theme.eui.euiSize} 0`};
`;
Expand Down Expand Up @@ -55,7 +50,7 @@ const ExceptionsViewerItemsComponent: React.FC<ExceptionsViewerItemsProps> = ({
onEditExceptionItem,
disableActions,
}): JSX.Element => (
<MyExceptionsContainer direction="column" className="eui-yScrollWithShadows">
<EuiFlexGroup direction="column" className="eui-yScrollWithShadows">
{showEmpty || showNoResults || isInitLoading ? (
<EuiFlexItem grow={1}>
<EuiEmptyPrompt
Expand Down Expand Up @@ -107,7 +102,7 @@ const ExceptionsViewerItemsComponent: React.FC<ExceptionsViewerItemsProps> = ({
</MyExceptionItemContainer>
</EuiFlexItem>
)}
</MyExceptionsContainer>
</EuiFlexGroup>
);

ExceptionsViewerItemsComponent.displayName = 'ExceptionsViewerItemsComponent';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ describe('VisualizationActions', () => {
addError: jest.fn(),
addSuccess: jest.fn(),
addWarning: jest.fn(),
remove: jest.fn(),
},
},
http: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jest.mock('../../../lib/kibana', () => ({
addError: jest.fn(),
addSuccess: jest.fn(),
addWarning: jest.fn(),
remove: jest.fn(),
}),
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ jest.mock('../../lib/kibana', () => ({
addError: jest.fn(),
addSuccess: jest.fn(),
addWarning: mockAddWarning,
remove: jest.fn(),
}),
useKibana: () => ({
services: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const createAppToastsMock = (): jest.Mocked<UseAppToasts> => ({
addError: jest.fn(),
addSuccess: jest.fn(),
addWarning: jest.fn(),
remove: jest.fn(),
api: {
get$: jest.fn(),
add: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ describe('useAppToasts', () => {
let addErrorMock: jest.Mock;
let addSuccessMock: jest.Mock;
let addWarningMock: jest.Mock;
let removeMock: jest.Mock;

beforeEach(() => {
addErrorMock = jest.fn();
addSuccessMock = jest.fn();
addWarningMock = jest.fn();
removeMock = jest.fn();
(useToasts as jest.Mock).mockImplementation(() => ({
addError: addErrorMock,
addSuccess: addSuccessMock,
addWarning: addWarningMock,
remove: removeMock,
}));
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { IEsError, isEsError } from '@kbn/data-plugin/public';
import { ErrorToastOptions, ToastsStart, Toast } from '@kbn/core/public';
import { useToasts } from '../lib/kibana';

export type UseAppToasts = Pick<ToastsStart, 'addSuccess' | 'addWarning'> & {
export type UseAppToasts = Pick<ToastsStart, 'addSuccess' | 'addWarning' | 'remove'> & {
api: ToastsStart;
addError: (error: unknown, options: ErrorToastOptions) => Toast;
};
Expand All @@ -36,6 +36,7 @@ export const useAppToasts = (): UseAppToasts => {
const addError = useRef(toasts.addError.bind(toasts)).current;
const addSuccess = useRef(toasts.addSuccess.bind(toasts)).current;
const addWarning = useRef(toasts.addWarning.bind(toasts)).current;
const remove = useRef(toasts.remove.bind(toasts)).current;

const _addError = useCallback(
(error: unknown, options: ErrorToastOptions) => {
Expand All @@ -46,8 +47,8 @@ export const useAppToasts = (): UseAppToasts => {
);

return useMemo(
() => ({ api: toasts, addError: _addError, addSuccess, addWarning }),
[_addError, addSuccess, addWarning, toasts]
() => ({ api: toasts, addError: _addError, addSuccess, addWarning, remove }),
[_addError, addSuccess, addWarning, remove, toasts]
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export const createStartServicesMock = (
theme: {
theme$: themeServiceMock.createTheme$(),
},
timelines: {
getLastUpdated: jest.fn(),
getFieldBrowser: jest.fn(),
},
} as unknown as StartServices;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jest.mock('../../../../common/lib/kibana/kibana_react', () => {
addWarning: jest.fn(),
addError: jest.fn(),
addSuccess: jest.fn(),
remove: jest.fn(),
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const fetchRuleExecutionEvents = async ({
duration_ms: 3866,
es_search_duration_ms: 1236,
execution_uuid: '88d15095-7937-462c-8f21-9763e1387cad',
gap_duration_ms: 0,
gap_duration_s: 0,
indexing_duration_ms: 95,
message:
"rule executed: siem.queryRule:fb1fc150-a292-11ec-a2cf-c1b28b0392b0: 'Lots of Execution Events'",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ describe('Detections Rules API', () => {
start: '2001-01-01T17:00:00.000Z',
end: '2001-01-02T17:00:00.000Z',
queryText: '',
statusFilters: '',
statusFilters: [],
signal: abortCtrl.signal,
});

Expand Down Expand Up @@ -659,7 +659,7 @@ describe('Detections Rules API', () => {
start: 'now-30',
end: 'now',
queryText: '',
statusFilters: '',
statusFilters: [],
signal: abortCtrl.signal,
});
expect(response).toEqual(responseMock);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { camelCase } from 'lodash';
import dateMath from '@kbn/datemath';
import { HttpStart } from '@kbn/core/public';
Expand All @@ -18,7 +19,11 @@ import {
DETECTION_ENGINE_RULES_PREVIEW,
detectionEngineRuleExecutionEventsUrl,
} from '../../../../../common/constants';
import { BulkAction } from '../../../../../common/detection_engine/schemas/common';
import {
AggregateRuleExecutionEvent,
BulkAction,
RuleExecutionStatus,
} from '../../../../../common/detection_engine/schemas/common';
import {
FullResponseSchema,
PreviewResponse,
Expand Down Expand Up @@ -320,11 +325,11 @@ export const exportRules = async ({
* @param start Start daterange either in UTC ISO8601 or as datemath string (e.g. `2021-12-29T02:44:41.653Z` or `now-30`)
* @param end End daterange either in UTC ISO8601 or as datemath string (e.g. `2021-12-29T02:44:41.653Z` or `now/w`)
* @param queryText search string in querystring format (e.g. `event.duration > 1000 OR kibana.alert.rule.execution.metrics.execution_gap_duration_s > 100`)
* @param statusFilters comma separated string of `statusFilters` (e.g. `succeeded,failed,partial failure`)
* @param statusFilters RuleExecutionStatus[] array of `statusFilters` (e.g. `succeeded,failed,partial failure`)
* @param page current page to fetch
* @param perPage number of results to fetch per page
* @param sortField field to sort by
* @param sortOrder what order to sort by (e.g. `asc` or `desc`)
* @param sortField keyof AggregateRuleExecutionEvent field to sort by
* @param sortOrder SortOrder what order to sort by (e.g. `asc` or `desc`)
* @param signal AbortSignal Optional signal for cancelling the request
*
* @throws An error if response is not OK
Expand All @@ -345,11 +350,11 @@ export const fetchRuleExecutionEvents = async ({
start: string;
end: string;
queryText?: string;
statusFilters?: string;
statusFilters?: RuleExecutionStatus[];
page?: number;
perPage?: number;
sortField?: string;
sortOrder?: string;
sortField?: keyof AggregateRuleExecutionEvent;
sortOrder?: SortOrder;
signal?: AbortSignal;
}): Promise<GetAggregateRuleExecutionEventsResponse> => {
const url = detectionEngineRuleExecutionEventsUrl(ruleId);
Expand All @@ -361,7 +366,7 @@ export const fetchRuleExecutionEvents = async ({
start: startDate?.utc().toISOString(),
end: endDate?.utc().toISOString(),
query_text: queryText,
status_filters: statusFilters,
status_filters: statusFilters?.sort()?.join(','),
page,
per_page: perPage,
sort_field: sortField,
Expand Down
Loading