diff --git a/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_job_status/job_configuration_outdated_callout.tsx b/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_job_status/job_configuration_outdated_callout.tsx index 877ac4a9e3b35..f3bfd2d7dc6fd 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_job_status/job_configuration_outdated_callout.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/logging/log_analysis_job_status/job_configuration_outdated_callout.tsx @@ -28,7 +28,7 @@ export const JobConfigurationOutdatedCallout: React.FC<{ > { + const { + services: { application }, + } = useKibanaContextForPlugin(); + + const advancedSettingsHref = useMemo( + () => getKibanaAdvancedSettingsHref(application), + [application] + ); + const changeIsIndexSelected = useCallback( (indexName: string, isSelected: boolean) => { onChangeSelectedIndices( @@ -67,7 +84,20 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{ + + + ), + }} /> diff --git a/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx b/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx index a8c371fa9439e..98d6213ad4357 100644 --- a/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx +++ b/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx @@ -18,14 +18,14 @@ import { useLogEntryCategoriesQuality } from './use_log_entry_categories_quality export const useLogEntryCategoriesModule = ({ indexPattern, - logViewId, + sourceId, spaceId, idFormat, timestampField, runtimeMappings, }: { indexPattern: string; - logViewId: string; + sourceId: string; spaceId: string; idFormat: IdFormat; timestampField: string; @@ -34,12 +34,12 @@ export const useLogEntryCategoriesModule = ({ const sourceConfiguration: ModuleSourceConfiguration = useMemo( () => ({ indices: indexPattern.split(','), - sourceId: logViewId, + sourceId, spaceId, timestampField, runtimeMappings, }), - [indexPattern, logViewId, spaceId, timestampField, runtimeMappings] + [indexPattern, sourceId, spaceId, timestampField, runtimeMappings] ); const logAnalysisModule = useLogAnalysisModule({ diff --git a/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx b/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx index a00d9f0017c31..fa3d13294a634 100644 --- a/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx +++ b/x-pack/plugins/observability_solution/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx @@ -17,14 +17,14 @@ import { logEntryRateModule } from './module_descriptor'; export const useLogEntryRateModule = ({ indexPattern, - logViewId, + sourceId, spaceId, idFormat, timestampField, runtimeMappings, }: { indexPattern: string; - logViewId: string; + sourceId: string; spaceId: string; idFormat: IdFormat; timestampField: string; @@ -33,12 +33,12 @@ export const useLogEntryRateModule = ({ const sourceConfiguration: ModuleSourceConfiguration = useMemo( () => ({ indices: indexPattern.split(','), - sourceId: logViewId, + sourceId, spaceId, timestampField, runtimeMappings, }), - [indexPattern, logViewId, spaceId, timestampField, runtimeMappings] + [indexPattern, sourceId, spaceId, timestampField, runtimeMappings] ); const logAnalysisModule = useLogAnalysisModule({ diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_providers.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_providers.tsx index bd1ae5d9c8336..f7a749eb6a312 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_providers.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_providers.tsx @@ -6,26 +6,27 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { useLogViewContext } from '@kbn/logs-shared-plugin/public'; +import { useLogSourcesContext } from '@kbn/logs-data-access-plugin/public'; import { logEntryCategoriesJobType } from '../../../../common/log_analysis'; -import { InlineLogViewSplashPage } from '../../../components/logging/inline_log_view_splash_page'; import { LogAnalysisSetupFlyoutStateProvider } from '../../../components/logging/log_analysis_setup/setup_flyout'; import { SourceLoadingPage } from '../../../components/source_loading_page'; import { LogEntryCategoriesModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_categories'; import { useActiveKibanaSpace } from '../../../hooks/use_kibana_space'; -import { ConnectedLogViewErrorPage } from '../shared/page_log_view_error'; +import { LogSourceErrorPage } from '../shared/page_log_view_error'; import { useLogMlJobIdFormatsShimContext } from '../shared/use_log_ml_job_id_formats_shim'; +const TIMESTAMP_FIELD = '@timestamp'; +const DEFAULT_MODULE_SOURCE_CONFIGURATION_ID = 'default'; // NOTE: Left in for legacy reasons, this used to refer to a log view ID (legacy). + export const LogEntryCategoriesPageProviders: FC> = ({ children }) => { const { - hasFailedLoading, - isLoading, + logSources, + isLoadingLogSources, isUninitialized, - resolvedLogView, - logViewReference, - isPersistedLogView, - revertToDefaultLogView, - } = useLogViewContext(); + hasFailedLoadingLogSources, + logSourcesError, + combinedIndices, + } = useLogSourcesContext(); const { space } = useActiveKibanaSpace(); const { idFormats, isLoadingLogAnalysisIdFormats, hasFailedLoadingLogAnalysisIdFormats } = useLogMlJobIdFormatsShimContext(); @@ -35,24 +36,24 @@ export const LogEntryCategoriesPageProviders: FC> = ( // React concurrent mode and Suspense in order to handle that more gracefully. if (space == null) { return null; - } else if (!isPersistedLogView) { - return ; - } else if (hasFailedLoading || hasFailedLoadingLogAnalysisIdFormats) { - return ; - } else if (isLoading || isUninitialized || isLoadingLogAnalysisIdFormats || !idFormats) { + } else if (hasFailedLoadingLogSources || hasFailedLoadingLogAnalysisIdFormats) { + return ; + } else if ( + isLoadingLogSources || + isUninitialized || + isLoadingLogAnalysisIdFormats || + !idFormats + ) { return ; - } else if (resolvedLogView != null) { - if (logViewReference.type === 'log-view-inline') { - throw new Error('Logs ML features only support persisted Log View references'); - } + } else if (logSources.length > 0) { return ( {children} diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/page_providers.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/page_providers.tsx index d2cf0f3e613ee..a57eac0a16cd8 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/page_providers.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/page_providers.tsx @@ -6,29 +6,29 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { useLogViewContext } from '@kbn/logs-shared-plugin/public'; +import { useLogSourcesContext } from '@kbn/logs-data-access-plugin/public'; import { logEntryCategoriesJobType, logEntryRateJobType } from '../../../../common/log_analysis'; -import { InlineLogViewSplashPage } from '../../../components/logging/inline_log_view_splash_page'; import { LogAnalysisSetupFlyoutStateProvider } from '../../../components/logging/log_analysis_setup/setup_flyout'; import { SourceLoadingPage } from '../../../components/source_loading_page'; import { LogEntryCategoriesModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_categories'; import { LogEntryRateModuleProvider } from '../../../containers/logs/log_analysis/modules/log_entry_rate'; import { LogEntryFlyoutProvider } from '../../../containers/logs/log_flyout'; import { useActiveKibanaSpace } from '../../../hooks/use_kibana_space'; -import { ConnectedLogViewErrorPage } from '../shared/page_log_view_error'; +import { LogSourceErrorPage } from '../shared/page_log_view_error'; import { useLogMlJobIdFormatsShimContext } from '../shared/use_log_ml_job_id_formats_shim'; +const TIMESTAMP_FIELD = '@timestamp'; +const DEFAULT_MODULE_SOURCE_CONFIGURATION_ID = 'default'; // NOTE: Left in for legacy reasons, this used to refer to a log view ID (legacy). + export const LogEntryRatePageProviders: FC> = ({ children }) => { const { - hasFailedLoading, - isLoading, + logSources, + isLoadingLogSources, isUninitialized, - logViewReference, - resolvedLogView, - isPersistedLogView, - revertToDefaultLogView, - } = useLogViewContext(); - + hasFailedLoadingLogSources, + logSourcesError, + combinedIndices, + } = useLogSourcesContext(); const { space } = useActiveKibanaSpace(); const { idFormats, isLoadingLogAnalysisIdFormats, hasFailedLoadingLogAnalysisIdFormats } = @@ -39,33 +39,33 @@ export const LogEntryRatePageProviders: FC> = ({ chil // React concurrent mode and Suspense in order to handle that more gracefully. if (space == null) { return null; - } else if (!isPersistedLogView) { - return ; - } else if (isLoading || isUninitialized || isLoadingLogAnalysisIdFormats || !idFormats) { + } else if ( + isLoadingLogSources || + isUninitialized || + isLoadingLogAnalysisIdFormats || + !idFormats + ) { return ; - } else if (hasFailedLoading || hasFailedLoadingLogAnalysisIdFormats) { - return ; - } else if (resolvedLogView != null) { - if (logViewReference.type === 'log-view-inline') { - throw new Error('Logs ML features only support persisted Log Views'); - } + } else if (hasFailedLoadingLogSources || hasFailedLoadingLogAnalysisIdFormats) { + return ; + } else if (logSources.length > 0) { return ( {children} diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/page_providers.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/page_providers.tsx index db4f00a8ab2b2..a0cd7f8639b24 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/page_providers.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/page_providers.tsx @@ -12,6 +12,7 @@ import { updateContextInUrl as createUpdateContextInUrl, listenForUrlChanges as createListenForUrlChanges, } from '@kbn/logs-shared-plugin/public'; +import { LogSourcesProvider } from '@kbn/logs-data-access-plugin/public'; import { LogAnalysisCapabilitiesProvider } from '../../containers/logs/log_analysis'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; import { useKbnUrlStateStorageFromRouterContext } from '../../containers/kbn_url_state_context'; @@ -21,6 +22,7 @@ export const LogsPageProviders: FC> = ({ children }) services: { notifications: { toasts: toastsService }, logsShared, + logsDataAccess, }, } = useKibanaContextForPlugin(); @@ -43,7 +45,9 @@ export const LogsPageProviders: FC> = ({ children }) updateContextInUrl={updateContextInUrl} listenForUrlChanges={listenForUrlChanges} > - {children} + + {children} + ); }; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/kibana_advanced_setting_configuration_panel.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/kibana_advanced_setting_configuration_panel.tsx index 1d7d4ad997407..49636e4171f2f 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/kibana_advanced_setting_configuration_panel.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/kibana_advanced_setting_configuration_panel.tsx @@ -7,12 +7,12 @@ import { EuiDescribedFormGroup, EuiFieldText, EuiFormRow } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useMemo } from 'react'; import { useTrackPageview } from '@kbn/observability-shared-plugin/public'; import { LogSourcesKibanaAdvancedSettingReference } from '@kbn/logs-shared-plugin/common'; import { ApplicationStart } from '@kbn/core-application-browser'; import { EuiLink } from '@elastic/eui'; -import { useTrackedPromise } from '../../../hooks/use_tracked_promise'; +import { useLogSourcesContext } from '@kbn/logs-data-access-plugin/public'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { FormElement } from './form_elements'; import { getFormRowProps } from './form_field_props'; @@ -33,7 +33,7 @@ export const KibanaAdvancedSettingConfigurationPanel: React.FC<{ >; }> = ({ isLoading, isReadOnly, advancedSettingFormElement }) => { const { - services: { application, logsDataAccess }, + services: { application }, } = useKibanaContextForPlugin(); useTrackPageview({ app: 'infra_logs', path: 'log_source_configuration_kibana_advanced_setting' }); @@ -48,31 +48,7 @@ export const KibanaAdvancedSettingConfigurationPanel: React.FC<{ [application] ); - const [logSourcesSettingValue, setLogSourcesSettingValue] = useState( - undefined - ); - - const [getLogSourcesRequest, getLogSources] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - return await logsDataAccess.services.logSourcesService.getLogSources(); - }, - onResolve: (response) => { - setLogSourcesSettingValue(response.map((logSource) => logSource.indexPattern).join(',')); - }, - }, - [] - ); - - const isLoadingLogSourcesSetting = useMemo( - () => getLogSourcesRequest.state === 'pending', - [getLogSourcesRequest.state] - ); - - useEffect(() => { - getLogSources(); - }, [getLogSources]); + const { isLoadingLogSources, combinedIndices } = useLogSourcesContext(); return ( <> @@ -125,9 +101,9 @@ export const KibanaAdvancedSettingConfigurationPanel: React.FC<{ data-test-subj="logSourcesSettingInput" fullWidth disabled={isLoading} - isLoading={isLoadingLogSourcesSetting} + isLoading={isLoadingLogSources} readOnly={true} - value={logSourcesSettingValue} + value={combinedIndices} isInvalid={false} /> diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/shared/page_log_view_error.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/shared/page_log_view_error.tsx index 2ecb9efb7003c..64a307f1bdd6c 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/shared/page_log_view_error.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/shared/page_log_view_error.tsx @@ -21,7 +21,7 @@ import { LogsPageTemplate } from './page_template'; export const LogViewErrorPage: React.FC<{ errors: Error[]; - onRetry: () => void; + onRetry?: () => void; }> = ({ errors, onRetry }) => { const settingsLinkProps = useLinkProps({ app: 'logs', pathname: '/settings' }); @@ -54,29 +54,33 @@ export const LogViewErrorPage: React.FC<{ ))} } - actions={[ - - - , - - - , - ]} + actions={ + onRetry + ? [ + + + , + + + , + ] + : undefined + } /> ); diff --git a/x-pack/plugins/observability_solution/logs_data_access/public/hooks/use_log_sources.ts b/x-pack/plugins/observability_solution/logs_data_access/public/hooks/use_log_sources.ts new file mode 100644 index 0000000000000..ff463867a7a77 --- /dev/null +++ b/x-pack/plugins/observability_solution/logs_data_access/public/hooks/use_log_sources.ts @@ -0,0 +1,51 @@ +/* + * 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 createContainer from 'constate'; +import { useTrackedPromise } from '@kbn/use-tracked-promise'; +import { useState, useEffect, useMemo } from 'react'; +import { LogSource, LogSourcesService } from '../../common/services/log_sources_service/types'; + +export const useLogSources = ({ logSourcesService }: { logSourcesService: LogSourcesService }) => { + const [logSources, setLogSources] = useState([]); + const [logSourcesError, setLogSourcesError] = useState(undefined); + const [requestState, getLogSources] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await logSourcesService.getLogSources(); + }, + onResolve: (response) => { + setLogSources(response); + setLogSourcesError(undefined); + }, + onReject: (response) => { + setLogSourcesError(response as Error); + }, + }, + [] + ); + + useEffect(() => { + getLogSources(); + }, [getLogSources]); + + const combinedIndices = useMemo(() => { + return logSources.map((logSource) => logSource.indexPattern).join(','); + }, [logSources]); + + return { + isUninitialized: requestState.state === 'uninitialized', + isLoadingLogSources: requestState.state === 'pending', + hasFailedLoadingLogSources: logSourcesError !== undefined, + logSourcesError, + logSources, + combinedIndices, + }; +}; + +export const [LogSourcesProvider, useLogSourcesContext] = createContainer(useLogSources); diff --git a/x-pack/plugins/observability_solution/logs_data_access/public/index.ts b/x-pack/plugins/observability_solution/logs_data_access/public/index.ts index bdb45d3d0a490..cc09500ef0a84 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/public/index.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/public/index.ts @@ -15,6 +15,7 @@ import { export type { LogsDataAccessPluginSetup, LogsDataAccessPluginStart }; import { LogsDataAccessPluginSetupDeps, LogsDataAccessPluginStartDeps } from './types'; +export { LogSourcesProvider, useLogSourcesContext } from './hooks/use_log_sources'; export const plugin: PluginInitializer< LogsDataAccessPluginSetup, diff --git a/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json b/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json index 45c96d862d9ff..fb2457edd993f 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json +++ b/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json @@ -21,6 +21,7 @@ "@kbn/core-ui-settings-browser", "@kbn/logging", "@kbn/core-saved-objects-api-server", - "@kbn/es-query" + "@kbn/es-query", + "@kbn/use-tracked-promise" ] } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 1396ba78da37a..e93c442a9759e 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -21352,7 +21352,6 @@ "xpack.infra.analysisSetup.endTimeAfterStartTimeErrorMessage": "L'heure de fin doit être ultérieure à l'heure de début.", "xpack.infra.analysisSetup.endTimeDefaultDescription": "Indéfiniment", "xpack.infra.analysisSetup.endTimeLabel": "Heure de fin", - "xpack.infra.analysisSetup.indicesSelectionDescription": "Par défaut, le Machine Learning analyse les messages de logs dans tous les index de logs configurés pour la source. Vous pouvez choisir de n'analyser qu'un sous-ensemble de noms d'index. Tous les noms d'index sélectionnés doivent correspondre à au moins un index avec des entrées de logs. Vous pouvez également choisir de n'inclure qu'un certain sous-ensemble d'ensembles de données. Notez que le filtre d'ensembles de données s'applique à tous les index sélectionnés.", "xpack.infra.analysisSetup.indicesSelectionIndexNotFound": "Aucun index ne correspond au modèle {index}", "xpack.infra.analysisSetup.indicesSelectionLabel": "Index", "xpack.infra.analysisSetup.indicesSelectionNetworkError": "Nous n'avons pas pu charger votre configuration d'index", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index de9f53757bd7e..1302a97c42854 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -21281,7 +21281,6 @@ "xpack.infra.analysisSetup.endTimeAfterStartTimeErrorMessage": "終了時刻は開始時刻よりも後でなければなりません。", "xpack.infra.analysisSetup.endTimeDefaultDescription": "永久", "xpack.infra.analysisSetup.endTimeLabel": "終了時刻", - "xpack.infra.analysisSetup.indicesSelectionDescription": "既定では、機械学習は、ソースに対して構成されたすべてのログインデックスにあるログメッセージを分析します。インデックス名のサブセットのみを分析することを選択できます。すべての選択したインデックス名は、ログエントリを含む1つ以上のインデックスと一致する必要があります。特定のデータセットのサブセットのみを含めることを選択できます。データセットフィルターはすべての選択したインデックスに適用されます。", "xpack.infra.analysisSetup.indicesSelectionIndexNotFound": "インデックスがパターン{index}と一致しません", "xpack.infra.analysisSetup.indicesSelectionLabel": "インデックス", "xpack.infra.analysisSetup.indicesSelectionNetworkError": "インデックス構成を読み込めませんでした", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e314413a565e8..446f5729f82d1 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -21379,7 +21379,6 @@ "xpack.infra.analysisSetup.endTimeAfterStartTimeErrorMessage": "结束时间必须晚于开始时间。", "xpack.infra.analysisSetup.endTimeDefaultDescription": "无限期", "xpack.infra.analysisSetup.endTimeLabel": "结束时间", - "xpack.infra.analysisSetup.indicesSelectionDescription": "默认情况下,Machine Learning 分析为源配置的所有日志索引中的日志消息。可以选择仅分析一部分索引名称。每个选定索引名称必须至少匹配一个具有日志条目的索引。还可以选择仅包括数据集的某个子集。注意,数据集筛选应用于所有选定索引。", "xpack.infra.analysisSetup.indicesSelectionIndexNotFound": "没有索引匹配模式 {index}", "xpack.infra.analysisSetup.indicesSelectionLabel": "索引", "xpack.infra.analysisSetup.indicesSelectionNetworkError": "我们无法加载您的索引配置",