diff --git a/x-pack/plugins/observability_solution/dataset_quality/common/translations.ts b/x-pack/plugins/observability_solution/dataset_quality/common/translations.ts index f6be84509761f..53e0e47f8f794 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/common/translations.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/common/translations.ts @@ -46,6 +46,13 @@ export const flyoutOpenInLogsExplorerText = i18n.translate( } ); +export const flyoutOpenInDiscoverText = i18n.translate( + 'xpack.datasetQuality.flyoutOpenInDiscoverText', + { + defaultMessage: 'Open in Discover', + } +); + export const flyoutDatasetDetailsText = i18n.translate( 'xpack.datasetQuality.flyoutDatasetDetailsText', { diff --git a/x-pack/plugins/observability_solution/dataset_quality/kibana.jsonc b/x-pack/plugins/observability_solution/dataset_quality/kibana.jsonc index 473f143a67cdc..af5a48748fb0e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/kibana.jsonc +++ b/x-pack/plugins/observability_solution/dataset_quality/kibana.jsonc @@ -25,7 +25,7 @@ "lens" ], "optionalPlugins": [], - "requiredBundles": ["unifiedHistogram"], + "requiredBundles": ["unifiedHistogram", "discover"], "extraPublicDirs": [ "common" ] diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx index a457053db2e07..6f61883719098 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/columns.tsx @@ -33,7 +33,7 @@ import { import { DataStreamStat } from '../../../../common/data_streams_stats/data_stream_stat'; import { DatasetQualityIndicator, QualityIndicator } from '../../quality_indicator'; import { IntegrationIcon } from '../../common'; -import { useLinkToLogsExplorer } from '../../../hooks'; +import { useRedirectLink } from '../../../hooks'; import { FlyoutDataset } from '../../../state_machines/dataset_quality_controller'; import { DegradedDocsPercentageLink } from './degraded_docs_percentage_link'; @@ -320,24 +320,24 @@ export const getDatasetQualityTableColumns = ({ { name: actionsColumnName, render: (dataStreamStat: DataStreamStat) => ( - + ), width: '100px', }, ]; }; -const LogsExplorerLink = ({ +const RedirectLink = ({ dataStreamStat, title, }: { dataStreamStat: DataStreamStat; title: string; }) => { - const logsExplorerLinkProps = useLinkToLogsExplorer({ dataStreamStat }); + const redirectLinkProps = useRedirectLink({ dataStreamStat }); return ( - + {title} ); diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx index d8aade6d74e51..66f61d6996bd3 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/dataset_quality/table/degraded_docs_percentage_link.tsx @@ -8,7 +8,7 @@ import { EuiSkeletonRectangle, EuiFlexGroup, EuiLink } from '@elastic/eui'; import React from 'react'; import { _IGNORED } from '../../../../common/es_fields'; -import { useLinkToLogsExplorer } from '../../../hooks'; +import { useRedirectLink } from '../../../hooks'; import { QualityPercentageIndicator } from '../../quality_indicator'; import { DataStreamStat } from '../../../../common/data_streams_stats/data_stream_stat'; @@ -23,7 +23,7 @@ export const DegradedDocsPercentageLink = ({ degradedDocs: { percentage, count }, } = dataStreamStat; - const logsExplorerLinkProps = useLinkToLogsExplorer({ + const redirectLinkProps = useRedirectLink({ dataStreamStat, query: { language: 'kuery', query: `${_IGNORED}: *` }, }); @@ -32,10 +32,7 @@ export const DegradedDocsPercentageLink = ({ {percentage ? ( - + ) : ( diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx index 66aa5e2e1daf7..c95cd7cae0d1a 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/flyout_summary/flyout_summary_kpis.tsx @@ -12,7 +12,7 @@ import { _IGNORED } from '../../../../common/es_fields'; import { DataStreamDetails } from '../../../../common/api_types'; import { useKibanaContextForPlugin } from '../../../utils'; -import { useLinkToLogsExplorer } from '../../../hooks'; +import { useRedirectLink } from '../../../hooks'; import { FlyoutDataset, TimeRangeConfig } from '../../../state_machines/dataset_quality_controller'; import { FlyoutSummaryKpiItem, FlyoutSummaryKpiItemLoading } from './flyout_summary_kpi_item'; import { getSummaryKpis } from './get_summary_kpis'; @@ -33,7 +33,7 @@ export function FlyoutSummaryKpis({ } = useKibanaContextForPlugin(); const hostsLocator = observabilityShared.locators.infra.hostsLocator; - const logsExplorerLinkProps = useLinkToLogsExplorer({ + const redirectLinkProps = useRedirectLink({ dataStreamStat, query: { language: 'kuery', query: `${_IGNORED}: *` }, timeRangeConfig: timeRange, @@ -44,10 +44,10 @@ export function FlyoutSummaryKpis({ getSummaryKpis({ dataStreamDetails, timeRange, - degradedDocsHref: logsExplorerLinkProps.href, + degradedDocsHref: redirectLinkProps.href, hostsLocator, }), - [dataStreamDetails, logsExplorerLinkProps, hostsLocator, timeRange] + [dataStreamDetails, redirectLinkProps, hostsLocator, timeRange] ); return ( diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx index 189567560112f..63fb761ce87f5 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/components/flyout/header.tsx @@ -16,8 +16,11 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; import React from 'react'; -import { flyoutOpenInLogsExplorerText } from '../../../common/translations'; -import { useLinkToLogsExplorer } from '../../hooks'; +import { + flyoutOpenInDiscoverText, + flyoutOpenInLogsExplorerText, +} from '../../../common/translations'; +import { useRedirectLink } from '../../hooks'; import { FlyoutDataset } from '../../state_machines/dataset_quality_controller'; import { IntegrationIcon } from '../common'; @@ -25,7 +28,7 @@ export function Header({ dataStreamStat }: { dataStreamStat: FlyoutDataset }) { const { integration, title } = dataStreamStat; const euiShadow = useEuiShadow('s'); const { euiTheme } = useEuiTheme(); - const logsExplorerLinkProps = useLinkToLogsExplorer({ dataStreamStat }); + const redirectLinkProps = useRedirectLink({ dataStreamStat }); return ( @@ -58,10 +61,14 @@ export function Header({ dataStreamStat }: { dataStreamStat: FlyoutDataset }) { - {flyoutOpenInLogsExplorerText} + {redirectLinkProps.isLogsExplorerAvailable + ? flyoutOpenInLogsExplorerText + : flyoutOpenInDiscoverText} diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts index eafeddaeb1386..aa9c59ed77b3c 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/index.ts @@ -8,7 +8,7 @@ export * from './use_dataset_quality_table'; export * from './use_dataset_quality_flyout'; export * from './use_degraded_docs_chart'; -export * from './use_link_to_logs_explorer'; +export * from './use_redirect_link'; export * from './use_summary_panel'; export * from './use_create_dataview'; export * from './use_dataset_quality_degraded_field'; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx index 84a09f8cbf5f1..c1bbca58d645e 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_degraded_docs_chart.tsx @@ -17,7 +17,7 @@ import { DEFAULT_LOGS_DATA_VIEW } from '../../common/constants'; import { indexNameToDataStreamParts } from '../../common/utils'; import { getLensAttributes } from '../components/flyout/degraded_docs_trend/lens_attributes'; import { useCreateDataView } from './use_create_dataview'; -import { useLinkToLogsExplorer } from './use_link_to_logs_explorer'; +import { useRedirectLink } from './use_redirect_link'; import { useDatasetQualityFlyout } from './use_dataset_quality_flyout'; import { useKibanaContextForPlugin } from '../utils'; @@ -28,6 +28,13 @@ const exploreDataInLogsExplorerText = i18n.translate( } ); +const exploreDataInDiscoverText = i18n.translate( + 'xpack.datasetQuality.flyoutChartExploreDataInDiscoverText', + { + defaultMessage: 'Explore data in Discover', + } +); + const openInLensText = i18n.translate('xpack.datasetQuality.flyoutChartOpenInLensText', { defaultMessage: 'Open in Lens', }); @@ -125,7 +132,7 @@ export const useDegradedDocsChart = ({ dataStream }: DegradedDocsChartDeps) => { }; }, [openInLensCallback]); - const logsExplorerLinkProps = useLinkToLogsExplorer({ + const redirectLinkProps = useRedirectLink({ dataStreamStat: dataStreamStat!, query: { language: 'kuery', query: '_ignored:*' }, timeRangeConfig: timeRange, @@ -137,10 +144,12 @@ export const useDegradedDocsChart = ({ dataStream }: DegradedDocsChartDeps) => { id: ACTION_EXPLORE_IN_LOGS_EXPLORER, type: 'link', getDisplayName(): string { - return exploreDataInLogsExplorerText; + return redirectLinkProps?.isLogsExplorerAvailable + ? exploreDataInLogsExplorerText + : exploreDataInDiscoverText; }, getHref: async () => { - return logsExplorerLinkProps.href; + return redirectLinkProps.href; }, getIconType(): string | undefined { return 'popout'; @@ -149,11 +158,11 @@ export const useDegradedDocsChart = ({ dataStream }: DegradedDocsChartDeps) => { return true; }, async execute(): Promise { - return logsExplorerLinkProps.navigate(); + return redirectLinkProps.navigate(); }, order: 18, }; - }, [logsExplorerLinkProps]); + }, [redirectLinkProps]); const extraActions: Action[] = [getOpenInLensAction, getOpenInLogsExplorerAction]; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_link_to_logs_explorer.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_link_to_logs_explorer.ts deleted file mode 100644 index ff442f970ab21..0000000000000 --- a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_link_to_logs_explorer.ts +++ /dev/null @@ -1,71 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SINGLE_DATASET_LOCATOR_ID, - SingleDatasetLocatorParams, -} from '@kbn/deeplinks-observability'; -import { Query, AggregateQuery } from '@kbn/es-query'; -import { getRouterLinkProps } from '@kbn/router-utils'; -import { useSelector } from '@xstate/react'; -import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat'; -import { useDatasetQualityContext } from '../components/dataset_quality/context'; -import { FlyoutDataset, TimeRangeConfig } from '../state_machines/dataset_quality_controller'; -import { useKibanaContextForPlugin } from '../utils'; - -export const useLinkToLogsExplorer = ({ - dataStreamStat, - query, - timeRangeConfig, - breakdownField, -}: { - dataStreamStat: DataStreamStat | FlyoutDataset; - query?: Query | AggregateQuery; - timeRangeConfig?: TimeRangeConfig; - breakdownField?: string; -}) => { - const { - services: { share }, - } = useKibanaContextForPlugin(); - - const { service } = useDatasetQualityContext(); - const { timeRange } = useSelector(service, (state) => state.context.filters); - const { from, to } = timeRangeConfig || timeRange; - - const params: SingleDatasetLocatorParams = { - dataset: dataStreamStat.name, - timeRange: { - from, - to, - }, - integration: dataStreamStat.integration?.name, - query, - filterControls: { - namespace: { - mode: 'include', - values: [dataStreamStat.namespace], - }, - }, - breakdownField, - }; - - const singleDatasetLocator = - share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); - - const urlToLogsExplorer = singleDatasetLocator?.getRedirectUrl(params); - - const navigateToLogsExplorer = () => { - singleDatasetLocator?.navigate(params) as Promise; - }; - - const logsExplorerLinkProps = getRouterLinkProps({ - href: urlToLogsExplorer, - onClick: navigateToLogsExplorer, - }); - - return { ...logsExplorerLinkProps, navigate: navigateToLogsExplorer }; -}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts new file mode 100644 index 0000000000000..751b7e14ebb79 --- /dev/null +++ b/x-pack/plugins/observability_solution/dataset_quality/public/hooks/use_redirect_link.ts @@ -0,0 +1,191 @@ +/* + * 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 { + SINGLE_DATASET_LOCATOR_ID, + SingleDatasetLocatorParams, +} from '@kbn/deeplinks-observability'; +import { DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '@kbn/discover-plugin/common'; +import { Query, AggregateQuery, buildPhraseFilter } from '@kbn/es-query'; +import { getRouterLinkProps } from '@kbn/router-utils'; +import { RouterLinkProps } from '@kbn/router-utils/src/get_router_link_props'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { LocatorClient } from '@kbn/shared-ux-prompt-no-data-views-types'; +import { useSelector } from '@xstate/react'; +import { DataStreamStat } from '../../common/data_streams_stats/data_stream_stat'; +import { useDatasetQualityContext } from '../components/dataset_quality/context'; +import { FlyoutDataset, TimeRangeConfig } from '../state_machines/dataset_quality_controller'; +import { useKibanaContextForPlugin } from '../utils'; + +export const useRedirectLink = ({ + dataStreamStat, + query, + timeRangeConfig, + breakdownField, +}: { + dataStreamStat: DataStreamStat | FlyoutDataset; + query?: Query | AggregateQuery; + timeRangeConfig?: TimeRangeConfig; + breakdownField?: string; +}) => { + const { + services: { share }, + } = useKibanaContextForPlugin(); + + const { service } = useDatasetQualityContext(); + const { timeRange } = useSelector(service, (state) => state.context.filters); + const { from, to } = timeRangeConfig || timeRange; + + const logsExplorerLocator = + share.url.locators.get(SINGLE_DATASET_LOCATOR_ID); + + const config = logsExplorerLocator + ? buildLogsExplorerConfig({ + locator: logsExplorerLocator, + dataStreamStat, + query, + from, + to, + breakdownField, + }) + : buildDiscoverConfig({ + locatorClient: share.url.locators, + dataStreamStat, + query, + from, + to, + breakdownField, + }); + + return { + ...config.routerLinkProps, + navigate: config.navigate, + isLogsExplorerAvailable: !!logsExplorerLocator, + }; +}; + +const buildLogsExplorerConfig = ({ + locator, + dataStreamStat, + query, + from, + to, + breakdownField, +}: { + locator: LocatorPublic; + dataStreamStat: DataStreamStat | FlyoutDataset; + query?: Query | AggregateQuery; + from: string; + to: string; + breakdownField?: string; +}): { + navigate: () => void; + routerLinkProps: RouterLinkProps; +} => { + const params: SingleDatasetLocatorParams = { + dataset: dataStreamStat.name, + timeRange: { + from, + to, + }, + integration: dataStreamStat.integration?.name, + query, + filterControls: { + namespace: { + mode: 'include', + values: [dataStreamStat.namespace], + }, + }, + breakdownField, + }; + + const urlToLogsExplorer = locator.getRedirectUrl(params); + + const navigateToLogsExplorer = () => { + locator.navigate(params) as Promise; + }; + + const logsExplorerLinkProps = getRouterLinkProps({ + href: urlToLogsExplorer, + onClick: navigateToLogsExplorer, + }); + + return { routerLinkProps: logsExplorerLinkProps, navigate: navigateToLogsExplorer }; +}; + +const buildDiscoverConfig = ({ + locatorClient, + dataStreamStat, + query, + from, + to, + breakdownField, +}: { + locatorClient: LocatorClient; + dataStreamStat: DataStreamStat | FlyoutDataset; + query?: Query | AggregateQuery; + from: string; + to: string; + breakdownField?: string; +}): { + navigate: () => void; + routerLinkProps: RouterLinkProps; +} => { + const dataViewId = `${dataStreamStat.type}-${dataStreamStat.name}-*`; + const dataViewTitle = dataStreamStat.integration + ? `[${dataStreamStat.integration.title}] ${dataStreamStat.name}` + : `${dataViewId}`; + + const params: DiscoverAppLocatorParams = { + timeRange: { + from, + to, + }, + refreshInterval: { + pause: true, + value: 60000, + }, + dataViewId, + dataViewSpec: { + id: dataViewId, + title: dataViewTitle, + }, + query, + breakdownField, + columns: ['@timestamp', 'message'], + filters: [ + buildPhraseFilter( + { + name: 'data_stream.namespace', + type: 'string', + }, + dataStreamStat.namespace, + { + id: dataViewId, + title: dataViewTitle, + } + ), + ], + interval: 'auto', + sort: [['@timestamp', 'desc']], + }; + + const locator = locatorClient.get(DISCOVER_APP_LOCATOR); + + const urlToDiscover = locator?.getRedirectUrl(params); + + const navigateToDiscover = () => { + locator?.navigate(params) as Promise; + }; + + const discoverLinkProps = getRouterLinkProps({ + href: urlToDiscover, + onClick: navigateToDiscover, + }); + + return { routerLinkProps: discoverLinkProps, navigate: navigateToDiscover }; +}; diff --git a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json index 843b7963ffb0c..631e44b121a97 100644 --- a/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json +++ b/x-pack/plugins/observability_solution/dataset_quality/tsconfig.json @@ -41,7 +41,9 @@ "@kbn/deeplinks-analytics", "@kbn/core-elasticsearch-server", "@kbn/ui-actions-plugin", - "@kbn/metrics-data-access-plugin" + "@kbn/metrics-data-access-plugin", + "@kbn/discover-plugin", + "@kbn/shared-ux-prompt-no-data-views-types" ], "exclude": ["target/**/*"] }