From 97e1206299d176e81c003c1c3e6a4898e1adb1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=BCrkan=20YALAMAN?= Date: Mon, 27 May 2024 16:56:52 +0200 Subject: [PATCH] [Search] Add sync status to connector page (#184024) ## Summary Adds Sync status to connector page. Adds a marker for content/access control sync buttons when last sync failed. Changes logic to show error message to make sure access control errors aren't lost. Fixes incomplete connector query to show correct counts on list. Screenshot 2024-05-22 at 16 01 27 Screenshot 2024-05-22 at 16 03 12 ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../connector_detail/connector_stats.tsx | 6 +-- .../connector_detail/connector_view_logic.ts | 6 ++- .../components/connector_detail/overview.tsx | 5 ++- .../components/connectors/connector_stats.tsx | 1 + .../connectors/connectors_table.tsx | 8 +--- .../search_index/index_view_logic.ts | 6 ++- .../components/search_index/overview.tsx | 18 +++++++-- .../search_index/sync_jobs/sync_jobs.tsx | 12 +++++- .../utils/connector_status_helpers.ts | 37 +++++++++++++------ .../server/utils/get_sync_jobs_queries.ts | 24 +++++------- 10 files changed, 79 insertions(+), 44 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx index 095844b4e04d48..d8725141eb5e3f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_stats.tsx @@ -122,10 +122,8 @@ export const ConnectorStats: React.FC = ({ connector, index - - {connectorStatusToText(connector?.status, !!connector?.index_name)} + + {connectorStatusToText(connector)} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_view_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_view_logic.ts index f7d6f30ee7d54f..42d881300ac5d1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_view_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/connector_view_logic.ts @@ -158,7 +158,11 @@ export const ConnectorViewLogic = kea [selectors.connector], (connector) => connector?.id], error: [ () => [selectors.connector], - (connector: Connector | undefined) => connector?.error || connector?.last_sync_error || null, + (connector: Connector | undefined) => + connector?.error || + connector?.last_sync_error || + connector?.last_access_control_sync_error || + null, ], indexName: [ () => [selectors.connector], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/overview.tsx index a97f7b8c862fd1..1931f0f9455054 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/overview.tsx @@ -186,7 +186,10 @@ export const ConnectorDetailOverview: React.FC = () => { {connector && connector.service_type !== ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE && ( <> - + )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connector_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connector_stats.tsx index 8b2ad4490a1a6b..db76e97ec719e7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connector_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connector_stats.tsx @@ -213,6 +213,7 @@ export const ConnectorStats: React.FC = ({ isCrawler }) => {}} onClickAriaLabel={getSyncJobErrorsLabel(errorCount, isCrawler)} + color={errorCount > 0 ? 'danger' : 'default'} > {getSyncJobErrorsLabel(errorCount, isCrawler)} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connectors_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connectors_table.tsx index daf3f59eef45ed..82f258487f39ec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connectors_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/connectors_table.tsx @@ -135,12 +135,8 @@ export const ConnectorsTable: React.FC = ({ } ), render: (connector: ConnectorViewItem) => { - const label = connectorStatusToText(connector.status, !!connector.index_name); - return ( - - {label} - - ); + const label = connectorStatusToText(connector); + return {label}; }, truncateText: true, width: '15%', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts index 57f6d8f11bfcef..597757e83534a7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/index_view_logic.ts @@ -264,7 +264,11 @@ export const IndexViewLogic = kea [selectors.connector], - (connector: Connector | undefined) => connector?.error || connector?.last_sync_error || null, + (connector: Connector | undefined) => + connector?.error || + connector?.last_sync_error || + connector?.last_access_control_sync_error || + null, ], hasAdvancedFilteringFeature: [ () => [selectors.connector], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx index b280d3fbf36b78..f8ccf71026e83b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx @@ -81,7 +81,11 @@ export const SearchIndexOverview: React.FC = () => { defaultMessage="Convert it to a {link}, to be self-managed on your own infrastructure. Native connectors are available only in your Elastic Cloud deployment." values={{ link: ( - + {i18n.translate( 'xpack.enterpriseSearch.content.searchIndex.nativeCloudCallout.connectorClient', { defaultMessage: 'connector client' } @@ -93,7 +97,12 @@ export const SearchIndexOverview: React.FC = () => {

- showModal()}> + showModal()} + > {i18n.translate( 'xpack.enterpriseSearch.content.indices.searchIndex.convertConnector.buttonLabel', { defaultMessage: 'Convert connector' } @@ -126,7 +135,10 @@ export const SearchIndexOverview: React.FC = () => { {isConnectorIndex(indexData) && ( <> - + )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs.tsx index 2013d601df4aa8..49f49591007361 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs/sync_jobs.tsx @@ -21,7 +21,15 @@ import { IndexViewLogic } from '../index_view_logic'; import { SyncJobsViewLogic } from './sync_jobs_view_logic'; -export const SyncJobs: React.FC = () => { +export interface SyncJobsProps { + errorOnAccessSync?: boolean; + errorOnContentSync?: boolean; +} + +export const SyncJobs: React.FC = ({ + errorOnAccessSync = false, + errorOnContentSync = false, +}) => { const { hasDocumentLevelSecurityFeature } = useValues(IndexViewLogic); const { productFeatures } = useValues(KibanaLogic); const shouldShowAccessSyncs = @@ -74,6 +82,7 @@ export const SyncJobs: React.FC = () => { 'xpack.enterpriseSearch.content.syncJobs.lastSync.tableSelector.content.label', { defaultMessage: 'Content syncs' } ), + ...(errorOnContentSync ? { iconSide: 'right', iconType: 'warning' } : {}), }, { @@ -82,6 +91,7 @@ export const SyncJobs: React.FC = () => { 'xpack.enterpriseSearch.content.syncJobs.lastSync.tableSelector.accessControl.label', { defaultMessage: 'Access control syncs' } ), + ...(errorOnAccessSync ? { iconSide: 'right', iconType: 'warning' } : {}), }, ]} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/connector_status_helpers.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/connector_status_helpers.ts index ef8e84177eae10..587539498c7865 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/connector_status_helpers.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/connector_status_helpers.ts @@ -6,17 +6,16 @@ */ import { i18n } from '@kbn/i18n'; -import { ConnectorStatus } from '@kbn/search-connectors'; +import { Connector, ConnectorStatus, SyncStatus } from '@kbn/search-connectors'; const incompleteText = i18n.translate( 'xpack.enterpriseSearch.content.searchIndices.ingestionStatus.incomplete.label', { defaultMessage: 'Incomplete' } ); -export function connectorStatusToText( - connectorStatus: ConnectorStatus, - hasIndexName: boolean -): string { +export function connectorStatusToText(connector: Connector): string { + const hasIndexName = !!connector.index_name; + const connectorStatus = connector.status; if ( connectorStatus === ConnectorStatus.CREATED || connectorStatus === ConnectorStatus.NEEDS_CONFIGURATION @@ -26,6 +25,16 @@ export function connectorStatusToText( { defaultMessage: 'Needs Configuration' } ); } + if ( + connector.error === SyncStatus.ERROR || + connector.last_sync_error !== null || + connector.last_access_control_sync_error !== null + ) { + return i18n.translate( + 'xpack.enterpriseSearch.content.searchIndices.connectorStatus.syncFailure.label', + { defaultMessage: 'Sync Failure' } + ); + } if (connectorStatus === ConnectorStatus.ERROR) { return i18n.translate( 'xpack.enterpriseSearch.content.searchIndices.connectorStatus.connectorFailure.label', @@ -51,18 +60,22 @@ export function connectorStatusToText( return incompleteText; } -export function connectorStatusToColor( - connectorStatus: ConnectorStatus, - hasIndexName: boolean -): 'warning' | 'danger' | 'success' { +export function connectorStatusToColor(connector: Connector): 'warning' | 'danger' | 'success' { + const hasIndexName = !!connector.index_name; + const connectorStatus = connector.status; if (!hasIndexName) { return 'warning'; } + if ( + connectorStatus === ConnectorStatus.ERROR || + connector.error === SyncStatus.ERROR || + connector.last_sync_error !== null || + connector.last_access_control_sync_error !== null + ) { + return 'danger'; + } if (connectorStatus === ConnectorStatus.CONNECTED) { return 'success'; } - if (connectorStatus === ConnectorStatus.ERROR) { - return 'danger'; - } return 'warning'; } diff --git a/x-pack/plugins/enterprise_search/server/utils/get_sync_jobs_queries.ts b/x-pack/plugins/enterprise_search/server/utils/get_sync_jobs_queries.ts index 5fe2e9b17eff73..ff6eeee4db472f 100644 --- a/x-pack/plugins/enterprise_search/server/utils/get_sync_jobs_queries.ts +++ b/x-pack/plugins/enterprise_search/server/utils/get_sync_jobs_queries.ts @@ -331,24 +331,18 @@ export const getIncompleteCountQuery = (isCrawler?: boolean) => { } return { bool: { - should: [ - { - bool: { - must_not: { - terms: { - status: [ConnectorStatus.CONNECTED, ConnectorStatus.ERROR], - }, - }, - }, + must_not: { + terms: { + status: [ConnectorStatus.CONNECTED, ConnectorStatus.ERROR], }, - { - range: { - last_seen: { - lt: moment().subtract(30, 'minutes').toISOString(), - }, + }, + must: { + range: { + last_seen: { + lt: moment().subtract(30, 'minutes').toISOString(), }, }, - ], + }, filter: [ { bool: {