diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts
index 7550055d8242d..42c05c2d80d37 100644
--- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts
+++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/helpers/app_context.mock.ts
@@ -33,13 +33,24 @@ const idToUrlMap = {
SNAPSHOT_RESTORE_LOCATOR: 'snapshotAndRestoreUrl',
DISCOVER_APP_LOCATOR: 'discoverUrl',
};
+type IdKey = keyof typeof idToUrlMap;
+
+const stringifySearchParams = (params: Record) => {
+ const stringifiedParams = Object.keys(params).reduce((list, key) => {
+ const value = typeof params[key] === 'object' ? JSON.stringify(params[key]) : params[key];
+
+ return { ...list, [key]: value };
+ }, {});
+
+ return new URLSearchParams(stringifiedParams).toString();
+};
const shareMock = sharePluginMock.createSetupContract();
-shareMock.url.locators.get = (id) => ({
- // @ts-expect-error This object is missing some properties that we're not using in the UI
+// @ts-expect-error This object is missing some properties that we're not using in the UI
+shareMock.url.locators.get = (id: IdKey) => ({
useUrl: (): string | undefined => idToUrlMap[id],
- // @ts-expect-error This object is missing some properties that we're not using in the UI
- getUrl: (): string | undefined => idToUrlMap[id],
+ getUrl: (params: Record): string | undefined =>
+ `${idToUrlMap[id]}?${stringifySearchParams(params)}`,
});
export const getAppContextMock = () => ({
diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx
index acc64e2872642..e19ea5b1dfd99 100644
--- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx
+++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/overview/fix_logs_step/fix_logs_step.test.tsx
@@ -7,6 +7,20 @@
import { act } from 'react-dom/test-utils';
+// Once the logs team register the kibana locators in their app, we should be able
+// to remove this mock and follow a similar approach to how discover link is tested.
+// See: https://github.com/elastic/kibana/issues/104855
+const MOCKED_TIME = '2021-09-05T10:49:01.805Z';
+jest.mock('../../../../public/application/lib/logs_checkpoint', () => {
+ const originalModule = jest.requireActual('../../../../public/application/lib/logs_checkpoint');
+
+ return {
+ __esModule: true,
+ ...originalModule,
+ loadLogsCheckpoint: jest.fn().mockReturnValue('2021-09-05T10:49:01.805Z'),
+ };
+});
+
import { DeprecationLoggingStatus } from '../../../../common/types';
import { DEPRECATION_LOGS_SOURCE_ID } from '../../../../common/constants';
import { setupEnvironment } from '../../helpers';
@@ -180,7 +194,7 @@ describe('Overview - Fix deprecation logs step', () => {
expect(exists('viewObserveLogs')).toBe(true);
expect(find('viewObserveLogs').props().href).toBe(
- `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}`
+ `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}&logPosition=(end:now,start:'${MOCKED_TIME}')`
);
});
@@ -194,7 +208,12 @@ describe('Overview - Fix deprecation logs step', () => {
component.update();
expect(exists('viewDiscoverLogs')).toBe(true);
- expect(find('viewDiscoverLogs').props().href).toBe('discoverUrl');
+
+ const decodedUrl = decodeURIComponent(find('viewDiscoverLogs').props().href);
+ expect(decodedUrl).toContain('discoverUrl');
+ ['"language":"kuery"', '"query":"@timestamp+>'].forEach((param) => {
+ expect(decodedUrl).toContain(param);
+ });
});
});
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx
index f0a4096687f6c..244583e9154c1 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/deprecations_count_checkpoint/deprecations_count_checkpoint.tsx
@@ -5,17 +5,13 @@
* 2.0.
*/
-import React, { FunctionComponent, useState, useEffect } from 'react';
+import React, { FunctionComponent, useEffect } from 'react';
import moment from 'moment-timezone';
import { FormattedDate, FormattedTime, FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { EuiCallOut, EuiButton, EuiLoadingContent } from '@elastic/eui';
import { useAppContext } from '../../../../app_context';
-import { Storage } from '../../../../../shared_imports';
-
-const LS_SETTING_ID = 'kibana.upgradeAssistant.lastCheckpoint';
-const localStorage = new Storage(window.localStorage);
const i18nTexts = {
calloutTitle: (warningsCount: number, previousCheck: string) => (
@@ -51,32 +47,22 @@ const i18nTexts = {
),
};
-const getPreviousCheckpointDate = () => {
- const storedValue = moment(localStorage.get(LS_SETTING_ID));
-
- if (storedValue.isValid()) {
- return storedValue.toISOString();
- }
-
- const now = moment().toISOString();
- localStorage.set(LS_SETTING_ID, now);
-
- return now;
-};
-
interface Props {
+ checkpoint: string;
+ setCheckpoint: (value: string) => void;
setHasNoDeprecationLogs: (hasNoLogs: boolean) => void;
}
export const DeprecationsCountCheckpoint: FunctionComponent = ({
+ checkpoint,
+ setCheckpoint,
setHasNoDeprecationLogs,
}) => {
const {
services: { api },
} = useAppContext();
- const [previousCheck, setPreviousCheck] = useState(getPreviousCheckpointDate());
const { data, error, isLoading, resendRequest, isInitialRequest } = api.getDeprecationLogsCount(
- previousCheck
+ checkpoint
);
const logsCount = data?.count || 0;
@@ -87,9 +73,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({
const onResetClick = () => {
const now = moment().toISOString();
-
- setPreviousCheck(now);
- localStorage.set(LS_SETTING_ID, now);
+ setCheckpoint(now);
};
useEffect(() => {
@@ -126,7 +110,7 @@ export const DeprecationsCountCheckpoint: FunctionComponent = ({
return (
{
- const { indexPatterns: indexPatternService } = dataService;
+interface Props {
+ checkpoint: string;
+}
- const results = await indexPatternService.find(DEPRECATION_LOGS_INDEX_PATTERN);
+const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart) => {
+ const results = await dataService.dataViews.find(DEPRECATION_LOGS_INDEX_PATTERN);
// Since the find might return also results with wildcard matchers we need to find the
// index pattern that has an exact match with our title.
const deprecationIndexPattern = results.find(
@@ -30,7 +33,7 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart)
if (deprecationIndexPattern) {
return deprecationIndexPattern.id;
} else {
- const newIndexPattern = await indexPatternService.createAndSave({
+ const newIndexPattern = await dataService.dataViews.createAndSave({
title: DEPRECATION_LOGS_INDEX_PATTERN,
allowNoIndex: true,
});
@@ -38,7 +41,7 @@ const getDeprecationIndexPatternId = async (dataService: DataPublicPluginStart)
}
};
-const DiscoverAppLink: FunctionComponent = () => {
+const DiscoverAppLink: FunctionComponent = ({ checkpoint }) => {
const {
services: { data: dataService },
plugins: { share },
@@ -55,12 +58,19 @@ const DiscoverAppLink: FunctionComponent = () => {
return;
}
- const url = await locator.getUrl({ indexPatternId });
+ const url = await locator.getUrl({
+ indexPatternId,
+ query: {
+ language: 'kuery',
+ query: `@timestamp > "${checkpoint}"`,
+ },
+ });
+
setDiscoveryUrl(url);
};
getDiscoveryUrl();
- }, [dataService, share.url.locators]);
+ }, [dataService, checkpoint, share.url.locators]);
return (
@@ -72,14 +82,16 @@ const DiscoverAppLink: FunctionComponent = () => {
);
};
-const ObservabilityAppLink: FunctionComponent = () => {
+const ObservabilityAppLink: FunctionComponent = ({ checkpoint }) => {
const {
services: {
core: { http },
},
} = useAppContext();
const logStreamUrl = http?.basePath?.prepend(
- `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}`
+ `/app/logs/stream?sourceId=${DEPRECATION_LOGS_SOURCE_ID}&logPosition=(end:now,start:${encode(
+ checkpoint
+ )})`
);
return (
@@ -92,7 +104,7 @@ const ObservabilityAppLink: FunctionComponent = () => {
);
};
-export const ExternalLinks: FunctionComponent = () => {
+export const ExternalLinks: FunctionComponent = ({ checkpoint }) => {
return (
@@ -106,7 +118,7 @@ export const ExternalLinks: FunctionComponent = () => {
-
+
@@ -120,7 +132,7 @@ export const ExternalLinks: FunctionComponent = () => {
-
+
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx
index 189dc4e39c0b2..c0977847d121c 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/overview/fix_logs_step/fix_logs_step.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { FunctionComponent } from 'react';
+import React, { FunctionComponent, useState, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiText, EuiSpacer, EuiPanel, EuiCallOut } from '@elastic/eui';
@@ -15,6 +15,7 @@ import { ExternalLinks } from './external_links';
import { DeprecationsCountCheckpoint } from './deprecations_count_checkpoint';
import { useDeprecationLogging } from './use_deprecation_logging';
import { DeprecationLoggingToggle } from './deprecation_logging_toggle';
+import { loadLogsCheckpoint, saveLogsCheckpoint } from '../../../lib/logs_checkpoint';
import type { OverviewStepProps } from '../../types';
const i18nTexts = {
@@ -54,6 +55,11 @@ interface Props {
const FixLogsStep: FunctionComponent = ({ setIsComplete }) => {
const state = useDeprecationLogging();
+ const [checkpoint, setCheckpoint] = useState(loadLogsCheckpoint());
+
+ useEffect(() => {
+ saveLogsCheckpoint(checkpoint);
+ }, [checkpoint]);
return (
<>
@@ -86,14 +92,18 @@ const FixLogsStep: FunctionComponent = ({ setIsComplete }) => {
{i18nTexts.analyzeTitle}
-
+
{i18nTexts.deprecationsCountCheckpointTitle}
-
+
>
)}
>
diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts
new file mode 100644
index 0000000000000..59c3adaed95df
--- /dev/null
+++ b/x-pack/plugins/upgrade_assistant/public/application/lib/logs_checkpoint.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import moment from 'moment-timezone';
+
+import { Storage } from '../../shared_imports';
+
+const SETTING_ID = 'kibana.upgradeAssistant.lastCheckpoint';
+const localStorage = new Storage(window.localStorage);
+
+export const loadLogsCheckpoint = () => {
+ const storedValue = moment(localStorage.get(SETTING_ID));
+
+ if (storedValue.isValid()) {
+ return storedValue.toISOString();
+ }
+
+ const now = moment().toISOString();
+ localStorage.set(SETTING_ID, now);
+
+ return now;
+};
+
+export const saveLogsCheckpoint = (value: string) => {
+ localStorage.set(SETTING_ID, value);
+};
diff --git a/x-pack/plugins/upgrade_assistant/public/plugin.ts b/x-pack/plugins/upgrade_assistant/public/plugin.ts
index 75069725c3f59..1b33ec676e1c0 100644
--- a/x-pack/plugins/upgrade_assistant/public/plugin.ts
+++ b/x-pack/plugins/upgrade_assistant/public/plugin.ts
@@ -42,7 +42,7 @@ export class UpgradeAssistantUIPlugin
title: pluginName,
order: 1,
async mount(params) {
- const [coreStart, { discover, data }] = await coreSetup.getStartServices();
+ const [coreStart, { data }] = await coreSetup.getStartServices();
const {
chrome: { docTitle },
@@ -61,7 +61,6 @@ export class UpgradeAssistantUIPlugin
core: coreStart,
data,
history: params.history,
- discover,
api: apiService,
breadcrumbs: breadcrumbService,
},
diff --git a/x-pack/plugins/upgrade_assistant/public/types.ts b/x-pack/plugins/upgrade_assistant/public/types.ts
index db04e59ccd362..d59e9b158b74e 100644
--- a/x-pack/plugins/upgrade_assistant/public/types.ts
+++ b/x-pack/plugins/upgrade_assistant/public/types.ts
@@ -6,7 +6,6 @@
*/
import { ScopedHistory } from 'kibana/public';
-import { DiscoverStart } from 'src/plugins/discover/public';
import { ManagementSetup } from 'src/plugins/management/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { SharePluginSetup } from 'src/plugins/share/public';
@@ -30,7 +29,6 @@ export interface SetupDependencies {
export interface StartDependencies {
licensing: LicensingPluginStart;
- discover: DiscoverStart;
data: DataPublicPluginStart;
}
@@ -43,7 +41,6 @@ export interface AppDependencies {
};
services: {
core: CoreStart;
- discover: DiscoverStart;
data: DataPublicPluginStart;
breadcrumbs: BreadcrumbService;
history: ScopedHistory;
diff --git a/x-pack/plugins/upgrade_assistant/tsconfig.json b/x-pack/plugins/upgrade_assistant/tsconfig.json
index 39d7404ebea9d..4336acb77c2eb 100644
--- a/x-pack/plugins/upgrade_assistant/tsconfig.json
+++ b/x-pack/plugins/upgrade_assistant/tsconfig.json
@@ -7,6 +7,7 @@
"declarationMap": true
},
"include": [
+ "../../../typings/**/*",
"__jest__/**/*",
"common/**/*",
"public/**/*",