From 31320e7c1c1e9a9ee5f50399eb7198a1f8a1fe78 Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Thu, 4 Mar 2021 14:22:37 -0700 Subject: [PATCH] [Security Solutions] Sets our default date time to be "today" instead of "Last 24 hours" to enable cachability and fixes one date math bug in the URL (#93548) ## Summary Enables caching in our application by setting the default date time of our application to be `from: now/d` and `to: now/d`. When users go to the advanced settings they will see this now: Screen Shot 2021-03-04 at 11 53 08 AM In their date time bars on page loads they will see today instead of 24 hours: Screen Shot 2021-03-04 at 11 50 18 AM When before they used to have `from: now-24` and `to: now`. This new date time frame plays well with Elastic caches and no longer "busts" them for users on each page request. Now users will send the same date time frame on each query which will cache the views as the default. This also fixes a small bug with the URL's where the "to" was not being rounded up when it was a dynamic date time on first load. For example if you went to the URL, `/app/security/hosts/allHosts` with no additional state information but have a default of `from: now/d` and `to: now/d` it would not round up the date time. Now it rounds it up through the date math utilities which only rounds when it sees that it is a dynamic date math. When requests are being sent, expect to see this where you have `from` rounded down and `to rounded up. This should be a consistent non-sliding date time math for caching to operate: Screen Shot 2021-03-04 at 11 33 11 AM If you change the `to` to be another date math such as `now+1d/d` expect to see it also rounded up. This behavior mirrors that of discover: Screen Shot 2021-03-04 at 11 33 11 AM You can manually verify this behavior by setting the same now dates in discover as well as security solutions and both should work as is even when you remove the URL state from the right side of a `?` ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../security_solution/common/constants.ts | 4 ++-- .../components/query_bar/index.test.tsx | 4 ++-- .../super_date_picker/index.test.tsx | 10 ++++----- .../common/store/inputs/helpers.test.ts | 8 +++---- .../utils/default_date_settings.test.ts | 21 +++++++++++++++++++ .../common/utils/default_date_settings.ts | 14 +++++++++---- .../recent_cases/no_cases/index.test.tsx | 2 +- .../timeline/query_bar/index.test.tsx | 4 ++-- 8 files changed, 47 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index c277ce369dca0..994e420260b25 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -28,8 +28,8 @@ export const DEFAULT_SEARCH_AFTER_PAGE_SIZE = 100; export const DEFAULT_ANOMALY_SCORE = 'securitySolution:defaultAnomalyScore'; export const DEFAULT_MAX_TABLE_QUERY_SIZE = 10000; export const DEFAULT_SCALE_DATE_FORMAT = 'dateFormat:scaled'; -export const DEFAULT_FROM = 'now-24h'; -export const DEFAULT_TO = 'now'; +export const DEFAULT_FROM = 'now/d'; +export const DEFAULT_TO = 'now/d'; export const DEFAULT_INTERVAL_PAUSE = true; export const DEFAULT_INTERVAL_TYPE = 'manual'; export const DEFAULT_INTERVAL_VALUE = 300000; // ms diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx index 1e998f9798e97..ca1a93e25534a 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx @@ -82,8 +82,8 @@ describe('QueryBar ', () => { expect(searchBarProps).toEqual({ dataTestSubj: undefined, - dateRangeFrom: 'now-24h', - dateRangeTo: 'now', + dateRangeFrom: 'now/d', + dateRangeTo: 'now/d', filters: [], indexPatterns: [ { diff --git a/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.test.tsx index 6d52ea8c011c5..d10f0eb28fadc 100644 --- a/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/super_date_picker/index.test.tsx @@ -135,8 +135,8 @@ describe('SIEM Super Date Picker', () => { expect(store.getState().inputs.global.timerange.kind).toBe('relative'); }); - test('Make Sure it is last 24 hours date', () => { - expect(store.getState().inputs.global.timerange.fromStr).toBe('now-24h'); + test('Make Sure it is last "now-${x}h" where ${x} is in hours date', () => { + expect(store.getState().inputs.global.timerange.fromStr).toMatch(/^now-[0-9]+h/); expect(store.getState().inputs.global.timerange.toStr).toBe('now'); }); @@ -206,7 +206,7 @@ describe('SIEM Super Date Picker', () => { expect(wrapper.find('div.euiQuickSelectPopover__section').at(1).text()).toBe('Today'); }); - test('Today and Last 24 hours are in Recently used date ranges', () => { + test('Today and "Last ${x} hours" where ${x} is in hours are in Recently used date ranges', () => { wrapper .find('[data-test-subj="superDatePickerToggleQuickMenuButton"]') .first() @@ -216,8 +216,8 @@ describe('SIEM Super Date Picker', () => { wrapper.find('button.euiQuickSelect__applyButton').first().simulate('click'); wrapper.update(); - expect(wrapper.find('div.euiQuickSelectPopover__section').at(1).text()).toBe( - 'Last 24 hoursToday' + expect(wrapper.find('div.euiQuickSelectPopover__section').at(1).text()).toMatch( + /^Last\s[0-9]+\shoursToday/ ); }); diff --git a/x-pack/plugins/security_solution/public/common/store/inputs/helpers.test.ts b/x-pack/plugins/security_solution/public/common/store/inputs/helpers.test.ts index 6dac1a20fefc0..c8848e6f7ffc7 100644 --- a/x-pack/plugins/security_solution/public/common/store/inputs/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/store/inputs/helpers.test.ts @@ -276,10 +276,10 @@ describe('Inputs', () => { ], timerange: { from: '2020-07-07T08:20:18.966Z', - fromStr: 'now-24h', + fromStr: 'now/d', kind: 'relative', to: '2020-07-08T08:20:18.966Z', - toStr: 'now', + toStr: 'now/d', }, query: { query: '', language: 'kuery' }, filters: [], @@ -293,10 +293,10 @@ describe('Inputs', () => { queries: [], timerange: { from: '2020-07-07T08:20:18.966Z', - fromStr: 'now-24h', + fromStr: 'now/d', kind: 'relative', to: '2020-07-08T08:20:18.966Z', - toStr: 'now', + toStr: 'now/d', }, query: { query: '', language: 'kuery' }, filters: [], diff --git a/x-pack/plugins/security_solution/public/common/utils/default_date_settings.test.ts b/x-pack/plugins/security_solution/public/common/utils/default_date_settings.test.ts index 26d25a49f43cf..2c5f9d2dda471 100644 --- a/x-pack/plugins/security_solution/public/common/utils/default_date_settings.test.ts +++ b/x-pack/plugins/security_solution/public/common/utils/default_date_settings.test.ts @@ -315,6 +315,22 @@ describe('getTimeRangeSettings', () => { expect(to).toBe(new Date(DEFAULT_TO_DATE).toISOString()); }); + test('should round up "to" when from and to are both "now/d"', () => { + const mockTo = 'now/d'; + const mockFrom = 'now/d'; + mockTimeRange({ from: mockFrom, to: mockTo }); + const { to } = getTimeRangeSettings(); + expect(to).toContain('59:59.999Z'); + }); + + test('should round up "to" when from and to are different date maths', () => { + const mockTo = 'now/d'; + const mockFrom = 'now/d+1'; + mockTimeRange({ from: mockFrom, to: mockTo }); + const { to } = getTimeRangeSettings(); + expect(to).toContain('59:59.999Z'); + }); + test('should return the DEFAULT_TO_DATE when the from value is malformed', () => { const malformedTimeRange = { from: true }; if (isMalformedTimeRange(malformedTimeRange)) { @@ -506,5 +522,10 @@ describe('getIntervalSettings', () => { const value = parseDateWithDefault('trashed string', moment('1950-05-31T13:03:54.234Z')); expect(value.toISOString()).toBe(new Date('1950-05-31T13:03:54.234Z').toISOString()); }); + + test('should round up a valid date string and end with 59:59.999Z', () => { + const value = parseDateWithDefault('now/d', moment('1950-05-31T13:03:54.234Z'), true); + expect(value.toISOString()).toContain('59:59.999Z'); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/default_date_settings.ts b/x-pack/plugins/security_solution/public/common/utils/default_date_settings.ts index 7a8645cd0eb10..ed747dbcf22bb 100644 --- a/x-pack/plugins/security_solution/public/common/utils/default_date_settings.ts +++ b/x-pack/plugins/security_solution/public/common/utils/default_date_settings.ts @@ -51,8 +51,7 @@ export const getTimeRangeSettings = (uiSettings = true) => { const fromStr = (isString(timeRange?.from) && timeRange?.from) || DEFAULT_FROM; const toStr = (isString(timeRange?.to) && timeRange?.to) || DEFAULT_TO; const from = parseDateWithDefault(fromStr, DEFAULT_FROM_MOMENT).toISOString(); - const to = parseDateWithDefault(toStr, DEFAULT_TO_MOMENT).toISOString(); - + const to = parseDateWithDefault(toStr, DEFAULT_TO_MOMENT, true).toISOString(); return { from, fromStr, to, toStr }; }; @@ -72,11 +71,18 @@ export const getIntervalSettings = (uiSettings = true): Policy => { return { kind, duration }; }; +/** + * Parses a date and returns the default if the date string is not valid. + * @param dateString The date string to parse + * @param defaultDate The defaultDate if we cannot parse the dateMath + * @returns The moment of the date time parsed + */ export const parseDateWithDefault = ( dateString: string, - defaultDate: moment.Moment + defaultDate: moment.Moment, + roundUp: boolean = false ): moment.Moment => { - const date = dateMath.parse(dateString); + const date = dateMath.parse(dateString, { roundUp }); if (date != null && date.isValid()) { return date; } else { diff --git a/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx index beb55b3833ad4..ccb2d776f6e61 100644 --- a/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/recent_cases/no_cases/index.test.tsx @@ -34,7 +34,7 @@ describe('RecentCases', () => { wrapper.find(`[data-test-subj="no-cases-create-case"]`).first().simulate('click'); expect(navigateToApp).toHaveBeenCalledWith('securitySolution:case', { path: - "/create?sourcerer=(default:!('apm-*-transaction*','auditbeat-*','endgame-*','filebeat-*','logs-*','packetbeat-*','winlogbeat-*'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "/create?sourcerer=(default:!('apm-*-transaction*','auditbeat-*','endgame-*','filebeat-*','logs-*','packetbeat-*','winlogbeat-*'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now%2Fd,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now%2Fd)))", }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx index fef579d78b620..0f0f2a8641ac0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx @@ -96,8 +96,8 @@ describe('Timeline QueryBar ', () => { ); const queryBarProps = wrapper.find(QueryBar).props(); - expect(queryBarProps.dateRangeFrom).toEqual('now-24h'); - expect(queryBarProps.dateRangeTo).toEqual('now'); + expect(queryBarProps.dateRangeFrom).toEqual('now/d'); + expect(queryBarProps.dateRangeTo).toEqual('now/d'); expect(queryBarProps.filterQuery).toEqual({ query: 'here: query', language: 'kuery' }); expect(queryBarProps.savedQuery).toEqual(undefined); expect(queryBarProps.filters).toHaveLength(1);