diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx
new file mode 100644
index 0000000000000..b4f7e92fac8cc
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx
@@ -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('[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 ', () => {
+    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');
+    expect(actions.toggleLogRetention).toHaveBeenCalledWith('api');
+  });
+});
+
+const mockLogRetention = (logRetention: Partial<ILogRetention>) => {
+  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,
+    },
+  };
+};
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
new file mode 100644
index 0000000000000..7b8eea061d110
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx
@@ -0,0 +1,110 @@
+/*
+ * 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 && (
+                <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>
+              {': '}
+              {hasILM && (
+                <EuiTextColor color="subdued">
+                  <ApiLogRetentionMessage />
+                </EuiTextColor>
+              )}
+            </>
+          }
+          checked={!!apiLogRetentionSettings?.enabled}
+          onChange={() => toggleLogRetention(ELogRetentionOptions.API)}
+          disabled={isLogRetentionUpdating}
+          data-test-subj="LogRetentionPanelAPISwitch"
+        />
+      </EuiText>
+    </div>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts
new file mode 100644
index 0000000000000..f7f0fbdff1acb
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts
@@ -0,0 +1,119 @@
+/*
+ * 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 { ILogRetentionMessages } 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: ILogRetentionMessages = {
+  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: ILogRetentionMessages = {
+  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/settings/log_retention/messaging/determine_tooltip_content.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts
new file mode 100644
index 0000000000000..fbc2ccfbc8a52
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts
@@ -0,0 +1,168 @@
+/*
+ * 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/settings/log_retention/messaging/determine_tooltip_content.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts
new file mode 100644
index 0000000000000..e361e28490a83
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 { ILogRetentionSettings } from '../types';
+import { TMessageStringOrFunction, ILogRetentionMessages } from './types';
+
+export const determineTooltipContent = (
+  messages: ILogRetentionMessages,
+  ilmEnabled: boolean,
+  logRetentionSettings?: ILogRetentionSettings
+) => {
+  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 (logRetentionSettings.enabled && !ilmEnabled) {
+    return renderOrReturnMessage(messages.ilmDisabled);
+  }
+  if (
+    logRetentionSettings.enabled &&
+    ilmEnabled &&
+    !logRetentionSettings.retentionPolicy?.isDefault
+  ) {
+    return renderOrReturnMessage(messages.customPolicy);
+  }
+  if (
+    logRetentionSettings.enabled &&
+    ilmEnabled &&
+    logRetentionSettings.retentionPolicy?.isDefault
+  ) {
+    return renderOrReturnMessage(messages.defaultPolicy);
+  }
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx
new file mode 100644
index 0000000000000..b65ffc04ad700
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx
@@ -0,0 +1,74 @@
+/*
+ * 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(<AnalyticsLogRetentionMessage />);
+      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(<AnalyticsLogRetentionMessage />);
+      expect(wrapper.isEmptyRender()).toEqual(true);
+    });
+  });
+
+  describe('ApiLogRetentionMessage', () => {
+    it('renders', () => {
+      setMockValues({
+        ilmEnabled: true,
+        logRetention: LOG_RETENTION,
+      });
+      const wrapper = shallow(<ApiLogRetentionMessage />);
+      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(<ApiLogRetentionMessage />);
+      expect(wrapper.isEmptyRender()).toEqual(true);
+    });
+  });
+});
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx
new file mode 100644
index 0000000000000..9fe2e8dc72ed6
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx
@@ -0,0 +1,46 @@
+/*
+ * 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 { ELogRetentionOptions } 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[ELogRetentionOptions.Analytics]
+      )}
+    </>
+  );
+};
+
+export const ApiLogRetentionMessage: React.FC = () => {
+  const { ilmEnabled } = useValues(AppLogic);
+  const { logRetention } = useValues(LogRetentionLogic);
+  if (!logRetention) return null;
+
+  return (
+    <>{determineTooltipContent(API_MESSAGES, ilmEnabled, logRetention[ELogRetentionOptions.API])}</>
+  );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts
new file mode 100644
index 0000000000000..a9546343d9aa7
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts
@@ -0,0 +1,18 @@
+/*
+ * 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 { ILogRetentionSettings } from '../types';
+
+export type TMessageStringOrFunction =
+  | string
+  | ((ilmEnabled: boolean, logRetentionSettings: ILogRetentionSettings) => string);
+
+export interface ILogRetentionMessages {
+  noLogging: TMessageStringOrFunction;
+  ilmDisabled: TMessageStringOrFunction;
+  customPolicy: TMessageStringOrFunction;
+  defaultPolicy: TMessageStringOrFunction;
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx
index 13079bb380f13..7bd3683919bc1 100644
--- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx
@@ -5,11 +5,17 @@
  */
 
 import React from 'react';
-
-import { EuiPageHeader, EuiPageHeaderSection, EuiPageContentBody, EuiTitle } from '@elastic/eui';
+import {
+  EuiPageHeader,
+  EuiPageHeaderSection,
+  EuiPageContent,
+  EuiPageContentBody,
+  EuiTitle,
+} from '@elastic/eui';
 
 import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
 import { FlashMessages } from '../../../shared/flash_messages';
+import { LogRetentionPanel } from './log_retention/log_retention_panel';
 
 import { SETTINGS_TITLE } from './';
 
@@ -24,9 +30,12 @@ export const Settings: React.FC = () => {
           </EuiTitle>
         </EuiPageHeaderSection>
       </EuiPageHeader>
-      <EuiPageContentBody>
-        <FlashMessages />
-      </EuiPageContentBody>
+      <EuiPageContent>
+        <EuiPageContentBody>
+          <FlashMessages />
+          <LogRetentionPanel />
+        </EuiPageContentBody>
+      </EuiPageContent>
     </>
   );
 };