-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[App Search] Added the log retention panel to the Settings page #82982
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
Changes from 3 commits
d167e3b
c01d68f
efdb51e
bddc519
7db5b62
406a04d
13b5697
16454f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License; | ||
| * you may not use this file except in compliance with the Elastic License. | ||
| */ | ||
|
|
||
| import '../../../../__mocks__/kea.mock'; | ||
| import '../../../../__mocks__/shallow_useeffect.mock'; | ||
|
|
||
| import { setMockActions, setMockValues } from '../../../../__mocks__'; | ||
|
|
||
| import React from 'react'; | ||
| import { shallow } from 'enzyme'; | ||
|
|
||
| import { LogRetentionPanel } from './log_retention_panel'; | ||
| import { ILogRetention } from './types'; | ||
|
|
||
| describe('<LogRetentionPanel />', () => { | ||
| const actions = { | ||
| fetchLogRetention: jest.fn(), | ||
| toggleLogRetention: jest.fn(), | ||
| }; | ||
|
|
||
| beforeEach(() => { | ||
| jest.clearAllMocks(); | ||
| setMockActions(actions); | ||
| }); | ||
|
|
||
| it('renders', () => { | ||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect(logRetentionPanel.find('div[data-test-subj="LogRetentionPanel"]')).toHaveLength(1); | ||
| }); | ||
|
|
||
| it('initializes data on mount', () => { | ||
| shallow(<LogRetentionPanel />); | ||
| expect(actions.fetchLogRetention).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| it('renders Analytics switch off when analytics log retention is false in LogRetentionLogic ', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| analytics: { | ||
| enabled: false, | ||
| }, | ||
| }), | ||
| }); | ||
|
|
||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAnalyticsSwitch"]`).prop('checked') | ||
| ).toEqual(false); | ||
| }); | ||
|
|
||
| it('renders Analytics switch on when analyticsLogRetention is true in LogRetentionLogic ', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| analytics: { | ||
| enabled: true, | ||
| }, | ||
| }), | ||
| }); | ||
|
|
||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAnalyticsSwitch"]`).prop('checked') | ||
| ).toEqual(true); | ||
| }); | ||
|
|
||
| it('renders API switch off when apiLogRetention is false in LogRetentionLogic ', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| api: { | ||
| enabled: false, | ||
| }, | ||
| }), | ||
| }); | ||
|
|
||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAPISwitch"]`).prop('checked') | ||
| ).toEqual(false); | ||
| }); | ||
|
|
||
| it('renders API switch on when apiLogRetention is true in LogRetentionLogic ', () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Not a change request] It might be interesting (later, as tech debt) to combine these two tests into a single test that tests both true/false. Might save on some setup time and combines the tests conceptually. I'd have to DRY out a rerender helper of some kind though. const logRetentionPanel = shallow(<LogRetentionPanel />);
setMockValues({ ... });
logRetentionPanel.setProps({}); // rerenders/updates component
expect(switchIsChecked).toEqual(false);
setMockValues({ ... });
logRetentionPanel.setProps({}); // rerenders/updates component
expect(switchIsChecked).toEqual(true);
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. |
||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| api: { | ||
| enabled: true, | ||
| }, | ||
| }), | ||
| }); | ||
|
|
||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAPISwitch"]`).prop('checked') | ||
| ).toEqual(true); | ||
| }); | ||
|
|
||
| it('enables both switches when isLogRetentionUpdating is false', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({}), | ||
| }); | ||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAnalyticsSwitch"]`).prop('disabled') | ||
| ).toEqual(false); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAPISwitch"]`).prop('disabled') | ||
| ).toEqual(false); | ||
| }); | ||
|
|
||
| it('disables both switches when isLogRetentionUpdating is true', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: true, | ||
| logRetention: mockLogRetention({}), | ||
| }); | ||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
|
|
||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAnalyticsSwitch"]`).prop('disabled') | ||
| ).toEqual(true); | ||
| expect( | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAPISwitch"]`).prop('disabled') | ||
| ).toEqual(true); | ||
| }); | ||
|
|
||
| it('calls toggleLogRetention when analytics log retention option is changed', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| analytics: { | ||
| enabled: false, | ||
| }, | ||
| }), | ||
| }); | ||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| logRetentionPanel | ||
| .find(`[data-test-subj="LogRetentionPanelAnalyticsSwitch"]`) | ||
| .simulate('change'); | ||
| expect(actions.toggleLogRetention).toHaveBeenCalledWith('analytics'); | ||
| }); | ||
|
|
||
| it('calls toggleLogRetention when api log retention option is changed', () => { | ||
| setMockValues({ | ||
| isLogRetentionUpdating: false, | ||
| logRetention: mockLogRetention({ | ||
| analytics: { | ||
| enabled: false, | ||
| }, | ||
| }), | ||
| }); | ||
| const logRetentionPanel = shallow(<LogRetentionPanel />); | ||
| logRetentionPanel.find(`[data-test-subj="LogRetentionPanelAPISwitch"]`).simulate('change'); | ||
cee-chen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| expect(actions.toggleLogRetention).toHaveBeenCalledWith('api'); | ||
| }); | ||
| }); | ||
|
|
||
| function mockLogRetention(logRetention: Partial<ILogRetention>) { | ||
JasonStoltz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const baseLogRetention = { | ||
| analytics: { | ||
| disabledAt: null, | ||
| enabled: true, | ||
| retentionPolicy: { isDefault: true, minAgeDays: 180 }, | ||
| }, | ||
| api: { | ||
| disabledAt: null, | ||
| enabled: true, | ||
| retentionPolicy: { isDefault: true, minAgeDays: 180 }, | ||
| }, | ||
| }; | ||
|
|
||
| return { | ||
| analytics: { | ||
| ...baseLogRetention.analytics, | ||
| ...logRetention.analytics, | ||
| }, | ||
| api: { | ||
| ...baseLogRetention.api, | ||
| ...logRetention.api, | ||
| }, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License; | ||
| * you may not use this file except in compliance with the Elastic License. | ||
| */ | ||
|
|
||
| import React, { useEffect } from 'react'; | ||
| import { i18n } from '@kbn/i18n'; | ||
|
|
||
| import { EuiLink, EuiSpacer, EuiSwitch, EuiText, EuiTextColor, EuiTitle } from '@elastic/eui'; | ||
| import { useActions, useValues } from 'kea'; | ||
|
|
||
| import { LogRetentionLogic } from './log_retention_logic'; | ||
| import { AnalyticsLogRetentionMessage, ApiLogRetentionMessage } from './messaging'; | ||
| import { ELogRetentionOptions } from './types'; | ||
|
|
||
| export const LogRetentionPanel: React.FC = () => { | ||
| const { toggleLogRetention, fetchLogRetention } = useActions(LogRetentionLogic); | ||
|
|
||
| const { logRetention, isLogRetentionUpdating } = useValues(LogRetentionLogic); | ||
|
|
||
| const hasILM = logRetention !== null; | ||
| const analyticsLogRetentionSettings = logRetention?.[ELogRetentionOptions.Analytics]; | ||
| const apiLogRetentionSettings = logRetention?.[ELogRetentionOptions.API]; | ||
|
|
||
| useEffect(() => { | ||
| fetchLogRetention(); | ||
| }, []); | ||
|
|
||
| return ( | ||
| <div data-test-subj="LogRetentionPanel"> | ||
| <EuiTitle size="s"> | ||
| <h2> | ||
| {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.title', { | ||
| defaultMessage: 'Log Retention', | ||
| })} | ||
| </h2> | ||
| </EuiTitle> | ||
| <EuiText> | ||
| <p> | ||
| {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.description', { | ||
| defaultMessage: 'Manage the default write settings for API Logs and Analytics.', | ||
| })}{' '} | ||
| <EuiLink | ||
| href="https://www.elastic.co/guide/en/app-search/current/logs.html" | ||
| target="_blank" | ||
| > | ||
| {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.learnMore', { | ||
| defaultMessage: 'Learn more about retention settings.', | ||
| })} | ||
| </EuiLink> | ||
| </p> | ||
| </EuiText> | ||
| <EuiSpacer size="m" /> | ||
| <EuiText> | ||
| <EuiSwitch | ||
| label={ | ||
| <> | ||
| <strong> | ||
| {i18n.translate( | ||
| 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.label', | ||
| { | ||
| defaultMessage: 'Analytics Logs', | ||
| } | ||
| )} | ||
| </strong>{' '} | ||
| {hasILM && ( | ||
JasonStoltz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <EuiTextColor color="subdued"> | ||
| <AnalyticsLogRetentionMessage /> | ||
| </EuiTextColor> | ||
| )} | ||
| </> | ||
| } | ||
| checked={!!analyticsLogRetentionSettings?.enabled} | ||
| onChange={() => toggleLogRetention(ELogRetentionOptions.Analytics)} | ||
| disabled={isLogRetentionUpdating} | ||
| data-test-subj="LogRetentionPanelAnalyticsSwitch" | ||
| /> | ||
| </EuiText> | ||
| <EuiSpacer size="m" /> | ||
| <EuiText> | ||
| <EuiSwitch | ||
| label={ | ||
| <> | ||
| <strong> | ||
| {i18n.translate( | ||
| 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.label', | ||
| { | ||
| defaultMessage: 'API Logs', | ||
| } | ||
| )} | ||
| </strong>{' '} | ||
| {logRetention !== null && ( | ||
JasonStoltz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
JasonStoltz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <EuiTextColor color="subdued"> | ||
| <ApiLogRetentionMessage /> | ||
| </EuiTextColor> | ||
| )} | ||
| </> | ||
| } | ||
| checked={!!apiLogRetentionSettings?.enabled} | ||
| onChange={() => toggleLogRetention(ELogRetentionOptions.API)} | ||
| disabled={isLogRetentionUpdating} | ||
| data-test-subj="LogRetentionPanelAPISwitch" | ||
| /> | ||
| </EuiText> | ||
| </div> | ||
| ); | ||
| }; | ||
Uh oh!
There was an error while loading. Please reload this page.