diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/index.ts new file mode 100644 index 0000000000000..1dba9c94ed724 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { LogRetentionCallout } from './log_retention_callout'; +export { LogRetentionTooltip } from './log_retention_tooltip'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx new file mode 100644 index 0000000000000..d990648682b78 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.test.tsx @@ -0,0 +1,101 @@ +/* + * 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__/shallow_useeffect.mock'; +import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; +import { mountWithIntl } from '../../../../__mocks__'; + +import React from 'react'; +import { shallow } from 'enzyme'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; + +import { LogRetentionOptions } from '../'; +import { LogRetentionCallout } from './'; + +describe('LogRetentionCallout', () => { + const actions = { fetchLogRetention: jest.fn() }; + const values = { myRole: { canManageLogSettings: true } }; + const DISABLED = { + disabledAt: '01 Jan 1970 12:00:00 +0000', + enabled: false, + }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockActions(actions); + }); + + it('renders an analytics callout', () => { + setMockValues({ ...values, logRetention: { analytics: DISABLED } }); + const wrapper = mountWithIntl(); + + expect(wrapper.find(EuiCallOut)).toHaveLength(1); + expect(wrapper.find('.euiCallOutHeader__title').text()).toEqual( + 'Analytics have been disabled since January 1, 1970.' + ); + expect(wrapper.find(EuiLink)).toHaveLength(1); + expect(wrapper.find('p').text()).toEqual('To manage analytics & logging, visit your settings.'); + }); + + it('renders an API callout', () => { + setMockValues({ ...values, logRetention: { api: DISABLED } }); + const wrapper = mountWithIntl(); + + expect(wrapper.find(EuiCallOut)).toHaveLength(1); + expect(wrapper.find('.euiCallOutHeader__title').text()).toEqual( + 'API Logs have been disabled since January 1, 1970.' + ); + expect(wrapper.find(EuiLink)).toHaveLength(1); + expect(wrapper.find('p').text()).toEqual('To manage analytics & logging, visit your settings.'); + }); + + it('renders a generic title if no disabled date is present', () => { + setMockValues({ ...values, logRetention: { api: { enabled: false, disabledAt: null } } }); + const wrapper = mountWithIntl(); + + expect(wrapper.find(EuiCallOut)).toHaveLength(1); + expect(wrapper.find('.euiCallOutHeader__title').text()).toEqual('API Logs have been disabled.'); + }); + + it('does not render a settings link if the user cannot manage settings', () => { + setMockValues({ myRole: { canManageLogSettings: false }, logRetention: { api: DISABLED } }); + const wrapper = mountWithIntl(); + + expect(wrapper.find(EuiCallOut)).toHaveLength(1); + expect(wrapper.find(EuiLink)).toHaveLength(0); + expect(wrapper.find('p')).toHaveLength(0); + }); + + it('does not render if log retention is enabled', () => { + setMockValues({ ...values, logRetention: { api: { enabled: true } } }); + const wrapper = shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + it('does not render if log retention is not available', () => { + setMockValues({ ...values, logRetention: null }); + const wrapper = shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + describe('on mount', () => { + it('fetches log retention data when not already loaded', () => { + setMockValues({ ...values, logRetention: null }); + shallow(); + + expect(actions.fetchLogRetention).toHaveBeenCalled(); + }); + + it('does not fetch log retention data if it has already been loaded', () => { + setMockValues({ ...values, logRetention: {} }); + shallow(); + + expect(actions.fetchLogRetention).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx new file mode 100644 index 0000000000000..f97b01602664f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_callout.tsx @@ -0,0 +1,95 @@ +/* + * 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 { useValues, useActions } from 'kea'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; + +import { EuiLinkTo } from '../../../../shared/react_router_helpers'; + +import { AppLogic } from '../../../app_logic'; +import { SETTINGS_PATH } from '../../../routes'; +import { ANALYTICS_TITLE } from '../../analytics'; +import { API_LOGS_TITLE } from '../../api_logs'; + +import { LogRetentionLogic, LogRetentionOptions, renderLogRetentionDate } from '../'; + +const TITLE_MAP = { + [LogRetentionOptions.Analytics]: ANALYTICS_TITLE, + [LogRetentionOptions.API]: API_LOGS_TITLE, +}; + +interface Props { + type: LogRetentionOptions; +} +export const LogRetentionCallout: React.FC = ({ type }) => { + const { fetchLogRetention } = useActions(LogRetentionLogic); + const { logRetention } = useValues(LogRetentionLogic); + const { + myRole: { canManageLogSettings }, + } = useValues(AppLogic); + + const hasLogRetention = logRetention !== null; + + useEffect(() => { + if (!hasLogRetention) fetchLogRetention(); + }, []); + + const logRetentionSettings = logRetention?.[type]; + const title = TITLE_MAP[type]; + const hasLogRetentionDisabled = hasLogRetention && !logRetentionSettings?.enabled; + + return hasLogRetentionDisabled ? ( + <> + + ) : ( + i18n.translate('xpack.enterpriseSearch.appSearch.logRetention.callout.disabledTitle', { + defaultMessage: '{logsTitle} have been disabled.', + values: { + logsTitle: title, + }, + }) + ) + } + > + {canManageLogSettings && ( +

+ + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.logRetention.callout.description.manageSettingsLinkText', + { defaultMessage: 'visit your settings' } + )} + + ), + }} + /> +

+ )} +
+ + + ) : null; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx new file mode 100644 index 0000000000000..9b0143f6f6c6d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.test.tsx @@ -0,0 +1,73 @@ +/* + * 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__/shallow_useeffect.mock'; +import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; + +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import { EuiIconTip } from '@elastic/eui'; + +import { LogRetentionOptions, LogRetentionMessage } from '../'; +import { LogRetentionTooltip } from './'; + +describe('LogRetentionTooltip', () => { + const values = { logRetention: {} }; + const actions = { fetchLogRetention: jest.fn() }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(values); + setMockActions(actions); + }); + + it('renders an analytics tooltip', () => { + const wrapper = shallow(); + const tooltipContent = wrapper.find(EuiIconTip).prop('content') as React.ReactElement; + + expect(tooltipContent.type).toEqual(LogRetentionMessage); + expect(tooltipContent.props.type).toEqual('analytics'); + }); + + it('renders an API tooltip', () => { + const wrapper = shallow(); + const tooltipContent = wrapper.find(EuiIconTip).prop('content') as React.ReactElement; + + expect(tooltipContent.type).toEqual(LogRetentionMessage); + expect(tooltipContent.props.type).toEqual('api'); + }); + + it('passes custom tooltip positions', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiIconTip).prop('position')).toEqual('bottom'); + + wrapper.setProps({ position: 'right' }); + expect(wrapper.find(EuiIconTip).prop('position')).toEqual('right'); + }); + + it('does not render if log retention is not available', () => { + setMockValues({ logRetention: null }); + const wrapper = mount(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + describe('on mount', () => { + it('fetches log retention data when not already loaded', () => { + setMockValues({ logRetention: null }); + shallow(); + + expect(actions.fetchLogRetention).toHaveBeenCalled(); + }); + + it('does not fetch log retention data if it has already been loaded', () => { + setMockValues({ logRetention: {} }); + shallow(); + + expect(actions.fetchLogRetention).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx new file mode 100644 index 0000000000000..9c08043b5313f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/components/log_retention_tooltip.tsx @@ -0,0 +1,41 @@ +/* + * 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 { useValues, useActions } from 'kea'; + +import { i18n } from '@kbn/i18n'; +import { EuiIconTip } from '@elastic/eui'; + +import { LogRetentionLogic, LogRetentionMessage, LogRetentionOptions } from '../'; + +interface Props { + type: LogRetentionOptions; + position?: 'top' | 'right' | 'bottom' | 'left'; +} +export const LogRetentionTooltip: React.FC = ({ type, position = 'bottom' }) => { + const { fetchLogRetention } = useActions(LogRetentionLogic); + const { logRetention } = useValues(LogRetentionLogic); + + const hasLogRetention = logRetention !== null; + + useEffect(() => { + if (!hasLogRetention) fetchLogRetention(); + }, []); + + return hasLogRetention ? ( + } + /> + ) : null; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/index.ts index 0e007f5d8d1d1..23db86f285d01 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/index.ts @@ -7,3 +7,4 @@ export { LogRetentionLogic } from './log_retention_logic'; export * from './types'; export * from './messaging'; +export * from './components'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts index 801a8d36cc403..004e5e9752d97 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.test.ts @@ -112,6 +112,21 @@ describe('LogRetentionLogic', () => { }); }); + describe('setLogRetentionUpdating', () => { + describe('isLogRetentionUpdating', () => { + it('sets isLogRetentionUpdating to true', () => { + mount(); + + LogRetentionLogic.actions.setLogRetentionUpdating(); + + expect(LogRetentionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLogRetentionUpdating: true, + }); + }); + }); + }); + describe('clearLogRetentionUpdating', () => { describe('isLogRetentionUpdating', () => { it('resets isLogRetentionUpdating to false', () => { @@ -263,24 +278,8 @@ describe('LogRetentionLogic', () => { }); describe('fetchLogRetention', () => { - describe('isLogRetentionUpdating', () => { - it('sets isLogRetentionUpdating to true', () => { - mount({ - isLogRetentionUpdating: false, - }); - - LogRetentionLogic.actions.fetchLogRetention(); - - expect(LogRetentionLogic.values).toEqual({ - ...DEFAULT_VALUES, - isLogRetentionUpdating: true, - }); - }); - }); - it('will call an API endpoint and update log retention', async () => { mount(); - jest.spyOn(LogRetentionLogic.actions, 'clearLogRetentionUpdating'); jest .spyOn(LogRetentionLogic.actions, 'updateLogRetention') .mockImplementationOnce(() => {}); @@ -289,14 +288,14 @@ describe('LogRetentionLogic', () => { http.get.mockReturnValue(promise); LogRetentionLogic.actions.fetchLogRetention(); + expect(LogRetentionLogic.values.isLogRetentionUpdating).toBe(true); expect(http.get).toHaveBeenCalledWith('/api/app_search/log_settings'); await promise; expect(LogRetentionLogic.actions.updateLogRetention).toHaveBeenCalledWith( TYPICAL_CLIENT_LOG_RETENTION ); - - expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); + expect(LogRetentionLogic.values.isLogRetentionUpdating).toBe(false); }); it('handles errors', async () => { @@ -315,6 +314,14 @@ describe('LogRetentionLogic', () => { expect(flashAPIErrors).toHaveBeenCalledWith('An error occured'); expect(LogRetentionLogic.actions.clearLogRetentionUpdating).toHaveBeenCalled(); }); + + it('does not run if isLogRetentionUpdating is true, preventing duplicate fetches', async () => { + mount({ isLogRetentionUpdating: true }); + + LogRetentionLogic.actions.fetchLogRetention(); + + expect(http.get).not.toHaveBeenCalled(); + }); }); it('will call saveLogRetention if NOT already enabled', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts index 46c91e5c3c45a..d0088fa1803dc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/log_retention_logic.ts @@ -13,9 +13,10 @@ import { LogRetentionOptions, LogRetention, LogRetentionServer } from './types'; import { convertLogRetentionFromServerToClient } from './utils/convert_log_retention'; interface LogRetentionActions { - clearLogRetentionUpdating(): { value: boolean }; - closeModals(): { value: boolean }; - fetchLogRetention(): { value: boolean }; + setLogRetentionUpdating(): void; + clearLogRetentionUpdating(): void; + closeModals(): void; + fetchLogRetention(): void; saveLogRetention( option: LogRetentionOptions, enabled: boolean @@ -34,6 +35,7 @@ interface LogRetentionValues { export const LogRetentionLogic = kea>({ path: ['enterprise_search', 'app_search', 'log_retention_logic'], actions: () => ({ + setLogRetentionUpdating: true, clearLogRetentionUpdating: true, closeModals: true, fetchLogRetention: true, @@ -54,7 +56,7 @@ export const LogRetentionLogic = kea false, closeModals: () => false, - fetchLogRetention: () => true, + setLogRetentionUpdating: () => true, toggleLogRetention: () => true, }, ], @@ -69,9 +71,14 @@ export const LogRetentionLogic = kea ({ fetchLogRetention: async () => { + if (values.isLogRetentionUpdating) return; // Prevent duplicate calls to the API + try { + actions.setLogRetentionUpdating(); + const { http } = HttpLogic.values; const response = await http.get('/api/app_search/log_settings'); + actions.updateLogRetention( convertLogRetentionFromServerToClient(response as LogRetentionServer) ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.ts deleted file mode 100644 index 6db087e092697..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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 { i18n } from '@kbn/i18n'; - -import { LogRetentionMessages } from './types'; -import { renderLogRetentionDate } from '.'; - -const ANALYTICS_NO_LOGGING = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging', - { - defaultMessage: 'Analytics collection has been disabled for all engines.', - } -); - -const ANALYTICS_NO_LOGGING_COLLECTED = (disabledAt: string) => - i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.collected', - { - defaultMessage: 'The last date analytics were collected was {disabledAt}.', - values: { disabledAt }, - } - ); - -const ANALYTICS_NO_LOGGING_NOT_COLLECTED = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.notCollected', - { - defaultMessage: 'There are no analytics collected.', - } -); - -const ANALYTICS_ILM_DISABLED = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.ilmDisabled', - { - defaultMessage: "App Search isn't managing analytics retention.", - } -); - -const ANALYTICS_CUSTOM_POLICY = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.customPolicy', - { - defaultMessage: 'You have a custom analytics retention policy.', - } -); - -const ANALYTICS_STORED = (minAgeDays: number | null | undefined) => - i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.stored', { - defaultMessage: 'Your analytics are being stored for at least {minAgeDays} days.', - values: { minAgeDays }, - }); - -const API_NO_LOGGING = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging', - { - defaultMessage: 'API logging has been disabled for all engines.', - } -); - -const API_NO_LOGGING_COLLECTED = (disabledAt: string) => - i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.collected', { - defaultMessage: 'The last date logs were collected was {disabledAt}.', - values: { disabledAt }, - }); - -const API_NO_LOGGING_NOT_COLLECTED = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.notCollected', - { - defaultMessage: 'There are no logs collected.', - } -); - -const API_ILM_DISABLED = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.ilmDisabled', - { - defaultMessage: "App Search isn't managing API log retention.", - } -); - -const API_CUSTOM_POLICY = i18n.translate( - 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.customPolicy', - { - defaultMessage: 'You have a custom API log retention policy.', - } -); - -const API_STORED = (minAgeDays: number | null | undefined) => - i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.api.stored', { - defaultMessage: 'Your logs are being stored for at least {minAgeDays} days.', - values: { minAgeDays }, - }); - -export const ANALYTICS_MESSAGES: LogRetentionMessages = { - noLogging: (_, logRetentionSettings) => - `${ANALYTICS_NO_LOGGING} ${ - logRetentionSettings.disabledAt - ? ANALYTICS_NO_LOGGING_COLLECTED(renderLogRetentionDate(logRetentionSettings.disabledAt)) - : ANALYTICS_NO_LOGGING_NOT_COLLECTED - }`, - ilmDisabled: ANALYTICS_ILM_DISABLED, - customPolicy: ANALYTICS_CUSTOM_POLICY, - defaultPolicy: (_, logRetentionSettings) => - ANALYTICS_STORED(logRetentionSettings.retentionPolicy?.minAgeDays), -}; - -export const API_MESSAGES: LogRetentionMessages = { - noLogging: (_, logRetentionSettings) => - `${API_NO_LOGGING} ${ - logRetentionSettings.disabledAt - ? API_NO_LOGGING_COLLECTED(renderLogRetentionDate(logRetentionSettings.disabledAt)) - : API_NO_LOGGING_NOT_COLLECTED - }`, - ilmDisabled: API_ILM_DISABLED, - customPolicy: API_CUSTOM_POLICY, - defaultPolicy: (_, logRetentionSettings) => - API_STORED(logRetentionSettings.retentionPolicy?.minAgeDays), -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx new file mode 100644 index 0000000000000..1f5dd7ed369c5 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/constants.tsx @@ -0,0 +1,96 @@ +/* + * 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 from 'react'; +import { FormattedDate, FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +import { LogRetentionOptions, LogRetentionSettings, LogRetentionPolicy } from '../types'; + +export const renderLogRetentionDate = (dateString: string) => ( + +); + +const CAPITALIZATION_MAP = { + [LogRetentionOptions.Analytics]: { + capitalized: i18n.translate( + 'xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.capitalized', + { defaultMessage: 'Analytics' } + ), + lowercase: i18n.translate( + 'xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.lowercase', + { defaultMessage: 'analytics' } + ), + }, + [LogRetentionOptions.API]: { + capitalized: i18n.translate( + 'xpack.enterpriseSearch.appSearch.logRetention.type.api.title.capitalized', + { defaultMessage: 'API' } + ), + lowercase: i18n.translate( + 'xpack.enterpriseSearch.appSearch.logRetention.type.api.title.lowercase', + { defaultMessage: 'API' } + ), + }, +}; + +interface Props { + type: LogRetentionOptions; + disabledAt?: LogRetentionSettings['disabledAt']; + minAgeDays?: LogRetentionPolicy['minAgeDays']; +} + +export const NoLogging: React.FC = ({ type, disabledAt }) => { + return ( + <> + {' '} + {disabledAt ? ( + + ) : ( + + )} + + ); +}; + +export const ILMDisabled: React.FC = ({ type }) => ( + +); + +export const CustomPolicy: React.FC = ({ type }) => ( + +); + +export const DefaultPolicy: React.FC = ({ type, minAgeDays }) => ( + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.test.ts deleted file mode 100644 index fbc2ccfbc8a52..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 { determineTooltipContent } from './determine_tooltip_content'; -import { ANALYTICS_MESSAGES, API_MESSAGES } from './constants'; - -describe('determineTooltipContent', () => { - const BASE_SETTINGS = { - disabledAt: null, - enabled: true, - retentionPolicy: null, - }; - - it('will return nothing if settings are not provided', () => { - expect(determineTooltipContent(ANALYTICS_MESSAGES, true)).toBeUndefined(); - }); - - describe('analytics messages', () => { - describe('when analytics logs are enabled', () => { - describe("and they're using the default policy", () => { - it('will render a retention policy message', () => { - expect( - determineTooltipContent(ANALYTICS_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: true, - retentionPolicy: { - isDefault: true, - minAgeDays: 7, - }, - }) - ).toEqual('Your analytics are being stored for at least 7 days.'); - }); - }); - - describe('and there is a custom policy', () => { - it('will render a retention policy message', () => { - expect( - determineTooltipContent(ANALYTICS_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: true, - retentionPolicy: { - isDefault: false, - minAgeDays: 7, - }, - }) - ).toEqual('You have a custom analytics retention policy.'); - }); - }); - }); - - describe('when analytics logs are disabled', () => { - describe('and there is no disabledAt date', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(ANALYTICS_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: false, - disabledAt: null, - }) - ).toEqual( - 'Analytics collection has been disabled for all engines. There are no analytics collected.' - ); - }); - }); - - describe('and there is a disabledAt date', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(ANALYTICS_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: false, - disabledAt: 'Thu, 05 Nov 2020 18:57:28 +0000', - }) - ).toEqual( - 'Analytics collection has been disabled for all engines. The last date analytics were collected was November 5, 2020.' - ); - }); - }); - }); - - describe('when ilm is disabled entirely', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(ANALYTICS_MESSAGES, false, { - ...BASE_SETTINGS, - enabled: true, - }) - ).toEqual("App Search isn't managing analytics retention."); - }); - }); - }); - - describe('api messages', () => { - describe('when analytics logs are enabled', () => { - describe("and they're using the default policy", () => { - it('will render a retention policy message', () => { - expect( - determineTooltipContent(API_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: true, - retentionPolicy: { - isDefault: true, - minAgeDays: 7, - }, - }) - ).toEqual('Your logs are being stored for at least 7 days.'); - }); - }); - - describe('and there is a custom policy', () => { - it('will render a retention policy message', () => { - expect( - determineTooltipContent(API_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: true, - retentionPolicy: { - isDefault: false, - minAgeDays: 7, - }, - }) - ).toEqual('You have a custom API log retention policy.'); - }); - }); - }); - - describe('when analytics logs are disabled', () => { - describe('and there is no disabledAt date', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(API_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: false, - disabledAt: null, - }) - ).toEqual('API logging has been disabled for all engines. There are no logs collected.'); - }); - }); - - describe('and there is a disabledAt date', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(API_MESSAGES, true, { - ...BASE_SETTINGS, - enabled: false, - disabledAt: 'Thu, 05 Nov 2020 18:57:28 +0000', - }) - ).toEqual( - 'API logging has been disabled for all engines. The last date logs were collected was November 5, 2020.' - ); - }); - }); - }); - - describe('when ilm is disabled entirely', () => { - it('will render a no logging message', () => { - expect( - determineTooltipContent(API_MESSAGES, false, { - ...BASE_SETTINGS, - enabled: true, - }) - ).toEqual("App Search isn't managing API log retention."); - }); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.ts deleted file mode 100644 index b1476dbd171ad..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/determine_tooltip_content.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 { LogRetentionSettings } from '../types'; -import { TMessageStringOrFunction, LogRetentionMessages } from './types'; - -export const determineTooltipContent = ( - messages: LogRetentionMessages, - ilmEnabled: boolean, - logRetentionSettings?: LogRetentionSettings -) => { - if (typeof logRetentionSettings === 'undefined') { - return; - } - - const renderOrReturnMessage = (message: TMessageStringOrFunction) => { - if (typeof message === 'function') { - return message(ilmEnabled, logRetentionSettings); - } - return message; - }; - - if (!logRetentionSettings.enabled) { - return renderOrReturnMessage(messages.noLogging); - } - if (!ilmEnabled) { - return renderOrReturnMessage(messages.ilmDisabled); - } - if (!logRetentionSettings.retentionPolicy?.isDefault) { - return renderOrReturnMessage(messages.customPolicy); - } else { - return renderOrReturnMessage(messages.defaultPolicy); - } -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.test.tsx deleted file mode 100644 index 13692bb3e415d..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.test.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 { setMockValues } from '../../../../__mocks__'; - -import React from 'react'; -import { shallow } from 'enzyme'; - -import { AnalyticsLogRetentionMessage, ApiLogRetentionMessage, renderLogRetentionDate } from '.'; - -describe('LogRetentionMessaging', () => { - const LOG_RETENTION = { - analytics: { - disabledAt: null, - enabled: true, - retentionPolicy: { isDefault: true, minAgeDays: 180 }, - }, - api: { - disabledAt: null, - enabled: true, - retentionPolicy: { isDefault: true, minAgeDays: 180 }, - }, - }; - - describe('renderLogRetentionDate', () => { - it('renders a formatted date', () => { - expect(renderLogRetentionDate('Thu, 05 Nov 2020 18:57:28 +0000')).toEqual('November 5, 2020'); - }); - }); - - describe('AnalyticsLogRetentionMessage', () => { - it('renders', () => { - setMockValues({ - ilmEnabled: true, - logRetention: LOG_RETENTION, - }); - const wrapper = shallow(); - expect(wrapper.text()).toEqual('Your analytics are being stored for at least 180 days.'); - }); - - it('renders nothing if logRetention is null', () => { - setMockValues({ - ilmEnabled: true, - logRetention: null, - }); - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toEqual(true); - }); - }); - - describe('ApiLogRetentionMessage', () => { - it('renders', () => { - setMockValues({ - ilmEnabled: true, - logRetention: LOG_RETENTION, - }); - const wrapper = shallow(); - expect(wrapper.text()).toEqual('Your logs are being stored for at least 180 days.'); - }); - - it('renders nothing if logRetention is null', () => { - setMockValues({ - ilmEnabled: true, - logRetention: null, - }); - const wrapper = shallow(); - expect(wrapper.isEmptyRender()).toEqual(true); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.ts new file mode 100644 index 0000000000000..3e5154be25b57 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { LogRetentionMessage } from './log_retention_message'; +export { renderLogRetentionDate } from './constants'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.tsx deleted file mode 100644 index 3b0761950ee3d..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 from 'react'; - -import { useValues } from 'kea'; -import moment from 'moment'; - -import { AppLogic } from '../../../app_logic'; -import { LogRetentionLogic } from '../log_retention_logic'; -import { LogRetentionOptions } from '../types'; - -import { determineTooltipContent } from './determine_tooltip_content'; -import { ANALYTICS_MESSAGES, API_MESSAGES } from './constants'; - -export const renderLogRetentionDate = (dateString: string) => - moment(dateString).format('MMMM D, YYYY'); - -export const AnalyticsLogRetentionMessage: React.FC = () => { - const { ilmEnabled } = useValues(AppLogic); - const { logRetention } = useValues(LogRetentionLogic); - if (!logRetention) return null; - - return ( - <> - {determineTooltipContent( - ANALYTICS_MESSAGES, - ilmEnabled, - logRetention[LogRetentionOptions.Analytics] - )} - - ); -}; - -export const ApiLogRetentionMessage: React.FC = () => { - const { ilmEnabled } = useValues(AppLogic); - const { logRetention } = useValues(LogRetentionLogic); - if (!logRetention) return null; - - return ( - <>{determineTooltipContent(API_MESSAGES, ilmEnabled, logRetention[LogRetentionOptions.API])} - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx new file mode 100644 index 0000000000000..435b28c9d6dc8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.test.tsx @@ -0,0 +1,172 @@ +/* + * 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 { setMockValues } from '../../../../__mocks__/kea.mock'; +import { mountWithIntl } from '../../../../__mocks__'; + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { LogRetentionOptions } from '../types'; +import { LogRetentionMessage } from './'; + +describe('LogRetentionMessage', () => { + const analytics = LogRetentionOptions.Analytics; + const api = LogRetentionOptions.API; + + const setLogRetention = (logRetention: object, ilmEnabled: boolean = true) => { + const logRetentionSettings = { + disabledAt: null, + enabled: true, + retentionPolicy: null, + ...logRetention, + }; + + setMockValues({ + ilmEnabled, + logRetention: { + [LogRetentionOptions.API]: logRetentionSettings, + [LogRetentionOptions.Analytics]: logRetentionSettings, + }, + }); + }; + + it('does not render if ILM is unavailable', () => { + setMockValues({ logRetention: null }); + const wrapper = shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + it('does not render if log retention settings are empty', () => { + setMockValues({ logRetention: { api: null } }); + const wrapper = shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + describe('when logs are enabled', () => { + describe("and they're using the default policy", () => { + describe('a retention policy message renders', () => { + beforeEach(() => { + setLogRetention({ + enabled: true, + retentionPolicy: { + isDefault: true, + minAgeDays: 7, + }, + }); + }); + + it('for analytics', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual( + 'Your analytics logs are being stored for at least 7 days.' + ); + }); + + it('for api', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual('Your API logs are being stored for at least 7 days.'); + }); + }); + }); + + describe('and there is a custom policy', () => { + describe('a retention policy message renders', () => { + beforeEach(() => { + setLogRetention({ + enabled: true, + retentionPolicy: { + isDefault: false, + minAgeDays: 7, + }, + }); + }); + + it('for analytics', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual('You have a custom analytics log retention policy.'); + }); + + it('for api', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual('You have a custom API log retention policy.'); + }); + }); + }); + }); + + describe('when logs are disabled', () => { + describe('and there is no disabledAt date', () => { + describe('a no logging message renders', () => { + beforeEach(() => { + setLogRetention({ + enabled: false, + disabledAt: null, + }); + }); + + it('for api', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual( + 'API logging has been disabled for all engines. There are no API logs collected.' + ); + }); + + it('for analytics', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual( + 'Analytics logging has been disabled for all engines. There are no analytics logs collected.' + ); + }); + }); + }); + + describe('and there is a disabledAt date', () => { + describe('a no logging message renders with a date', () => { + beforeEach(() => { + setLogRetention({ + enabled: false, + disabledAt: 'Thu, 05 Nov 2020 18:57:28 +0000', + }); + }); + + it('for analytics', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual( + 'Analytics logging has been disabled for all engines. The last date analytics logs were collected was November 5, 2020.' + ); + }); + + it('for api', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual( + 'API logging has been disabled for all engines. The last date API logs were collected was November 5, 2020.' + ); + }); + }); + }); + }); + + describe('when ILM is disabled entirely', () => { + describe('an ILM disabled message renders', () => { + beforeEach(() => { + setLogRetention({}, false); + }); + + it('for analytics', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual("App Search isn't managing analytics log retention."); + }); + + it('for api', () => { + const wrapper = mountWithIntl(); + expect(wrapper.text()).toEqual("App Search isn't managing API log retention."); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx new file mode 100644 index 0000000000000..2c213cfc43e92 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/log_retention_message.tsx @@ -0,0 +1,41 @@ +/* + * 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 from 'react'; +import { useValues } from 'kea'; + +import { AppLogic } from '../../../app_logic'; +import { LogRetentionLogic } from '../log_retention_logic'; +import { LogRetentionOptions } from '../types'; + +import { NoLogging, ILMDisabled, CustomPolicy, DefaultPolicy } from './constants'; + +interface Props { + type: LogRetentionOptions; +} +export const LogRetentionMessage: React.FC = ({ type }) => { + const { ilmEnabled } = useValues(AppLogic); + + const { logRetention } = useValues(LogRetentionLogic); + if (!logRetention) return null; + + const logRetentionSettings = logRetention[type]; + if (!logRetentionSettings) return null; + + if (!logRetentionSettings.enabled) { + return ; + } + if (!ilmEnabled) { + return ; + } + if (!logRetentionSettings.retentionPolicy?.isDefault) { + return ; + } else { + return ( + + ); + } +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/types.ts deleted file mode 100644 index 8f86e397dfe26..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/log_retention/messaging/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 { LogRetentionSettings } from '../types'; - -export type TMessageStringOrFunction = - | string - | ((ilmEnabled: boolean, logRetentionSettings: LogRetentionSettings) => string); - -export interface LogRetentionMessages { - noLogging: TMessageStringOrFunction; - ilmDisabled: TMessageStringOrFunction; - customPolicy: TMessageStringOrFunction; - defaultPolicy: TMessageStringOrFunction; -} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx index a3aa463ad069a..873ff58be8373 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx @@ -12,12 +12,7 @@ import { useActions, useValues } from 'kea'; import { DOCS_PREFIX } from '../../../routes'; -import { - LogRetentionLogic, - LogRetentionOptions, - AnalyticsLogRetentionMessage, - ApiLogRetentionMessage, -} from '../../log_retention'; +import { LogRetentionLogic, LogRetentionOptions, LogRetentionMessage } from '../../log_retention'; export const LogRetentionPanel: React.FC = () => { const { toggleLogRetention, fetchLogRetention } = useActions(LogRetentionLogic); @@ -69,7 +64,7 @@ export const LogRetentionPanel: React.FC = () => { {': '} {hasILM && ( - + )} @@ -96,7 +91,7 @@ export const LogRetentionPanel: React.FC = () => { {': '} {hasILM && ( - + )} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5701312501dba..f8c5d7327d20d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7271,20 +7271,18 @@ "xpack.enterpriseSearch.appSearch.productName": "App Search", "xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "追加フィールドを非表示", "xpack.enterpriseSearch.appSearch.roleMappings.title": "ロールマッピング", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.customPolicy": "カスタム分析保持ポリシーがあります。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.ilmDisabled": "App Search は分析保持を管理していません。", + "xpack.enterpriseSearch.appSearch.logRetention.customPolicy": "カスタム {logsType} ログ保持ポリシーがあります。", + "xpack.enterpriseSearch.appSearch.logRetention.defaultPolicy": "{logsType} ログは {minAgeDays} 日以上保存されています。", + "xpack.enterpriseSearch.appSearch.logRetention.ilmDisabled": "App Search は {logsType} 保持を管理していません。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging": "すべてのエンジンの {logsType} ログが無効です。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging.collected": "前回の {logsType} ログは {disabledAtDate} に収集されました。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging.notCollected": "収集された {logsType} ログはありません。", + "xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.capitalized": "分析", + "xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.lowercase": "分析", + "xpack.enterpriseSearch.appSearch.logRetention.type.api.title.capitalized": "API", + "xpack.enterpriseSearch.appSearch.logRetention.type.api.title.lowercase": "API", "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.label": "分析ログ", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging": "すべてのエンジンの分析収集が無効です。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.collected": "前回の分析は {disabledAt} に収集されました。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.notCollected": "収集された分析はありません。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.stored": "分析は {minAgeDays} 日以上保存されています。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.customPolicy": "カスタム API ログ保持ポリシーがあります。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.ilmDisabled": "App Search は API ログ保持を管理していません。", "xpack.enterpriseSearch.appSearch.settings.logRetention.api.label": "API ログ", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging": "すべてのエンジンの API ログが無効です。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.collected": "前回のログは {disabledAt} に収集されました。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.notCollected": "収集されたログはありません。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.stored": "ログは {minAgeDays} 日以上保存されています。", "xpack.enterpriseSearch.appSearch.settings.logRetention.description": "API ログと分析のデフォルト書き込み設定を管理します。", "xpack.enterpriseSearch.appSearch.settings.logRetention.learnMore": "保持設定の詳細をご覧ください。", "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.analytics.description": "分析ログを無効にすると、すべてのエンジンがただちに分析ログのインデックス作成を停止します。既存のデータは、上記で概説したストレージタイムフレームに従って削除されます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f6e4bfeb9ebde..6dbf484150d99 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7290,20 +7290,18 @@ "xpack.enterpriseSearch.appSearch.productName": "App Search", "xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "隐藏其他字段", "xpack.enterpriseSearch.appSearch.roleMappings.title": "角色映射", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.customPolicy": "您有定制分析保留策略。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.ilmDisabled": "App Search 不管理分析保留。", + "xpack.enterpriseSearch.appSearch.logRetention.customPolicy": "您有定制 {logsType} 日志保留策略。", + "xpack.enterpriseSearch.appSearch.logRetention.defaultPolicy": "您的 {logsType} 日志将存储至少 {minAgeDays} 天。", + "xpack.enterpriseSearch.appSearch.logRetention.ilmDisabled": "App Search 不管理 {logsType} 保留。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging": "所有引擎的 {logsType} 日志记录均已禁用。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging.collected": "{logsType} 日志的最后收集日期为 {disabledAtDate}。", + "xpack.enterpriseSearch.appSearch.logRetention.noLogging.notCollected": "未收集任何 {logsType} 日志。", + "xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.capitalized": "分析", + "xpack.enterpriseSearch.appSearch.logRetention.type.analytics.title.lowercase": "分析", + "xpack.enterpriseSearch.appSearch.logRetention.type.api.title.capitalized": "API", + "xpack.enterpriseSearch.appSearch.logRetention.type.api.title.lowercase": "API", "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.label": "分析日志", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging": "所有引擎的分析收集均已禁用。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.collected": "分析的最后收集日期是 {disabledAt}。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.notCollected": "未收集任何分析。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.stored": "您的分析将存储至少 {minAgeDays} 天。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.customPolicy": "您有定制 API 日志保留策略。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.ilmDisabled": "App Search 不管理 API 日志保留。", "xpack.enterpriseSearch.appSearch.settings.logRetention.api.label": "API 日志", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging": "所有引擎的 API 日志记录均已禁用。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.collected": "日志的最后收集日期为 {disabledAt}。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.notCollected": "未收集任何日志。", - "xpack.enterpriseSearch.appSearch.settings.logRetention.api.stored": "您的日志将存储至少 {minAgeDays} 天。", "xpack.enterpriseSearch.appSearch.settings.logRetention.description": "管理 API 日志和分析的默认写入设置。", "xpack.enterpriseSearch.appSearch.settings.logRetention.learnMore": "了解保留设置的详情。", "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.analytics.description": "禁用分析日志后,您的所有引擎将立即停止索引分析日志。您的现有数据将按照上述存储时间范围被删除。",