[Logs] Use central log sources setting in ML jobs (#190071)

## Summary

This uses the new central log sources setting when creating or
recreating log rate and category jobs.

The indices are injected into the job configuration so changes to the
advanced setting won't suddenly break the jobs (in the same way that it
would potentially break alerting rules).

## UI / UX

Small amendment to the text here:

![Screenshot 2024-08-08 at 15 53
28](https://github.com/user-attachments/assets/19f573f3-619e-4c3e-8778-87972dff922e)

Callout functionality should still work as expected if the advanced
setting is changed after the job has been created:

![Screenshot 2024-08-08 at 15 55
25](https://github.com/user-attachments/assets/a4e54ca3-f31a-4496-9c27-fd2aa8424853)

## Side quests

- Logs > Settings page has been updated to use the new `useLogSources`
provider in the advanced setting panel.

---------

Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani01@gmail.com>
This commit is contained in:
Kerry Gallagher 2024-08-09 21:34:06 +01:00 committed by GitHub
parent b1a2922301
commit 1f11376a3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 187 additions and 122 deletions

View file

@ -28,7 +28,7 @@ export const JobConfigurationOutdatedCallout: React.FC<{
>
<FormattedMessage
id="xpack.infra.logs.analysis.jobConfigurationOutdatedCalloutMessage"
defaultMessage="The {moduleName} ML job was created using a different source configuration. Recreate the job to apply the current configuration. This removes previously detected anomalies."
defaultMessage="The {moduleName} ML job was created using a different configuration. Recreate the job to apply the current configuration. This removes previously detected anomalies."
values={{
moduleName,
}}

View file

@ -5,15 +5,23 @@
* 2.0.
*/
import { EuiTitle, EuiText, EuiFormRow, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiTitle, EuiText, EuiFormRow, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { ApplicationStart } from '@kbn/core-application-browser';
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
import { QualityWarning } from '../../../../../common/log_analysis';
import { LoadingOverlayWrapper } from '../../../loading_overlay_wrapper';
import { IndexSetupRow } from './index_setup_row';
import { AvailableIndex, ValidationIndicesError } from './validation';
function getKibanaAdvancedSettingsHref(application: ApplicationStart) {
return application.getUrlForApp('management', {
path: `/kibana/settings?query=${encodeURIComponent('Log sources')}`,
});
}
export const AnalysisSetupIndicesForm: React.FunctionComponent<{
disabled?: boolean;
indices: AvailableIndex[];
@ -29,6 +37,15 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{
previousQualityWarnings = [],
validationErrors = [],
}) => {
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<{
<EuiText size="s" color="subdued">
<FormattedMessage
id="xpack.infra.analysisSetup.indicesSelectionDescription"
defaultMessage="By default, Machine Learning analyzes log messages in all log indices configured for the source. You can choose to only analyze a subset of the index names. Every selected index name must match at least one index with log entries. You can also choose to only include a certain subset of datasets. Note that the dataset filter applies to all selected indices."
defaultMessage="By default, Machine Learning analyzes log messages in all log indices configured for the {advancedSettingsLink}. You can choose to only analyze a subset of the index names. Every selected index name must match at least one index with log entries. You can also choose to only include a certain subset of datasets. Note that the dataset filter applies to all selected indices."
values={{
advancedSettingsLink: (
<EuiLink
data-test-subj="xpack.infra.analysisSetup.logSourcesSettingLink"
href={advancedSettingsHref}
>
<FormattedMessage
id="xpack.infra.analysisSetup.logSourcesSettingLinkText"
defaultMessage="log sources setting"
/>
</EuiLink>
),
}}
/>
</EuiText>
</EuiFlexItem>

View file

@ -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({

View file

@ -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({

View file

@ -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<PropsWithChildren<unknown>> = ({ 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<PropsWithChildren<unknown>> = (
// React concurrent mode and Suspense in order to handle that more gracefully.
if (space == null) {
return null;
} else if (!isPersistedLogView) {
return <InlineLogViewSplashPage revertToDefaultLogView={revertToDefaultLogView} />;
} else if (hasFailedLoading || hasFailedLoadingLogAnalysisIdFormats) {
return <ConnectedLogViewErrorPage />;
} else if (isLoading || isUninitialized || isLoadingLogAnalysisIdFormats || !idFormats) {
} else if (hasFailedLoadingLogSources || hasFailedLoadingLogAnalysisIdFormats) {
return <LogSourceErrorPage errors={logSourcesError !== undefined ? [logSourcesError] : []} />;
} else if (
isLoadingLogSources ||
isUninitialized ||
isLoadingLogAnalysisIdFormats ||
!idFormats
) {
return <SourceLoadingPage />;
} 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 (
<LogEntryCategoriesModuleProvider
indexPattern={resolvedLogView.indices}
logViewId={logViewReference.logViewId}
indexPattern={combinedIndices}
spaceId={space.id}
sourceId={DEFAULT_MODULE_SOURCE_CONFIGURATION_ID}
idFormat={idFormats[logEntryCategoriesJobType]}
timestampField={resolvedLogView.timestampField}
runtimeMappings={resolvedLogView.runtimeMappings}
timestampField={TIMESTAMP_FIELD}
runtimeMappings={{}}
>
<LogAnalysisSetupFlyoutStateProvider>{children}</LogAnalysisSetupFlyoutStateProvider>
</LogEntryCategoriesModuleProvider>

View file

@ -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<PropsWithChildren<unknown>> = ({ 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<PropsWithChildren<unknown>> = ({ chil
// React concurrent mode and Suspense in order to handle that more gracefully.
if (space == null) {
return null;
} else if (!isPersistedLogView) {
return <InlineLogViewSplashPage revertToDefaultLogView={revertToDefaultLogView} />;
} else if (isLoading || isUninitialized || isLoadingLogAnalysisIdFormats || !idFormats) {
} else if (
isLoadingLogSources ||
isUninitialized ||
isLoadingLogAnalysisIdFormats ||
!idFormats
) {
return <SourceLoadingPage />;
} else if (hasFailedLoading || hasFailedLoadingLogAnalysisIdFormats) {
return <ConnectedLogViewErrorPage />;
} 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 <LogSourceErrorPage errors={logSourcesError !== undefined ? [logSourcesError] : []} />;
} else if (logSources.length > 0) {
return (
<LogEntryFlyoutProvider>
<LogEntryRateModuleProvider
indexPattern={resolvedLogView.indices}
logViewId={logViewReference.logViewId}
indexPattern={combinedIndices}
spaceId={space.id}
sourceId={DEFAULT_MODULE_SOURCE_CONFIGURATION_ID}
idFormat={idFormats[logEntryRateJobType]}
timestampField={resolvedLogView.timestampField}
runtimeMappings={resolvedLogView.runtimeMappings}
timestampField={TIMESTAMP_FIELD}
runtimeMappings={{}}
>
<LogEntryCategoriesModuleProvider
indexPattern={resolvedLogView.indices}
logViewId={logViewReference.logViewId}
indexPattern={combinedIndices}
spaceId={space.id}
sourceId={DEFAULT_MODULE_SOURCE_CONFIGURATION_ID}
idFormat={idFormats[logEntryCategoriesJobType]}
timestampField={resolvedLogView.timestampField}
runtimeMappings={resolvedLogView.runtimeMappings}
timestampField={TIMESTAMP_FIELD}
runtimeMappings={{}}
>
<LogAnalysisSetupFlyoutStateProvider>{children}</LogAnalysisSetupFlyoutStateProvider>
</LogEntryCategoriesModuleProvider>

View file

@ -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<PropsWithChildren<unknown>> = ({ children })
services: {
notifications: { toasts: toastsService },
logsShared,
logsDataAccess,
},
} = useKibanaContextForPlugin();
@ -43,7 +45,9 @@ export const LogsPageProviders: FC<PropsWithChildren<unknown>> = ({ children })
updateContextInUrl={updateContextInUrl}
listenForUrlChanges={listenForUrlChanges}
>
<LogAnalysisCapabilitiesProvider>{children}</LogAnalysisCapabilitiesProvider>
<LogSourcesProvider logSourcesService={logsDataAccess.services.logSourcesService}>
<LogAnalysisCapabilitiesProvider>{children}</LogAnalysisCapabilitiesProvider>
</LogSourcesProvider>
</LogViewProvider>
);
};

View file

@ -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<string | undefined>(
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}
/>
</EuiFormRow>

View file

@ -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={[
<EuiButton
data-test-subj="infraLogViewErrorPageTryAgainButton"
onClick={onRetry}
iconType="refresh"
fill
>
<FormattedMessage
id="xpack.infra.logSourceErrorPage.tryAgainButtonLabel"
defaultMessage="Try again"
/>
</EuiButton>,
<EuiButtonEmpty
data-test-subj="infraLogViewErrorPageChangeConfigurationButton"
iconType="gear"
{...settingsLinkProps}
>
<FormattedMessage
id="xpack.infra.logSourceErrorPage.navigateToSettingsButtonLabel"
defaultMessage="Change configuration"
/>
</EuiButtonEmpty>,
]}
actions={
onRetry
? [
<EuiButton
data-test-subj="infraLogViewErrorPageTryAgainButton"
onClick={onRetry}
iconType="refresh"
fill
>
<FormattedMessage
id="xpack.infra.logSourceErrorPage.tryAgainButtonLabel"
defaultMessage="Try again"
/>
</EuiButton>,
<EuiButtonEmpty
data-test-subj="infraLogViewErrorPageChangeConfigurationButton"
iconType="gear"
{...settingsLinkProps}
>
<FormattedMessage
id="xpack.infra.logSourceErrorPage.navigateToSettingsButtonLabel"
defaultMessage="Change configuration"
/>
</EuiButtonEmpty>,
]
: undefined
}
/>
</LogsPageTemplate>
);

View file

@ -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<LogSource[]>([]);
const [logSourcesError, setLogSourcesError] = useState<Error | undefined>(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);

View file

@ -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,

View file

@ -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"
]
}

View file

@ -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",

View file

@ -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": "インデックス構成を読み込めませんでした",

View file

@ -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": "我们无法加载您的索引配置",