[Logs UI] move ML job setup UI to a flyout (#68366)

Co-authored-by: Felix Stürmer <weltenwort@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Alejandro Fernández 2020-07-06 17:04:23 +02:00 committed by GitHub
parent 81bd66dcfd
commit b172b5b777
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 411 additions and 169 deletions

View file

@ -35,7 +35,7 @@ export type SetupStatus =
| {
type: 'skipped';
newlyCreated?: boolean;
}; // setup is hidden
}; // setup is not necessary
/**
* Maps a job status to the possibility that results have already been produced

View file

@ -252,7 +252,7 @@ const getSetupStatus = <JobType extends string>(everyJobStatus: Record<JobType,
Object.entries<JobStatus>(everyJobStatus).reduce<SetupStatus>((setupStatus, [, jobStatus]) => {
if (jobStatus === 'missing') {
return { type: 'required', reason: 'missing' };
} else if (setupStatus.type === 'required') {
} else if (setupStatus.type === 'required' || setupStatus.type === 'succeeded') {
return setupStatus;
} else if (setupStatus.type === 'skipped' || isJobStatusWithResults(jobStatus)) {
return {

View file

@ -5,8 +5,8 @@
*/
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import { isSetupStatusWithResults } from '../../../../common/log_analysis';
import React, { useEffect, useState, useCallback } from 'react';
import { isJobStatusWithResults } from '../../../../common/log_analysis';
import { LoadingPage } from '../../../components/loading_page';
import {
LogAnalysisSetupStatusUnknownPrompt,
@ -21,6 +21,7 @@ import { useLogSourceContext } from '../../../containers/logs/log_source';
import { LogEntryCategoriesResultsContent } from './page_results_content';
import { LogEntryCategoriesSetupContent } from './page_setup_content';
import { useLogEntryCategoriesModuleContext } from './use_log_entry_categories_module';
import { LogEntryCategoriesSetupFlyout } from './setup_flyout';
export const LogEntryCategoriesPageContent = () => {
const {
@ -37,7 +38,11 @@ export const LogEntryCategoriesPageContent = () => {
hasLogAnalysisSetupCapabilities,
} = useLogAnalysisCapabilitiesContext();
const { fetchJobStatus, setupStatus } = useLogEntryCategoriesModuleContext();
const { fetchJobStatus, setupStatus, jobStatus } = useLogEntryCategoriesModuleContext();
const [isFlyoutOpen, setIsFlyoutOpen] = useState<boolean>(false);
const openFlyout = useCallback(() => setIsFlyoutOpen(true), []);
const closeFlyout = useCallback(() => setIsFlyoutOpen(false), []);
useEffect(() => {
if (hasLogAnalysisReadCapabilities) {
@ -45,6 +50,13 @@ export const LogEntryCategoriesPageContent = () => {
}
}, [fetchJobStatus, hasLogAnalysisReadCapabilities]);
// Open flyout if there are no ML jobs
useEffect(() => {
if (setupStatus.type === 'required' && setupStatus.reason === 'missing') {
openFlyout();
}
}, [setupStatus, openFlyout]);
if (isLoading || isUninitialized) {
return <SourceLoadingPage />;
} else if (hasFailedLoadingSource) {
@ -63,11 +75,21 @@ export const LogEntryCategoriesPageContent = () => {
);
} else if (setupStatus.type === 'unknown') {
return <LogAnalysisSetupStatusUnknownPrompt retry={fetchJobStatus} />;
} else if (isSetupStatusWithResults(setupStatus)) {
return <LogEntryCategoriesResultsContent />;
} else if (isJobStatusWithResults(jobStatus['log-entry-categories-count'])) {
return (
<>
<LogEntryCategoriesResultsContent onOpenSetup={openFlyout} />
<LogEntryCategoriesSetupFlyout isOpen={isFlyoutOpen} onClose={closeFlyout} />
</>
);
} else if (!hasLogAnalysisSetupCapabilities) {
return <MissingSetupPrivilegesPrompt />;
} else {
return <LogEntryCategoriesSetupContent />;
return (
<>
<LogEntryCategoriesSetupContent onOpenSetup={openFlyout} />
<LogEntryCategoriesSetupFlyout isOpen={isFlyoutOpen} onClose={closeFlyout} />
</>
);
}
};

View file

@ -24,7 +24,13 @@ import {
const JOB_STATUS_POLLING_INTERVAL = 30000;
export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
interface LogEntryCategoriesResultsContentProps {
onOpenSetup: () => void;
}
export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryCategoriesResultsContentProps> = ({
onOpenSetup,
}) => {
useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_results' });
useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_results', delay: 15000 });
@ -123,12 +129,25 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
[setAutoRefresh]
);
const viewSetupFlyoutForReconfiguration = useCallback(() => {
viewSetupForReconfiguration();
onOpenSetup();
}, [onOpenSetup, viewSetupForReconfiguration]);
const viewSetupFlyoutForUpdate = useCallback(() => {
viewSetupForUpdate();
onOpenSetup();
}, [onOpenSetup, viewSetupForUpdate]);
const hasResults = useMemo(() => topLogEntryCategories.length > 0, [
topLogEntryCategories.length,
]);
const isFirstUse = useMemo(
() => setupStatus.type === 'skipped' && !!setupStatus.newlyCreated && !hasResults,
() =>
((setupStatus.type === 'skipped' && !!setupStatus.newlyCreated) ||
setupStatus.type === 'succeeded') &&
!hasResults,
[hasResults, setupStatus]
);
@ -184,8 +203,8 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
hasOutdatedJobDefinitions={hasOutdatedJobDefinitions}
hasStoppedJobs={hasStoppedJobs}
isFirstUse={isFirstUse}
onRecreateMlJobForReconfiguration={viewSetupForReconfiguration}
onRecreateMlJobForUpdate={viewSetupForUpdate}
onRecreateMlJobForReconfiguration={viewSetupFlyoutForReconfiguration}
onRecreateMlJobForUpdate={viewSetupFlyoutForUpdate}
qualityWarnings={categoryQualityWarnings}
/>
</EuiFlexItem>
@ -197,7 +216,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
isLoadingTopCategories={isLoadingTopLogEntryCategories}
jobId={jobIds['log-entry-categories-count']}
onChangeDatasetSelection={setCategoryQueryDatasets}
onRequestRecreateMlJob={viewSetupForReconfiguration}
onRequestRecreateMlJob={viewSetupFlyoutForReconfiguration}
selectedDatasets={categoryQueryDatasets}
sourceId={sourceId}
timeRange={categoryQueryTimeRange.timeRange}

View file

@ -4,98 +4,51 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiSpacer, EuiSteps, EuiText } from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { useMemo } from 'react';
import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui';
import { BetaBadge } from '../../../components/beta_badge';
import {
createInitialConfigurationStep,
createProcessStep,
LogAnalysisSetupPage,
LogAnalysisSetupPageContent,
LogAnalysisSetupPageHeader,
} from '../../../components/logging/log_analysis_setup';
import { useTrackPageview } from '../../../../../observability/public';
import { useLogEntryCategoriesSetup } from './use_log_entry_categories_setup';
export const LogEntryCategoriesSetupContent: React.FunctionComponent = () => {
interface LogEntryCategoriesSetupContentProps {
onOpenSetup: () => void;
}
export const LogEntryCategoriesSetupContent: React.FunctionComponent<LogEntryCategoriesSetupContentProps> = ({
onOpenSetup,
}) => {
useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_setup' });
useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_setup', delay: 15000 });
const {
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setValidatedIndices,
setUp,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
} = useLogEntryCategoriesSetup();
const steps = useMemo(
() => [
createInitialConfigurationStep({
setStartTime,
setEndTime,
startTime,
endTime,
isValidating,
validatedIndices,
setupStatus,
setValidatedIndices,
validationErrors,
}),
createProcessStep({
cleanUpAndSetUp,
errorMessages: lastSetupErrorMessages,
isConfigurationValid: validationErrors.length <= 0 && !isValidating,
setUp,
setupStatus,
viewResults,
}),
],
[
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setUp,
setValidatedIndices,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
]
);
return (
<LogAnalysisSetupPage data-test-subj="logEntryCategoriesSetupPage">
<LogAnalysisSetupPageHeader>
<FormattedMessage
id="xpack.infra.logs.logEntryCategories.setupTitle"
defaultMessage="Enable Machine Learning analysis"
/>{' '}
<BetaBadge />
defaultMessage="Set up log category analysis"
/>
</LogAnalysisSetupPageHeader>
<LogAnalysisSetupPageContent>
<EuiText size="s">
<FormattedMessage
id="xpack.infra.logs.logEntryCategories.setupDescription"
defaultMessage="Use Machine Learning to automatically categorize log messages."
/>
<p>
<FormattedMessage
id="xpack.infra.logs.logEntryCategories.setupDescription"
defaultMessage="To enable log categories, set up a machine learning job."
/>
</p>
</EuiText>
<EuiSpacer />
<EuiSteps steps={steps} />
<EuiButton fill onClick={onOpenSetup}>
<FormattedMessage
id="xpack.infra.logs.logEntryCategories.showAnalysisSetupButtonLabel"
defaultMessage="ML setup"
/>
</EuiButton>
</LogAnalysisSetupPageContent>
</LogAnalysisSetupPage>
);

View file

@ -0,0 +1,129 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useMemo, useCallback } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiFlyout,
EuiFlyoutHeader,
EuiFlyoutBody,
EuiTitle,
EuiText,
EuiSpacer,
EuiSteps,
} from '@elastic/eui';
import {
createInitialConfigurationStep,
createProcessStep,
} from '../../../components/logging/log_analysis_setup';
import { useLogEntryCategoriesSetup } from './use_log_entry_categories_setup';
interface LogEntryCategoriesSetupFlyoutProps {
isOpen: boolean;
onClose: () => void;
}
export const LogEntryCategoriesSetupFlyout: React.FC<LogEntryCategoriesSetupFlyoutProps> = ({
isOpen,
onClose,
}) => {
const {
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setValidatedIndices,
setUp,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
} = useLogEntryCategoriesSetup();
const viewResultsAndClose = useCallback(() => {
viewResults();
onClose();
}, [viewResults, onClose]);
const steps = useMemo(
() => [
createInitialConfigurationStep({
setStartTime,
setEndTime,
startTime,
endTime,
isValidating,
validatedIndices,
setupStatus,
setValidatedIndices,
validationErrors,
}),
createProcessStep({
cleanUpAndSetUp,
errorMessages: lastSetupErrorMessages,
isConfigurationValid: validationErrors.length <= 0 && !isValidating,
setUp,
setupStatus,
viewResults: viewResultsAndClose,
}),
],
[
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setUp,
setValidatedIndices,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResultsAndClose,
]
);
if (!isOpen) {
return null;
}
return (
<EuiFlyout onClose={onClose}>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.infra.logs.setupFlyout.setupFlyoutTitle"
defaultMessage="Anomaly detection with Machine Learning"
/>
</h3>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.infra.logs.setupFlyout.logCategoriesTitle"
defaultMessage="Log categories"
/>
</h3>
</EuiTitle>
<EuiText size="s">
<FormattedMessage
id="xpack.infra.logs.setupFlyout.logCategoriesDescription"
defaultMessage="Use Machine Learning to automatically categorize log messages."
/>
</EuiText>
<EuiSpacer />
<EuiSteps steps={steps} />
</EuiFlyoutBody>
</EuiFlyout>
);
};

View file

@ -5,8 +5,8 @@
*/
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import { isSetupStatusWithResults } from '../../../../common/log_analysis';
import React, { useEffect, useState, useCallback } from 'react';
import { isJobStatusWithResults } from '../../../../common/log_analysis';
import { LoadingPage } from '../../../components/loading_page';
import {
LogAnalysisSetupStatusUnknownPrompt,
@ -21,6 +21,7 @@ import { useLogSourceContext } from '../../../containers/logs/log_source';
import { LogEntryRateResultsContent } from './page_results_content';
import { LogEntryRateSetupContent } from './page_setup_content';
import { useLogEntryRateModuleContext } from './use_log_entry_rate_module';
import { LogEntryRateSetupFlyout } from './setup_flyout';
export const LogEntryRatePageContent = () => {
const {
@ -37,7 +38,11 @@ export const LogEntryRatePageContent = () => {
hasLogAnalysisSetupCapabilities,
} = useLogAnalysisCapabilitiesContext();
const { fetchJobStatus, setupStatus } = useLogEntryRateModuleContext();
const { fetchJobStatus, setupStatus, jobStatus } = useLogEntryRateModuleContext();
const [isFlyoutOpen, setIsFlyoutOpen] = useState<boolean>(false);
const openFlyout = useCallback(() => setIsFlyoutOpen(true), []);
const closeFlyout = useCallback(() => setIsFlyoutOpen(false), []);
useEffect(() => {
if (hasLogAnalysisReadCapabilities) {
@ -45,6 +50,13 @@ export const LogEntryRatePageContent = () => {
}
}, [fetchJobStatus, hasLogAnalysisReadCapabilities]);
// Open flyout if there are no ML jobs
useEffect(() => {
if (setupStatus.type === 'required' && setupStatus.reason === 'missing') {
openFlyout();
}
}, [setupStatus, openFlyout]);
if (isLoading || isUninitialized) {
return <SourceLoadingPage />;
} else if (hasFailedLoadingSource) {
@ -63,11 +75,21 @@ export const LogEntryRatePageContent = () => {
);
} else if (setupStatus.type === 'unknown') {
return <LogAnalysisSetupStatusUnknownPrompt retry={fetchJobStatus} />;
} else if (isSetupStatusWithResults(setupStatus)) {
return <LogEntryRateResultsContent />;
} else if (isJobStatusWithResults(jobStatus['log-entry-rate'])) {
return (
<>
<LogEntryRateResultsContent onOpenSetup={openFlyout} />
<LogEntryRateSetupFlyout isOpen={isFlyoutOpen} onClose={closeFlyout} />
</>
);
} else if (!hasLogAnalysisSetupCapabilities) {
return <MissingSetupPrivilegesPrompt />;
} else {
return <LogEntryRateSetupContent />;
return (
<>
<LogEntryRateSetupContent onOpenSetup={openFlyout} />
<LogEntryRateSetupFlyout isOpen={isFlyoutOpen} onClose={closeFlyout} />
</>
);
}
};

View file

@ -36,7 +36,13 @@ import {
const JOB_STATUS_POLLING_INTERVAL = 30000;
export const LogEntryRateResultsContent: React.FunctionComponent = () => {
interface LogEntryRateResultsContentProps {
onOpenSetup: () => void;
}
export const LogEntryRateResultsContent: React.FunctionComponent<LogEntryRateResultsContentProps> = ({
onOpenSetup,
}) => {
useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_results' });
useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_results', delay: 15000 });
@ -127,13 +133,26 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
[setAutoRefresh]
);
const viewSetupFlyoutForReconfiguration = useCallback(() => {
viewSetupForReconfiguration();
onOpenSetup();
}, [viewSetupForReconfiguration, onOpenSetup]);
const viewSetupFlyoutForUpdate = useCallback(() => {
viewSetupForUpdate();
onOpenSetup();
}, [viewSetupForUpdate, onOpenSetup]);
/* eslint-disable-next-line react-hooks/exhaustive-deps */
const hasResults = useMemo(() => (logEntryRate?.histogramBuckets?.length ?? 0) > 0, [
logEntryRate,
]);
const isFirstUse = useMemo(
() => setupStatus.type === 'skipped' && !!setupStatus.newlyCreated && !hasResults,
() =>
((setupStatus.type === 'skipped' && !!setupStatus.newlyCreated) ||
setupStatus.type === 'succeeded') &&
!hasResults,
[hasResults, setupStatus]
);
@ -209,8 +228,8 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
hasOutdatedJobDefinitions={hasOutdatedJobDefinitions}
hasStoppedJobs={hasStoppedJobs}
isFirstUse={isFirstUse}
onRecreateMlJobForReconfiguration={viewSetupForReconfiguration}
onRecreateMlJobForUpdate={viewSetupForUpdate}
onRecreateMlJobForReconfiguration={viewSetupFlyoutForReconfiguration}
onRecreateMlJobForUpdate={viewSetupFlyoutForUpdate}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
@ -227,7 +246,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
<EuiPanel paddingSize="m">
<AnomaliesResults
isLoading={isLoading}
viewSetupForReconfiguration={viewSetupForReconfiguration}
viewSetupForReconfiguration={viewSetupFlyoutForReconfiguration}
results={logEntryRate}
setTimeRange={handleChartTimeRangeChange}
timeRange={queryTimeRange.value}

View file

@ -4,98 +4,51 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EuiSpacer, EuiSteps, EuiText } from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { useMemo } from 'react';
import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui';
import { BetaBadge } from '../../../components/beta_badge';
import {
createInitialConfigurationStep,
createProcessStep,
LogAnalysisSetupPage,
LogAnalysisSetupPageContent,
LogAnalysisSetupPageHeader,
} from '../../../components/logging/log_analysis_setup';
import { useTrackPageview } from '../../../../../observability/public';
import { useLogEntryRateSetup } from './use_log_entry_rate_setup';
export const LogEntryRateSetupContent: React.FunctionComponent = () => {
interface LogEntryRateSetupContentProps {
onOpenSetup: () => void;
}
export const LogEntryRateSetupContent: React.FunctionComponent<LogEntryRateSetupContentProps> = ({
onOpenSetup,
}) => {
useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup' });
useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup', delay: 15000 });
const {
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setValidatedIndices,
setUp,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
} = useLogEntryRateSetup();
const steps = useMemo(
() => [
createInitialConfigurationStep({
setStartTime,
setEndTime,
startTime,
endTime,
isValidating,
validatedIndices,
setupStatus,
setValidatedIndices,
validationErrors,
}),
createProcessStep({
cleanUpAndSetUp,
errorMessages: lastSetupErrorMessages,
isConfigurationValid: validationErrors.length <= 0 && !isValidating,
setUp,
setupStatus,
viewResults,
}),
],
[
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setUp,
setValidatedIndices,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
]
);
return (
<LogAnalysisSetupPage data-test-subj="logEntryRateSetupPage">
<LogAnalysisSetupPageHeader>
<FormattedMessage
id="xpack.infra.analysisSetup.analysisSetupTitle"
defaultMessage="Enable Machine Learning analysis"
/>{' '}
<BetaBadge />
id="xpack.infra.logs.logEntryRate.setupTitle"
defaultMessage="Set up log anomaly analysis"
/>
</LogAnalysisSetupPageHeader>
<LogAnalysisSetupPageContent>
<EuiText size="s">
<FormattedMessage
id="xpack.infra.analysisSetup.analysisSetupDescription"
defaultMessage="Use Machine Learning to automatically detect anomalous log rate counts."
/>
<p>
<FormattedMessage
id="xpack.infra.logs.logEntryRate.setupDescription"
defaultMessage="To enable log anomalies, set up a machine learning job"
/>
</p>
</EuiText>
<EuiSpacer />
<EuiSteps steps={steps} />
<EuiButton fill onClick={onOpenSetup}>
<FormattedMessage
id="xpack.infra.logs.logEntryRate.showAnalysisSetupButtonLabel"
defaultMessage="ML Setup"
/>
</EuiButton>
</LogAnalysisSetupPageContent>
</LogAnalysisSetupPage>
);

View file

@ -0,0 +1,129 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useMemo, useCallback } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiFlyout,
EuiFlyoutHeader,
EuiFlyoutBody,
EuiTitle,
EuiText,
EuiSpacer,
EuiSteps,
} from '@elastic/eui';
import {
createInitialConfigurationStep,
createProcessStep,
} from '../../../components/logging/log_analysis_setup';
import { useLogEntryRateSetup } from './use_log_entry_rate_setup';
interface LogEntryRateSetupFlyoutProps {
isOpen: boolean;
onClose: () => void;
}
export const LogEntryRateSetupFlyout: React.FC<LogEntryRateSetupFlyoutProps> = ({
isOpen,
onClose,
}) => {
const {
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setValidatedIndices,
setUp,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResults,
} = useLogEntryRateSetup();
const viewResultsAndClose = useCallback(() => {
viewResults();
onClose();
}, [viewResults, onClose]);
const steps = useMemo(
() => [
createInitialConfigurationStep({
setStartTime,
setEndTime,
startTime,
endTime,
isValidating,
validatedIndices,
setupStatus,
setValidatedIndices,
validationErrors,
}),
createProcessStep({
cleanUpAndSetUp,
errorMessages: lastSetupErrorMessages,
isConfigurationValid: validationErrors.length <= 0 && !isValidating,
setUp,
setupStatus,
viewResults: viewResultsAndClose,
}),
],
[
cleanUpAndSetUp,
endTime,
isValidating,
lastSetupErrorMessages,
setEndTime,
setStartTime,
setUp,
setValidatedIndices,
setupStatus,
startTime,
validatedIndices,
validationErrors,
viewResultsAndClose,
]
);
if (!isOpen) {
return null;
}
return (
<EuiFlyout onClose={onClose}>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.infra.logs.setupFlyout.setupFlyoutTitle"
defaultMessage="Anomaly detection with Machine Learning"
/>
</h3>
</EuiTitle>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiTitle size="s">
<h3>
<FormattedMessage
id="xpack.infra.logs.setupFlyout.logRateTitle"
defaultMessage="Log rate"
/>
</h3>
</EuiTitle>
<EuiText size="s">
<FormattedMessage
id="xpack.infra.logs.setupFlyout.logRateDescription"
defaultMessage="Use Machine Learning to automatically detect anomalous log rate counts."
/>
</EuiText>
<EuiSpacer />
<EuiSteps steps={steps} />
</EuiFlyoutBody>
</EuiFlyout>
);
};

View file

@ -7316,8 +7316,6 @@
"xpack.infra.alerting.logs.manageAlerts": "アラートを管理",
"xpack.infra.alerting.manageAlerts": "アラートを管理",
"xpack.infra.analysisSetup.actionStepTitle": "MLジョブを作成",
"xpack.infra.analysisSetup.analysisSetupDescription": "機械学習を使用して自動的に異常ログレートカウントを検出します。",
"xpack.infra.analysisSetup.analysisSetupTitle": "機械学習分析を有効にする",
"xpack.infra.analysisSetup.configurationStepTitle": "構成",
"xpack.infra.analysisSetup.createMlJobButton": "ML ジョブを作成",
"xpack.infra.analysisSetup.deleteAnalysisResultsWarning": "これにより以前検出された異常が削除されます。",

View file

@ -7320,8 +7320,6 @@
"xpack.infra.alerting.logs.manageAlerts": "管理告警",
"xpack.infra.alerting.manageAlerts": "管理告警",
"xpack.infra.analysisSetup.actionStepTitle": "创建 ML 作业",
"xpack.infra.analysisSetup.analysisSetupDescription": "使用 Machine Learning 自动检测异常日志速率计数。",
"xpack.infra.analysisSetup.analysisSetupTitle": "启用 Machine Learning 分析",
"xpack.infra.analysisSetup.configurationStepTitle": "配置",
"xpack.infra.analysisSetup.createMlJobButton": "创建 ML 作业",
"xpack.infra.analysisSetup.deleteAnalysisResultsWarning": "这将移除以前检测到的异常。",