From 9a473879af226351f346210977b5a877f704f64d Mon Sep 17 00:00:00 2001 From: mohamedhamed-ahmed Date: Thu, 22 Feb 2024 13:28:17 +0200 Subject: [PATCH] [Dataset Quality] Added Dataset Quality Locator (#177000) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/elastic/kibana/issues/170611 ## πŸ“ Summary This PR adds the infrastructure work for the locators needed to create the navigation link from the Logs Explorer to the Dataset Quality Page, but the links themselves are to be added with a later ticket. ## πŸ’‘For Reviewers To be abled to test this PR you can add the below code [here](https://github.com/elastic/kibana/blob/main/x-pack/plugins/observability_solution/observability_logs_explorer/public/components/logs_explorer_top_nav_menu.tsx#L150) to make the link visible in the Logs Explorer Page. ` ` ## πŸŽ₯ Demo https://github.com/elastic/kibana/assets/11225826/1f3ce10a-3b8c-4027-b72d-1ed71b782fa5 --- .../observability/locators/dataset_quality.ts | 33 ++++++ .../deeplinks/observability/locators/index.ts | 1 + .../datasets_quality_indicators.tsx | 6 +- .../public/hooks/use_summary_panel.tsx | 4 +- .../locators/dataset_quality_locator.ts | 29 +++++ .../common/locators/index.ts | 3 + .../common/locators/locators.test.ts | 42 +++++++- .../common/locators/types.ts | 4 + .../construct_dataset_quality_locator_path.ts | 47 ++++++++ .../common/locators/utils/index.ts | 1 + .../common/translations.ts | 7 ++ .../components/dataset_quality_link.tsx | 102 ++++++++++++++++++ .../public/plugin.ts | 8 ++ 13 files changed, 283 insertions(+), 4 deletions(-) create mode 100644 packages/deeplinks/observability/locators/dataset_quality.ts create mode 100644 x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/dataset_quality_locator.ts create mode 100644 x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/construct_dataset_quality_locator_path.ts create mode 100644 x-pack/plugins/observability_solution/observability_logs_explorer/public/components/dataset_quality_link.tsx diff --git a/packages/deeplinks/observability/locators/dataset_quality.ts b/packages/deeplinks/observability/locators/dataset_quality.ts new file mode 100644 index 0000000000000..eaaaf23c959ae --- /dev/null +++ b/packages/deeplinks/observability/locators/dataset_quality.ts @@ -0,0 +1,33 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { SerializableRecord } from '@kbn/utility-types'; + +export const DATASET_QUALITY_LOCATOR_ID = 'DATASET_QUALITY_LOCATOR'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type RefreshInterval = { + isPaused: boolean; + interval: number; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type TimeRangeConfig = { + from: string; + to: string; + refresh: RefreshInterval; +}; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +type Filters = { + timeRange: TimeRangeConfig; +}; + +export interface DatasetQualityLocatorParams extends SerializableRecord { + filters?: Filters; +} diff --git a/packages/deeplinks/observability/locators/index.ts b/packages/deeplinks/observability/locators/index.ts index 1dedf5e2a4083..73fe4b64bce9f 100644 --- a/packages/deeplinks/observability/locators/index.ts +++ b/packages/deeplinks/observability/locators/index.ts @@ -9,3 +9,4 @@ export * from './logs_explorer'; export * from './observability_logs_explorer'; export * from './observability_onboarding'; +export * from './dataset_quality'; diff --git a/x-pack/plugins/dataset_quality/public/components/dataset_quality/summary_panel/datasets_quality_indicators.tsx b/x-pack/plugins/dataset_quality/public/components/dataset_quality/summary_panel/datasets_quality_indicators.tsx index 999f260bde3c9..3da7d9b810b06 100644 --- a/x-pack/plugins/dataset_quality/public/components/dataset_quality/summary_panel/datasets_quality_indicators.tsx +++ b/x-pack/plugins/dataset_quality/public/components/dataset_quality/summary_panel/datasets_quality_indicators.tsx @@ -31,8 +31,10 @@ import { mapPercentagesToQualityCounts } from '../../quality_indicator'; import { InfoIndicators } from '../../common'; export function DatasetsQualityIndicators() { - const { datasetsQuality, isDatasetsQualityLoading } = useSummaryPanelContext(); + const { datasetsQuality, isDatasetsQualityLoading, datasetsActivity } = useSummaryPanelContext(); const qualityCounts = mapPercentagesToQualityCounts(datasetsQuality.percentages); + const datasetsWithoutIgnoredField = + datasetsActivity.total > 0 ? datasetsActivity.total - datasetsQuality.percentages.length : 0; return ( @@ -61,7 +63,7 @@ export function DatasetsQualityIndicators() { /> - state.matches('datasetsQuality.fetching') || state.matches('datasetsQuality.retrying') + state.matches('datasetsQuality.fetching') || + state.matches('datasetsQuality.retrying') || + state.matches('datasetsActivity.fetching') ); /* diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/dataset_quality_locator.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/dataset_quality_locator.ts new file mode 100644 index 0000000000000..33ea5616d2543 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/dataset_quality_locator.ts @@ -0,0 +1,29 @@ +/* + * 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 type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public'; +import { + DatasetQualityLocatorParams, + DATASET_QUALITY_LOCATOR_ID, +} from '@kbn/deeplinks-observability/locators'; +import { DatasetQualityLocatorDependencies } from './types'; +import { constructDatasetQualityLocatorPath } from './utils'; + +export type DatasetQualityLocator = LocatorPublic; + +export class DatasetQualityLocatorDefinition + implements LocatorDefinition +{ + public readonly id = DATASET_QUALITY_LOCATOR_ID; + + constructor(protected readonly deps: DatasetQualityLocatorDependencies) {} + + public readonly getLocation = async (params: DatasetQualityLocatorParams) => { + const { useHash } = this.deps; + return constructDatasetQualityLocatorPath({ useHash, locatorParams: params }); + }; +} diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/index.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/index.ts index 6692c6d30cea9..0c7fda1cd0f70 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/index.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/index.ts @@ -9,7 +9,9 @@ export type { ObservabilityLogsExplorerLocationState } from '@kbn/deeplinks-obse import { AllDatasetsLocator } from './all_datasets_locator'; import { DataViewLocator } from './data_view_locator'; import { SingleDatasetLocator } from './single_dataset_locator'; +import { DatasetQualityLocator } from './dataset_quality_locator'; +export * from './dataset_quality_locator'; export * from './single_dataset_locator'; export * from './all_datasets_locator'; export * from './utils'; @@ -18,4 +20,5 @@ export interface ObservabilityLogsExplorerLocators { allDatasetsLocator: AllDatasetsLocator; dataViewLocator: DataViewLocator; singleDatasetLocator: SingleDatasetLocator; + datasetQualityLocator: DatasetQualityLocator; } diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/locators.test.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/locators.test.ts index 902d7fd936e8d..05f5d4f53ee85 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/locators.test.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/locators.test.ts @@ -8,9 +8,10 @@ import { OBSERVABILITY_LOGS_EXPLORER_APP_ID } from '@kbn/deeplinks-observability'; import { AllDatasetsLocatorParams, - ObsLogsExplorerDataViewLocatorParams, SingleDatasetLocatorParams, + ObsLogsExplorerDataViewLocatorParams, } from '@kbn/deeplinks-observability/locators'; +import { DatasetQualityLocatorDefinition } from './dataset_quality_locator'; import { AllDatasetsLocatorDefinition } from './all_datasets_locator'; import { DataViewLocatorDefinition } from './data_view_locator'; import { SingleDatasetLocatorDefinition } from './single_dataset_locator'; @@ -23,11 +24,13 @@ const setup = async () => { const allDatasetsLocator = new AllDatasetsLocatorDefinition(dep); const dataViewLocator = new DataViewLocatorDefinition(dep); const singleDatasetLocator = new SingleDatasetLocatorDefinition(dep); + const datasetQualityLocator = new DatasetQualityLocatorDefinition(dep); return { allDatasetsLocator, dataViewLocator, singleDatasetLocator, + datasetQualityLocator, }; }; @@ -375,4 +378,41 @@ describe('Observability Logs Explorer Locators', () => { ); }); }); + + describe('Dataset Quality Locator', () => { + it('should create a link with correct path and no state', async () => { + const { datasetQualityLocator } = await setup(); + const location = await datasetQualityLocator.getLocation({}); + + expect(location).toMatchObject({ + app: OBSERVABILITY_LOGS_EXPLORER_APP_ID, + path: '/dataset-quality?pageState=(v:1)', + state: {}, + }); + }); + + it('should create a link with correct timeRange', async () => { + const refresh = { + isPaused: false, + interval: 0, + }; + const locatorParams = { + filters: { + timeRange: { + ...timeRange, + refresh, + }, + }, + }; + const { datasetQualityLocator } = await setup(); + + const location = await datasetQualityLocator.getLocation(locatorParams); + + expect(location).toMatchObject({ + app: OBSERVABILITY_LOGS_EXPLORER_APP_ID, + path: '/dataset-quality?pageState=(filters:(timeRange:(from:now-30m,refresh:(interval:0,isPaused:!f),to:now)),v:1)', + state: {}, + }); + }); + }); }); diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/types.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/types.ts index 4c80bcf31c2a6..b6b9364a2aee3 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/types.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/types.ts @@ -7,3 +7,7 @@ export interface ObsLogsExplorerLocatorDependencies { useHash: boolean; } + +export interface DatasetQualityLocatorDependencies { + useHash: boolean; +} diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/construct_dataset_quality_locator_path.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/construct_dataset_quality_locator_path.ts new file mode 100644 index 0000000000000..e38ffe33bc822 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/construct_dataset_quality_locator_path.ts @@ -0,0 +1,47 @@ +/* + * 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 { DatasetQualityLocatorParams } from '@kbn/deeplinks-observability/locators'; +import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common'; +import { OBSERVABILITY_LOGS_EXPLORER_APP_ID } from '@kbn/deeplinks-observability'; +import { + OBSERVABILITY_DATASET_QUALITY_URL_STATE_KEY, + datasetQualityUrlSchemaV1, +} from '../../url_schema'; +import { deepCompactObject } from '../../utils/deep_compact_object'; + +interface LocatorPathConstructionParams { + locatorParams: DatasetQualityLocatorParams; + useHash: boolean; +} + +export const constructDatasetQualityLocatorPath = async (params: LocatorPathConstructionParams) => { + const { + locatorParams: { filters }, + useHash, + } = params; + + const pageState = datasetQualityUrlSchemaV1.urlSchemaRT.encode( + deepCompactObject({ + v: 1, + filters, + }) + ); + + const path = setStateToKbnUrl( + OBSERVABILITY_DATASET_QUALITY_URL_STATE_KEY, + pageState, + { useHash, storeInHashQuery: false }, + '/dataset-quality' + ); + + return { + app: OBSERVABILITY_LOGS_EXPLORER_APP_ID, + path, + state: {}, + }; +}; diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/index.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/index.ts index 6e5aad44fbe9a..23c6a9b59c2d2 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/index.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/locators/utils/index.ts @@ -6,3 +6,4 @@ */ export * from './construct_locator_path'; +export * from './construct_dataset_quality_locator_path'; diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/common/translations.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/common/translations.ts index d7bd0724aeb07..dce0befbfea1e 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/common/translations.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/common/translations.ts @@ -53,3 +53,10 @@ export const feedbackLinkTitle = i18n.translate( defaultMessage: 'Give feedback', } ); + +export const datasetQualityLinkTitle = i18n.translate( + 'xpack.observabilityLogsExplorer.datasetQualityLinkTitle', + { + defaultMessage: 'Datasets', + } +); diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/public/components/dataset_quality_link.tsx b/x-pack/plugins/observability_solution/observability_logs_explorer/public/components/dataset_quality_link.tsx new file mode 100644 index 0000000000000..1d27ae931093b --- /dev/null +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/public/components/dataset_quality_link.tsx @@ -0,0 +1,102 @@ +/* + * 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 { EuiHeaderLink } from '@elastic/eui'; +import { + DatasetQualityLocatorParams, + DATASET_QUALITY_LOCATOR_ID, +} from '@kbn/deeplinks-observability/locators'; +import { LogsExplorerPublicState } from '@kbn/logs-explorer-plugin/public'; +import { getRouterLinkProps } from '@kbn/router-utils'; +import { BrowserUrlService } from '@kbn/share-plugin/public'; +import { MatchedStateFromActor } from '@kbn/xstate-utils'; +import { useActor } from '@xstate/react'; +import React from 'react'; +import { datasetQualityLinkTitle } from '../../common/translations'; +import { + ObservabilityLogsExplorerService, + useObservabilityLogsExplorerPageStateContext, +} from '../state_machines/observability_logs_explorer/src'; +import { useKibanaContextForPlugin } from '../utils/use_kibana'; + +export const ConnectedDatasetQualityLink = React.memo(() => { + const { + services: { + share: { url }, + }, + } = useKibanaContextForPlugin(); + const [pageState] = useActor(useObservabilityLogsExplorerPageStateContext()); + + if (pageState.matches({ initialized: 'validLogsExplorerState' })) { + return ; + } else { + return ; + } +}); + +type InitializedPageState = MatchedStateFromActor< + ObservabilityLogsExplorerService, + { initialized: 'validLogsExplorerState' } +>; + +const constructLocatorParams = ( + logsExplorerState: LogsExplorerPublicState +): DatasetQualityLocatorParams => { + const { time, refreshInterval } = logsExplorerState; + const locatorParams: DatasetQualityLocatorParams = { + filters: { + timeRange: { + from: time?.from || 'now-24h', + to: time?.to || 'now', + refresh: { + isPaused: refreshInterval ? refreshInterval.pause : false, + interval: refreshInterval ? refreshInterval.value : 60000, + }, + }, + }, + }; + + return locatorParams; +}; + +export const DatasetQualityLink = React.memo( + ({ + urlService, + pageState, + }: { + urlService: BrowserUrlService; + pageState?: InitializedPageState; + }) => { + const locator = urlService.locators.get( + DATASET_QUALITY_LOCATOR_ID + ); + const locatorParams: DatasetQualityLocatorParams = pageState + ? constructLocatorParams(pageState.context.logsExplorerState) + : {}; + + const datasetQualityUrl = locator?.useUrl(locatorParams); + + const navigateToDatasetQuality = () => { + locator?.navigate(locatorParams); + }; + + const datasetQualityLinkProps = getRouterLinkProps({ + href: datasetQualityUrl, + onClick: navigateToDatasetQuality, + }); + + return ( + + {datasetQualityLinkTitle} + + ); + } +); diff --git a/x-pack/plugins/observability_solution/observability_logs_explorer/public/plugin.ts b/x-pack/plugins/observability_solution/observability_logs_explorer/public/plugin.ts index c5042590e6e01..0a61aecf107be 100644 --- a/x-pack/plugins/observability_solution/observability_logs_explorer/public/plugin.ts +++ b/x-pack/plugins/observability_solution/observability_logs_explorer/public/plugin.ts @@ -16,6 +16,7 @@ import { import { OBSERVABILITY_LOGS_EXPLORER_APP_ID } from '@kbn/deeplinks-observability'; import { AllDatasetsLocatorDefinition, + DatasetQualityLocatorDefinition, ObservabilityLogsExplorerLocators, SingleDatasetLocatorDefinition, } from '../common/locators'; @@ -95,6 +96,12 @@ export class ObservabilityLogsExplorerPlugin useHash, }) ); + const datasetQualityLocator = share.url.locators.create( + new DatasetQualityLocatorDefinition({ + useHash, + }) + ); + const dataViewLocator = share.url.locators.create( new DataViewLocatorDefinition({ useHash, @@ -108,6 +115,7 @@ export class ObservabilityLogsExplorerPlugin this.locators = { allDatasetsLocator, + datasetQualityLocator, dataViewLocator, singleDatasetLocator, };