From de0499e45ddb84215a9d903d9dc9bc845559aa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 8 Aug 2019 14:37:44 +0200 Subject: [PATCH 01/25] Add empty analysis tab --- .../infra/public/pages/logs/analysis/index.ts | 7 ++++++ .../infra/public/pages/logs/analysis/page.tsx | 24 +++++++++++++++++++ .../pages/logs/analysis/page_providers.tsx | 17 +++++++++++++ .../logs/analysis/page_results_content.tsx | 16 +++++++++++++ .../logs/analysis/page_setup_content.tsx | 16 +++++++++++++ .../plugins/infra/public/pages/logs/index.tsx | 9 +++++++ 6 files changed, 89 insertions(+) create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/index.ts create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_providers.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/index.ts b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/index.ts new file mode 100644 index 0000000000000..224217e860e94 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export * from './page'; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx new file mode 100644 index 0000000000000..4e54cef7e5738 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -0,0 +1,24 @@ +/* + * 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 from 'react'; + +import { ColumnarPage } from '../../../components/page'; +import { AnalysisPageProviders } from './page_providers'; +import { AnalysisResultsContent } from './page_results_content'; +import { AnalysisSetupContent } from './page_setup_content'; + +export const AnalysisPage = () => { + const isSetupRequired = true; + + return ( + + + {isSetupRequired ? : } + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_providers.tsx new file mode 100644 index 0000000000000..95d6278164326 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_providers.tsx @@ -0,0 +1,17 @@ +/* + * 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 from 'react'; + +import { Source, useSource } from '../../../containers/source'; +import { useSourceId } from '../../../containers/source_id'; + +export const AnalysisPageProviders: React.FunctionComponent = ({ children }) => { + const [sourceId] = useSourceId(); + const source = useSource({ sourceId }); + + return {children}; +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx new file mode 100644 index 0000000000000..a570f9e37309f --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx @@ -0,0 +1,16 @@ +/* + * 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 from 'react'; + +import { useTrackPageview } from '../../../hooks/use_track_metric'; + +export const AnalysisResultsContent = () => { + useTrackPageview({ app: 'infra_logs', path: 'analysis_results' }); + useTrackPageview({ app: 'infra_logs', path: 'analysis_results', delay: 15000 }); + + return
Results
; +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx new file mode 100644 index 0000000000000..a4e1402e9ce60 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -0,0 +1,16 @@ +/* + * 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 from 'react'; + +import { useTrackPageview } from '../../../hooks/use_track_metric'; + +export const AnalysisSetupContent = () => { + useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); + useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); + + return
Setup
; +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx index dbcd046549c96..06e67a9d3e1f5 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx @@ -20,6 +20,7 @@ import { Source } from '../../containers/source'; import { StreamPage } from './stream'; import { SettingsPage } from '../shared/settings'; import { AppNavigation } from '../../components/navigation/app_navigation'; +import { AnalysisPage } from './analysis'; interface LogsPageProps extends RouteComponentProps { intl: InjectedIntl; @@ -66,6 +67,13 @@ export const LogsPage = injectUICapabilities( }), path: `${match.path}/stream`, }, + { + title: intl.formatMessage({ + id: 'xpack.infra.logs.index.analysisTabTitle', + defaultMessage: 'Analysis', + }), + path: `${match.path}/analysis`, + }, { title: intl.formatMessage({ id: 'xpack.infra.logs.index.settingsTabTitle', @@ -79,6 +87,7 @@ export const LogsPage = injectUICapabilities( + From 0ba9cca7471b736864adf4e0c8c3187bea355229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 8 Aug 2019 16:31:10 +0200 Subject: [PATCH 02/25] Add ml capabilities check --- .../common/log_analysis/job_parameters.ts | 5 +- .../containers/logs/log_analysis/index.ts | 2 + .../log_analysis_capabilities.tsx | 85 +++++++++++ .../logs/log_analysis/log_analysis_jobs.tsx | 70 +++++++++ .../log_analysis/log_analysis_results.tsx | 2 +- .../logs/log_analysis/ml_api_types.ts | 28 ++++ .../plugins/infra/public/pages/logs/index.tsx | 138 ++++++++++-------- .../public/pages/logs/stream/page_content.tsx | 24 +-- .../pages/logs/stream/page_providers.tsx | 24 ++- 9 files changed, 283 insertions(+), 95 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_capabilities.tsx create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts diff --git a/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts b/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts index ff4490d2c700a..82cfb0f83ed69 100644 --- a/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts +++ b/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts @@ -6,5 +6,8 @@ import { JobType } from './log_analysis'; +export const getJobIdPrefix = (spaceId: string, sourceId: string) => + `kibana-logs-ui-${spaceId}-${sourceId}-`; + export const getJobId = (spaceId: string, sourceId: string, jobType: JobType) => - `kibana-logs-ui-${spaceId}-${sourceId}-${jobType}`; + `${getJobIdPrefix(spaceId, sourceId)}${jobType}`; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/index.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/index.ts index 784c02f89615f..294a78cc85206 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/index.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/index.ts @@ -4,4 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ +export * from './log_analysis_capabilities'; +export * from './log_analysis_jobs'; export * from './log_analysis_results'; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_capabilities.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_capabilities.tsx new file mode 100644 index 0000000000000..f364e37462f39 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_capabilities.tsx @@ -0,0 +1,85 @@ +/* + * 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 { useMemo, useState, useEffect } from 'react'; +import { kfetch } from 'ui/kfetch'; + +import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { + getMlCapabilitiesResponsePayloadRT, + GetMlCapabilitiesResponsePayload, +} from './ml_api_types'; +import { throwErrors, createPlainError } from '../../../../common/runtime_types'; + +export const useLogAnalysisCapabilities = () => { + const [mlCapabilities, setMlCapabilities] = useState( + initialMlCapabilities + ); + + const [fetchMlCapabilitiesRequest, fetchMlCapabilities] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + const rawResponse = await kfetch({ + method: 'GET', + pathname: '/api/ml/ml_capabilities', + }); + + return getMlCapabilitiesResponsePayloadRT + .decode(rawResponse) + .getOrElseL(throwErrors(createPlainError)); + }, + onResolve: response => { + setMlCapabilities(response); + }, + }, + [] + ); + + useEffect(() => { + fetchMlCapabilities(); + }, []); + + const isLoading = useMemo(() => fetchMlCapabilitiesRequest.state === 'pending', [ + fetchMlCapabilitiesRequest.state, + ]); + + return { + hasLogAnalysisCapabilites: mlCapabilities.capabilities.canCreateJob, + isLoading, + }; +}; + +const initialMlCapabilities = { + capabilities: { + canGetJobs: false, + canCreateJob: false, + canDeleteJob: false, + canOpenJob: false, + canCloseJob: false, + canForecastJob: false, + canGetDatafeeds: false, + canStartStopDatafeed: false, + canUpdateJob: false, + canUpdateDatafeed: false, + canPreviewDatafeed: false, + canGetCalendars: false, + canCreateCalendar: false, + canDeleteCalendar: false, + canGetFilters: false, + canCreateFilter: false, + canDeleteFilter: false, + canFindFileStructure: false, + canGetDataFrameJobs: false, + canDeleteDataFrameJob: false, + canPreviewDataFrameJob: false, + canCreateDataFrameJob: false, + canStartStopDataFrameJob: false, + }, + isPlatinumOrTrialLicense: false, + mlFeatureEnabledInSpace: false, + upgradeInProgress: false, +}; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx new file mode 100644 index 0000000000000..dcecfaea3467b --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -0,0 +1,70 @@ +/* + * 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 createContainer from 'constate-latest'; +import { useMemo, useState } from 'react'; +import { kfetch } from 'ui/kfetch'; + +import { getJobIdPrefix } from '../../../../common/log_analysis'; +import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { setupMlModuleRequestPayloadRT } from './ml_api_types'; + +type JobStatus = 'unknown' | 'querying' | 'missing' | 'creating' | 'running' | 'inconsistent'; + +export const useLogAnalysisJobs = ({ + indexPattern, + sourceId, + spaceId, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; +}) => { + const [jobStatus, setJobStatus] = useState<{ + logEntryRate: JobStatus; + }>({ + logEntryRate: 'unknown', + }); + + // const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( + // { + // cancelPreviousOn: 'resolution', + // createPromise: async () => { + // kfetch({ + // method: 'POST', + // pathname: '/api/ml/modules/setup', + // body: JSON.stringify( + // setupMlModuleRequestPayloadRT.encode({ + // indexPatternName: indexPattern, + // prefix: getJobIdPrefix(spaceId, sourceId), + // startDatafeed: true, + // }) + // ), + // }); + // }, + // }, + // [indexPattern, spaceId, sourceId] + // ); + + const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + kfetch({ + method: 'POST', + pathname: '/api/ml/jobs/jobs_summary', + }); + }, + }, + [indexPattern, spaceId, sourceId] + ); + + return { + jobStatus, + }; +}; + +export const LogAnalysisJobs = createContainer(useLogAnalysisJobs); diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx index 1903441037822..861c07c3ad5fa 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import createContainer from 'constate-latest/dist/ts/src'; +import createContainer from 'constate-latest'; import { useMemo } from 'react'; import { useLogEntryRate } from './log_entry_rate'; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts new file mode 100644 index 0000000000000..ee70edc31d49b --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts @@ -0,0 +1,28 @@ +/* + * 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 * as rt from 'io-ts'; + +export const getMlCapabilitiesResponsePayloadRT = rt.type({ + capabilities: rt.type({ + canGetJobs: rt.boolean, + canCreateJob: rt.boolean, + canDeleteJob: rt.boolean, + canOpenJob: rt.boolean, + canCloseJob: rt.boolean, + canForecastJob: rt.boolean, + canGetDatafeeds: rt.boolean, + canStartStopDatafeed: rt.boolean, + canUpdateJob: rt.boolean, + canUpdateDatafeed: rt.boolean, + canPreviewDatafeed: rt.boolean, + }), + isPlatinumOrTrialLicense: rt.boolean, + mlFeatureEnabledInSpace: rt.boolean, + upgradeInProgress: rt.boolean, +}); + +export type GetMlCapabilitiesResponsePayload = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx index 06e67a9d3e1f5..7fb060b45c63a 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx @@ -16,11 +16,15 @@ import { HelpCenterContent } from '../../components/help_center_content'; import { Header } from '../../components/header'; import { RoutedTabs } from '../../components/navigation/routed_tabs'; import { ColumnarPage } from '../../components/page'; -import { Source } from '../../containers/source'; +import { SourceLoadingPage } from '../../components/source_loading_page'; +import { SourceErrorPage } from '../../components/source_error_page'; +import { Source, useSource } from '../../containers/source'; import { StreamPage } from './stream'; import { SettingsPage } from '../shared/settings'; import { AppNavigation } from '../../components/navigation/app_navigation'; import { AnalysisPage } from './analysis'; +import { useLogAnalysisCapabilities } from '../../containers/logs/log_analysis'; +import { useSourceId } from '../../containers/source_id'; interface LogsPageProps extends RouteComponentProps { intl: InjectedIntl; @@ -28,69 +32,89 @@ interface LogsPageProps extends RouteComponentProps { } export const LogsPage = injectUICapabilities( - injectI18n(({ match, intl, uiCapabilities }: LogsPageProps) => ( - - - + injectI18n(({ match, intl, uiCapabilities }: LogsPageProps) => { + const [sourceId] = useSourceId(); + const source = useSource({ sourceId }); + const { hasLogAnalysisCapabilites } = useLogAnalysisCapabilities(); - + return ( + + + -
+ - - - + {source.isLoadingSource ? ( + + ) : source.hasFailedLoadingSource ? ( + + ) : ( + <> + + + - - - - - - - - )) + + + + + + + )} + + + ); + }) ); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_content.tsx index abcc881dd250e..3188b3e03b015 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_content.tsx @@ -6,32 +6,12 @@ import React, { useContext } from 'react'; -import { SourceErrorPage } from '../../../components/source_error_page'; -import { SourceLoadingPage } from '../../../components/source_loading_page'; import { Source } from '../../../containers/source'; import { LogsPageLogsContent } from './page_logs_content'; import { LogsPageNoIndicesContent } from './page_no_indices_content'; export const StreamPageContent: React.FunctionComponent = () => { - const { - hasFailedLoadingSource, - isLoadingSource, - logIndicesExist, - loadSource, - loadSourceFailureMessage, - } = useContext(Source.Context); + const { logIndicesExist } = useContext(Source.Context); - return ( - <> - {isLoadingSource ? ( - - ) : logIndicesExist ? ( - - ) : hasFailedLoadingSource ? ( - - ) : ( - - )} - - ); + return <>{logIndicesExist ? : }; }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_providers.tsx index b93cf48bde5e7..55ffc807f7ba8 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_providers.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/stream/page_providers.tsx @@ -4,27 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useContext } from 'react'; import { LogFlyout } from '../../../containers/logs/log_flyout'; import { LogViewConfiguration } from '../../../containers/logs/log_view_configuration'; import { LogHighlightsState } from '../../../containers/logs/log_highlights/log_highlights'; -import { Source, useSource } from '../../../containers/source'; -import { useSourceId } from '../../../containers/source_id'; +import { Source } from '../../../containers/source'; export const LogsPageProviders: React.FunctionComponent = ({ children }) => { - const [sourceId] = useSourceId(); - const source = useSource({ sourceId }); + const { sourceId, version } = useContext(Source.Context); return ( - - - - - {children} - - - - + + + + {children} + + + ); }; From 84248c2f894f3365478b690b2bce190c39cc9c28 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 9 Aug 2019 00:37:19 +0100 Subject: [PATCH 03/25] Add job status checking functionality --- .../logs/log_analysis/log_analysis_jobs.tsx | 54 +++++++++++++++++-- .../logs/log_analysis/ml_api_types.ts | 29 ++++++++++ .../infra/public/pages/logs/analysis/page.tsx | 25 +++++++-- .../plugins/infra/public/pages/logs/index.tsx | 6 ++- 4 files changed, 103 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index dcecfaea3467b..cc97a3b9acebb 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -5,12 +5,17 @@ */ import createContainer from 'constate-latest'; -import { useMemo, useState } from 'react'; +import { useMemo, useEffect, useState } from 'react'; import { kfetch } from 'ui/kfetch'; - -import { getJobIdPrefix } from '../../../../common/log_analysis'; +import { values } from 'lodash'; +import { getJobId, getJobIdPrefix } from '../../../../common/log_analysis'; +import { throwErrors, createPlainError } from '../../../../common/runtime_types'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { setupMlModuleRequestPayloadRT } from './ml_api_types'; +import { + setupMlModuleRequestPayloadRT, + fetchJobStatusRequestPayloadRT, + fetchJobStatusResponsePayloadRT, +} from './ml_api_types'; type JobStatus = 'unknown' | 'querying' | 'missing' | 'creating' | 'running' | 'inconsistent'; @@ -53,17 +58,56 @@ export const useLogAnalysisJobs = ({ { cancelPreviousOn: 'resolution', createPromise: async () => { - kfetch({ + const response = await kfetch({ method: 'POST', pathname: '/api/ml/jobs/jobs_summary', + body: JSON.stringify( + fetchJobStatusRequestPayloadRT.encode({ + jobIds: [getJobId(spaceId, sourceId, 'log-entry-rate')], + }) + ), }); + return fetchJobStatusResponsePayloadRT + .decode(response) + .getOrElseL(throwErrors(createPlainError)); + }, + onResolve: response => { + if (response && response.length) { + const logEntryRate = response.find( + job => job.id === getJobId(spaceId, sourceId, 'log-entry-rate') + ); + setJobStatus({ + logEntryRate: logEntryRate ? (logEntryRate.jobState as JobStatus) : 'unknown', + }); + } + }, + onReject: error => { + // TODO: Handle errors }, }, [indexPattern, spaceId, sourceId] ); + useEffect(() => { + fetchJobStatus(); + }, []); + + const isSetupRequired = useMemo(() => { + const jobStates = values(jobStatus); + const badStates = jobStates.filter(state => { + return state === 'unknown' || state === 'missing' || state === 'inconsistent'; + }); + return badStates.length > 0; + }, [jobStatus]); + + const isLoadingSetupStatus = useMemo(() => fetchJobStatusRequest.state === 'pending', [ + fetchJobStatusRequest.state, + ]); + return { jobStatus, + isSetupRequired, + isLoadingSetupStatus, }; }; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts index ee70edc31d49b..74f450d0a7637 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts @@ -26,3 +26,32 @@ export const getMlCapabilitiesResponsePayloadRT = rt.type({ }); export type GetMlCapabilitiesResponsePayload = rt.TypeOf; + +export const fetchJobStatusRequestPayloadRT = rt.type({ + jobIds: rt.array(rt.string), +}); + +export type FetchJobStatusRequestPayload = rt.TypeOf; + +// TODO: Get types aligned properly with response +// export const fetchJobStatusResponsePayloadRT = rt.array(rt.type({ +// datafeedId: rt.string, +// datafeedIndices: rt.array(rt.string), +// datafeedState: rt.string, +// description: rt.string, +// earliestTimestampMs: rt.number, +// groups: rt.array(rt.string), +// hasDatafeed: rt.boolean, +// id: rt.string, +// isSingleMetricViewerJob: rt.boolean, +// jobState: rt.string, +// latestResultsTimestampMs: rt.number, +// latestTimestampMs: rt.number, +// memory_status: rt.string, +// nodeName: rt.string, +// processed_record_count: rt.number +// })); + +export const fetchJobStatusResponsePayloadRT = rt.any; + +export type FetchJobStatusResponsePayload = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index 4e54cef7e5738..fa1f3195dc1bc 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -4,20 +4,37 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; - +import React, { useContext } from 'react'; +import { last } from 'lodash'; +import chrome from 'ui/chrome'; import { ColumnarPage } from '../../../components/page'; import { AnalysisPageProviders } from './page_providers'; import { AnalysisResultsContent } from './page_results_content'; import { AnalysisSetupContent } from './page_setup_content'; +import { useLogAnalysisJobs } from '../../../containers/logs/log_analysis/log_analysis_jobs'; +import { Source } from '../../../containers/source'; export const AnalysisPage = () => { - const isSetupRequired = true; + const { sourceId, source } = useContext(Source.Context); + // TODO: Find out the proper Kibana way to derive the space ID client side + const basePath = chrome.getBasePath(); + const spaceId = basePath.includes('s/') ? last(basePath.split('/')) : 'default'; + const { isSetupRequired, isLoadingSetupStatus } = useLogAnalysisJobs({ + indexPattern: source.configuration.logAlias, + sourceId, + spaceId, + }); return ( - {isSetupRequired ? : } + {isLoadingSetupStatus ? ( +
Checking status...
+ ) : isSetupRequired ? ( + + ) : ( + + )}
); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx index 7fb060b45c63a..d4c410cd291eb 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx @@ -36,7 +36,6 @@ export const LogsPage = injectUICapabilities( const [sourceId] = useSourceId(); const source = useSource({ sourceId }); const { hasLogAnalysisCapabilites } = useLogAnalysisCapabilities(); - return ( @@ -65,7 +64,10 @@ export const LogsPage = injectUICapabilities( ]} readOnlyBadge={!uiCapabilities.logs.save} /> - {source.isLoadingSource ? ( + {source.isLoadingSource || + (!source.isLoadingSource && + !source.hasFailedLoadingSource && + source.source === undefined) ? ( ) : source.hasFailedLoadingSource ? ( Date: Fri, 9 Aug 2019 13:27:50 +0100 Subject: [PATCH 04/25] Add a loading page for the job status check --- .../legacy/plugins/infra/public/pages/logs/analysis/page.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index fa1f3195dc1bc..1809f8041e2ff 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -8,6 +8,7 @@ import React, { useContext } from 'react'; import { last } from 'lodash'; import chrome from 'ui/chrome'; import { ColumnarPage } from '../../../components/page'; +import { LoadingPage } from '../../../components/loading_page'; import { AnalysisPageProviders } from './page_providers'; import { AnalysisResultsContent } from './page_results_content'; import { AnalysisSetupContent } from './page_setup_content'; @@ -29,7 +30,7 @@ export const AnalysisPage = () => { {isLoadingSetupStatus ? ( -
Checking status...
+ ) : isSetupRequired ? ( ) : ( From 6c0bac5bf4bde682e8a1961ef9a8807e2322ebf2 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 9 Aug 2019 15:51:36 +0100 Subject: [PATCH 05/25] Change types / change method for deriving space ID / change setup requirement filtering check --- .../logs/log_analysis/log_analysis_jobs.tsx | 22 ++++++++----------- .../logs/log_analysis/ml_api_types.ts | 8 ++++--- .../infra/public/pages/logs/analysis/page.tsx | 7 ++---- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index cc97a3b9acebb..b9576474453db 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -8,16 +8,13 @@ import createContainer from 'constate-latest'; import { useMemo, useEffect, useState } from 'react'; import { kfetch } from 'ui/kfetch'; import { values } from 'lodash'; -import { getJobId, getJobIdPrefix } from '../../../../common/log_analysis'; +import { getJobId } from '../../../../common/log_analysis'; import { throwErrors, createPlainError } from '../../../../common/runtime_types'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { - setupMlModuleRequestPayloadRT, - fetchJobStatusRequestPayloadRT, - fetchJobStatusResponsePayloadRT, -} from './ml_api_types'; +import { fetchJobStatusRequestPayloadRT, fetchJobStatusResponsePayloadRT } from './ml_api_types'; -type JobStatus = 'unknown' | 'querying' | 'missing' | 'creating' | 'running' | 'inconsistent'; +type JobStatus = 'unknown' | 'closed' | 'closing' | 'failed' | 'opened' | 'opening' | 'deleted'; +// type DatafeedStatus = 'unknown' | 'started' | 'starting' | 'stopped' | 'stopping' | 'deleted'; export const useLogAnalysisJobs = ({ indexPattern, @@ -74,10 +71,10 @@ export const useLogAnalysisJobs = ({ onResolve: response => { if (response && response.length) { const logEntryRate = response.find( - job => job.id === getJobId(spaceId, sourceId, 'log-entry-rate') + (job: any) => job.id === getJobId(spaceId, sourceId, 'log-entry-rate') ); setJobStatus({ - logEntryRate: logEntryRate ? (logEntryRate.jobState as JobStatus) : 'unknown', + logEntryRate: logEntryRate ? logEntryRate.jobState : 'unknown', }); } }, @@ -94,10 +91,9 @@ export const useLogAnalysisJobs = ({ const isSetupRequired = useMemo(() => { const jobStates = values(jobStatus); - const badStates = jobStates.filter(state => { - return state === 'unknown' || state === 'missing' || state === 'inconsistent'; - }); - return badStates.length > 0; + return ( + jobStates.filter(state => state === 'opened' || state === 'opening').length < jobStates.length + ); }, [jobStatus]); const isLoadingSetupStatus = useMemo(() => fetchJobStatusRequest.state === 'pending', [ diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts index 74f450d0a7637..fc9ff0d3834b0 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts @@ -33,7 +33,6 @@ export const fetchJobStatusRequestPayloadRT = rt.type({ export type FetchJobStatusRequestPayload = rt.TypeOf; -// TODO: Get types aligned properly with response // export const fetchJobStatusResponsePayloadRT = rt.array(rt.type({ // datafeedId: rt.string, // datafeedIndices: rt.array(rt.string), @@ -48,8 +47,11 @@ export type FetchJobStatusRequestPayload = rt.TypeOf { const { sourceId, source } = useContext(Source.Context); - // TODO: Find out the proper Kibana way to derive the space ID client side - const basePath = chrome.getBasePath(); - const spaceId = basePath.includes('s/') ? last(basePath.split('/')) : 'default'; + const spaceId = chrome.getInjected('activeSpace').space.id; const { isSetupRequired, isLoadingSetupStatus } = useLogAnalysisJobs({ - indexPattern: source.configuration.logAlias, + indexPattern: source ? source.configuration.logAlias : '', sourceId, spaceId, }); From 98a9fa9bd229d7c641357558d2bd00f0832c077a Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 9 Aug 2019 16:11:15 +0100 Subject: [PATCH 06/25] Use new structure --- .../api/ml_get_jobs_summary_api.ts | 55 +++++++++++++++++++ .../logs/log_analysis/log_analysis_jobs.tsx | 17 +----- .../logs/log_analysis/ml_api_types.ts | 31 ----------- 3 files changed, 57 insertions(+), 46 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts new file mode 100644 index 0000000000000..e364e534a2d61 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_get_jobs_summary_api.ts @@ -0,0 +1,55 @@ +/* + * 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 * as rt from 'io-ts'; +import { kfetch } from 'ui/kfetch'; +import { getJobId } from '../../../../../common/log_analysis'; +import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; + +export const callJobsSummaryAPI = async (spaceId: string, sourceId: string) => { + const response = await kfetch({ + method: 'POST', + pathname: '/api/ml/jobs/jobs_summary', + body: JSON.stringify( + fetchJobStatusRequestPayloadRT.encode({ + jobIds: [getJobId(spaceId, sourceId, 'log-entry-rate')], + }) + ), + }); + return fetchJobStatusResponsePayloadRT.decode(response).getOrElseL(throwErrors(createPlainError)); +}; + +export const fetchJobStatusRequestPayloadRT = rt.type({ + jobIds: rt.array(rt.string), +}); + +export type FetchJobStatusRequestPayload = rt.TypeOf; + +// TODO: Get this to align with the payload - something is tripping it up somewhere +// export const fetchJobStatusResponsePayloadRT = rt.array(rt.type({ +// datafeedId: rt.string, +// datafeedIndices: rt.array(rt.string), +// datafeedState: rt.string, +// description: rt.string, +// earliestTimestampMs: rt.number, +// groups: rt.array(rt.string), +// hasDatafeed: rt.boolean, +// id: rt.string, +// isSingleMetricViewerJob: rt.boolean, +// jobState: rt.string, +// latestResultsTimestampMs: rt.number, +// latestTimestampMs: rt.number, +// memory_status: rt.string, +// nodeName: rt.union([rt.string, rt.undefined]), +// processed_record_count: rt.number, +// fullJob: rt.any, +// auditMessage: rt.any, +// deleting: rt.union([rt.boolean, rt.undefined]), +// })); + +export const fetchJobStatusResponsePayloadRT = rt.any; + +export type FetchJobStatusResponsePayload = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index b9576474453db..391a4b190edd2 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -6,12 +6,10 @@ import createContainer from 'constate-latest'; import { useMemo, useEffect, useState } from 'react'; -import { kfetch } from 'ui/kfetch'; import { values } from 'lodash'; import { getJobId } from '../../../../common/log_analysis'; -import { throwErrors, createPlainError } from '../../../../common/runtime_types'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { fetchJobStatusRequestPayloadRT, fetchJobStatusResponsePayloadRT } from './ml_api_types'; +import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; type JobStatus = 'unknown' | 'closed' | 'closing' | 'failed' | 'opened' | 'opening' | 'deleted'; // type DatafeedStatus = 'unknown' | 'started' | 'starting' | 'stopped' | 'stopping' | 'deleted'; @@ -55,18 +53,7 @@ export const useLogAnalysisJobs = ({ { cancelPreviousOn: 'resolution', createPromise: async () => { - const response = await kfetch({ - method: 'POST', - pathname: '/api/ml/jobs/jobs_summary', - body: JSON.stringify( - fetchJobStatusRequestPayloadRT.encode({ - jobIds: [getJobId(spaceId, sourceId, 'log-entry-rate')], - }) - ), - }); - return fetchJobStatusResponsePayloadRT - .decode(response) - .getOrElseL(throwErrors(createPlainError)); + return callJobsSummaryAPI(spaceId, sourceId); }, onResolve: response => { if (response && response.length) { diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts index fc9ff0d3834b0..ee70edc31d49b 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts @@ -26,34 +26,3 @@ export const getMlCapabilitiesResponsePayloadRT = rt.type({ }); export type GetMlCapabilitiesResponsePayload = rt.TypeOf; - -export const fetchJobStatusRequestPayloadRT = rt.type({ - jobIds: rt.array(rt.string), -}); - -export type FetchJobStatusRequestPayload = rt.TypeOf; - -// export const fetchJobStatusResponsePayloadRT = rt.array(rt.type({ -// datafeedId: rt.string, -// datafeedIndices: rt.array(rt.string), -// datafeedState: rt.string, -// description: rt.string, -// earliestTimestampMs: rt.number, -// groups: rt.array(rt.string), -// hasDatafeed: rt.boolean, -// id: rt.string, -// isSingleMetricViewerJob: rt.boolean, -// jobState: rt.string, -// latestResultsTimestampMs: rt.number, -// latestTimestampMs: rt.number, -// memory_status: rt.string, -// nodeName: rt.union([rt.string, rt.undefined]), -// processed_record_count: rt.number, -// fullJob: rt.any, -// auditMessage: rt.any, -// deleting: rt.union([rt.boolean, rt.undefined]), -// })); - -export const fetchJobStatusResponsePayloadRT = rt.any; - -export type FetchJobStatusResponsePayload = rt.TypeOf; From 83330d77b9e37dea26ea3eb004b0801a320f577c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Fri, 9 Aug 2019 15:36:37 +0200 Subject: [PATCH 07/25] Add module setup to log analysis jobs hook --- .../common/log_analysis/job_parameters.ts | 5 + .../log_analysis/api/ml_setup_module_api.ts | 97 +++++++++++++++++++ .../logs/log_analysis/log_analysis_jobs.tsx | 53 ++++++---- .../infra/public/pages/logs/analysis/page.tsx | 1 + 4 files changed, 135 insertions(+), 21 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts diff --git a/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts b/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts index 82cfb0f83ed69..ebdc2251891eb 100644 --- a/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts +++ b/x-pack/legacy/plugins/infra/common/log_analysis/job_parameters.ts @@ -6,8 +6,13 @@ import { JobType } from './log_analysis'; +export const bucketSpan = 900000; + export const getJobIdPrefix = (spaceId: string, sourceId: string) => `kibana-logs-ui-${spaceId}-${sourceId}-`; export const getJobId = (spaceId: string, sourceId: string, jobType: JobType) => `${getJobIdPrefix(spaceId, sourceId)}${jobType}`; + +export const getDatafeedId = (spaceId: string, sourceId: string, jobType: JobType) => + `datafeed-${getJobId(spaceId, sourceId, jobType)}`; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts new file mode 100644 index 0000000000000..3ae1f447e22d9 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -0,0 +1,97 @@ +/* + * 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 * as rt from 'io-ts'; +import { kfetch } from 'ui/kfetch'; + +import { getJobIdPrefix } from '../../../../../common/log_analysis'; +import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; + +export const callSetupMlModuleAPI = async ( + spaceId: string, + sourceId: string, + indexPattern: string, + timeField: string, + bucketSpan: number +) => { + const response = await kfetch({ + method: 'POST', + pathname: '/api/ml/modules/setup', + body: JSON.stringify( + setupMlModuleRequestPayloadRT.encode({ + indexPatternName: indexPattern, + prefix: getJobIdPrefix(spaceId, sourceId), + startDatafeed: true, + jobOverrides: [ + { + job_id: 'log-entry-rate', + analysis_config: { + bucket_span: `${bucketSpan}ms`, + }, + data_description: { + time_field: timeField, + }, + }, + ], + datafeedOverrides: [ + { + job_id: 'log-entry-rate', + aggregations: { + buckets: { + date_histogram: { + field: timeField, + fixed_interval: `{bucketSpan}ms`, + }, + aggregations: { + [timeField]: { + max: { + field: [timeField], + }, + }, + doc_count_per_minute: { + bucket_script: { + script: { + params: { + bucket_span_in_ms: bucketSpan, + }, + }, + }, + }, + }, + }, + }, + }, + ], + }) + ), + }); + + return setupMlModuleResponsePayloadRT.decode(response).getOrElseL(throwErrors(createPlainError)); +}; + +const setupMlModuleRequestPayloadRT = rt.type({ + indexPatternName: rt.string, + prefix: rt.string, + startDatafeed: rt.boolean, + jobOverrides: rt.array(rt.object), + datafeedOverrides: rt.array(rt.object), +}); + +const setupMlModuleResponsePayloadRT = rt.type({ + datafeeds: rt.array( + rt.type({ + id: rt.string, + started: rt.boolean, + success: rt.boolean, + }) + ), + jobs: rt.array( + rt.type({ + id: rt.string, + success: rt.boolean, + }) + ), +}); diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index 391a4b190edd2..7718349292cf8 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -7,21 +7,27 @@ import createContainer from 'constate-latest'; import { useMemo, useEffect, useState } from 'react'; import { values } from 'lodash'; -import { getJobId } from '../../../../common/log_analysis'; +import { bucketSpan, getJobId } from '../../../../common/log_analysis'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { callSetupMlModuleAPI } from './api/ml_setup_module_api'; import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; -type JobStatus = 'unknown' | 'closed' | 'closing' | 'failed' | 'opened' | 'opening' | 'deleted'; +// combines and abstracts job and datafeed status +type JobStatus = 'unknown' | 'missing' | 'inconsistent' | 'created' | 'started'; + +// type JobStatus = 'unknown' | 'closed' | 'closing' | 'failed' | 'opened' | 'opening' | 'deleted'; // type DatafeedStatus = 'unknown' | 'started' | 'starting' | 'stopped' | 'stopping' | 'deleted'; export const useLogAnalysisJobs = ({ indexPattern, sourceId, spaceId, + timeField, }: { indexPattern: string; sourceId: string; spaceId: string; + timeField: string; }) => { const [jobStatus, setJobStatus] = useState<{ logEntryRate: JobStatus; @@ -29,25 +35,30 @@ export const useLogAnalysisJobs = ({ logEntryRate: 'unknown', }); - // const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( - // { - // cancelPreviousOn: 'resolution', - // createPromise: async () => { - // kfetch({ - // method: 'POST', - // pathname: '/api/ml/modules/setup', - // body: JSON.stringify( - // setupMlModuleRequestPayloadRT.encode({ - // indexPatternName: indexPattern, - // prefix: getJobIdPrefix(spaceId, sourceId), - // startDatafeed: true, - // }) - // ), - // }); - // }, - // }, - // [indexPattern, spaceId, sourceId] - // ); + const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await callSetupMlModuleAPI(spaceId, sourceId, indexPattern, timeField, bucketSpan); + }, + onResolve: ({ datafeeds, jobs }) => { + const hasSuccessfullyCreatedJobs = jobs.every(job => job.success); + const hasSuccessfullyStartedDatafeeds = datafeeds.every( + datafeed => datafeed.success && datafeed.started + ); + + setJobStatus(currentJobStatus => ({ + ...currentJobStatus, + logEntryRate: hasSuccessfullyCreatedJobs + ? hasSuccessfullyStartedDatafeeds + ? 'started' + : 'created' + : 'inconsistent', + })); + }, + }, + [indexPattern, spaceId, sourceId] + ); const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( { diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index 6a39b76f07f6d..00a8f0f214674 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -21,6 +21,7 @@ export const AnalysisPage = () => { indexPattern: source ? source.configuration.logAlias : '', sourceId, spaceId, + timeField: source ? source.configuration.fields.timestamp : '', }); return ( From 6951bde53d79d4a97d96bfd4496ea4062ac1409f Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 13 Aug 2019 21:12:59 +0100 Subject: [PATCH 08/25] Add ID to path --- .../containers/logs/log_analysis/api/ml_setup_module_api.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index 3ae1f447e22d9..d731ad19eca46 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -10,6 +10,8 @@ import { kfetch } from 'ui/kfetch'; import { getJobIdPrefix } from '../../../../../common/log_analysis'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; +const MODULE_ID = 'logs_ui_analysis'; + export const callSetupMlModuleAPI = async ( spaceId: string, sourceId: string, @@ -19,7 +21,7 @@ export const callSetupMlModuleAPI = async ( ) => { const response = await kfetch({ method: 'POST', - pathname: '/api/ml/modules/setup', + pathname: `/api/ml/modules/setup/${MODULE_ID}`, body: JSON.stringify( setupMlModuleRequestPayloadRT.encode({ indexPatternName: indexPattern, From 705577a8215973080b7efdbd5d5816ba92de0a30 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 15 Aug 2019 14:26:50 -0500 Subject: [PATCH 09/25] [Logs UI] Add analyis setup landing screen --- .../logs/analysis/page_setup_content.tsx | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index a4e1402e9ce60..6d7280f6b0eb9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -5,12 +5,69 @@ */ import React from 'react'; - +import { + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiPageContentBody, + EuiText, + EuiTitle, + EuiSpacer, + EuiButton, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import euiStyled from '../../../../../../common/eui_styled_components'; import { useTrackPageview } from '../../../hooks/use_track_metric'; export const AnalysisSetupContent = () => { useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); - return
Setup
; + return ( + + + + + + +

+ +

+
+
+
+ + + + + + + + Create ML Job + + +
+
+
+ ); }; + +// https://github.com/elastic/eui/issues/2232 +const AnalysisPageContent = euiStyled(EuiPageContent)<{ style: object }>``; + +const AnalysisSetupPage = euiStyled(EuiPage)` + height: 100%; +`; From 1beb78ccc280ef9a0959da2e6fc0ec39fec56fb4 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 15 Aug 2019 15:44:12 -0500 Subject: [PATCH 10/25] Add function to set up ML module on click --- .../log_analysis/api/ml_setup_module_api.ts | 4 +++ .../logs/log_analysis/log_analysis_jobs.tsx | 17 ++++++++-- .../infra/public/pages/logs/analysis/page.tsx | 9 ++++-- .../logs/analysis/page_setup_content.tsx | 31 ++++++++++++++----- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index d731ad19eca46..c852b137a6b7e 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -13,17 +13,21 @@ import { throwErrors, createPlainError } from '../../../../../common/runtime_typ const MODULE_ID = 'logs_ui_analysis'; export const callSetupMlModuleAPI = async ( + start: number | null, + end: number | null, spaceId: string, sourceId: string, indexPattern: string, timeField: string, bucketSpan: number ) => { + const startEndProps = start && end ? { start, end } : {}; const response = await kfetch({ method: 'POST', pathname: `/api/ml/modules/setup/${MODULE_ID}`, body: JSON.stringify( setupMlModuleRequestPayloadRT.encode({ + ...startEndProps, indexPatternName: indexPattern, prefix: getJobIdPrefix(spaceId, sourceId), startDatafeed: true, diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index ab5395dc76234..925403e2f66fb 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -39,8 +39,16 @@ export const useLogAnalysisJobs = ({ const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( { cancelPreviousOn: 'resolution', - createPromise: async () => { - return await callSetupMlModuleAPI(spaceId, sourceId, indexPattern, timeField, bucketSpan); + createPromise: async (start = null, end = null) => { + return await callSetupMlModuleAPI( + start, + end, + spaceId, + sourceId, + indexPattern, + timeField, + bucketSpan + ); }, onResolve: ({ datafeeds, jobs }) => { const hasSuccessfullyCreatedJobs = jobs.every(job => job.success); @@ -99,12 +107,17 @@ export const useLogAnalysisJobs = ({ fetchJobStatusRequest.state, ]); + const isSettingUpMlModule = useMemo(() => setupMlModuleRequest.state === 'pending', [ + setupMlModuleRequest.state, + ]); + return { jobStatus, isSetupRequired, isLoadingSetupStatus, setupMlModule, setupMlModuleRequest, + isSettingUpMlModule, }; }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index 5c97046fa9663..905ba15007bbf 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -18,7 +18,12 @@ import { Source } from '../../../containers/source'; export const AnalysisPage = () => { const { sourceId, source } = useContext(Source.Context); const spaceId = chrome.getInjected('activeSpace').space.id; - const { isSetupRequired, isLoadingSetupStatus } = useLogAnalysisJobs({ + const { + isSetupRequired, + isLoadingSetupStatus, + setupMlModule, + isSettingUpMlModule, + } = useLogAnalysisJobs({ indexPattern: source ? source.configuration.logAlias : '', sourceId, spaceId, @@ -35,7 +40,7 @@ export const AnalysisPage = () => { })} /> ) : isSetupRequired ? ( - + ) : ( )} diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 6d7280f6b0eb9..9a1d9beec665e 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -21,10 +21,17 @@ import { FormattedMessage } from '@kbn/i18n/react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { useTrackPageview } from '../../../hooks/use_track_metric'; -export const AnalysisSetupContent = () => { +interface AnalysisSetupContentProps { + onCreateJobs: () => void; + isSettingUp: boolean; +} + +export const AnalysisSetupContent: React.FunctionComponent = ({ + onCreateJobs, + isSettingUp, +}) => { useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); - return ( @@ -32,7 +39,6 @@ export const AnalysisSetupContent = () => { verticalPosition="center" horizontalPosition="center" data-test-subj="analysisSetupContent" - style={{ maxWidth: '518px' }} > @@ -55,8 +61,17 @@ export const AnalysisSetupContent = () => { - - Create ML Job + + @@ -65,8 +80,10 @@ export const AnalysisSetupContent = () => { ); }; -// https://github.com/elastic/eui/issues/2232 -const AnalysisPageContent = euiStyled(EuiPageContent)<{ style: object }>``; +// !important due to https://github.com/elastic/eui/issues/2232 +const AnalysisPageContent = euiStyled(EuiPageContent)` + max-width: 518px !important; +`; const AnalysisSetupPage = euiStyled(EuiPage)` height: 100%; From f6594e3b4d36496aeba65e8886894c59e156c024 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 15 Aug 2019 15:59:42 -0500 Subject: [PATCH 11/25] Use partial type for start and end props --- .../log_analysis/api/ml_setup_module_api.ts | 20 ++++++++++++++----- .../logs/log_analysis/log_analysis_jobs.tsx | 2 +- .../logs/analysis/page_setup_content.tsx | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index c852b137a6b7e..246651081bd53 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -13,21 +13,21 @@ import { throwErrors, createPlainError } from '../../../../../common/runtime_typ const MODULE_ID = 'logs_ui_analysis'; export const callSetupMlModuleAPI = async ( - start: number | null, - end: number | null, + start: number | undefined, + end: number | undefined, spaceId: string, sourceId: string, indexPattern: string, timeField: string, bucketSpan: number ) => { - const startEndProps = start && end ? { start, end } : {}; const response = await kfetch({ method: 'POST', pathname: `/api/ml/modules/setup/${MODULE_ID}`, body: JSON.stringify( setupMlModuleRequestPayloadRT.encode({ - ...startEndProps, + start, + end, indexPatternName: indexPattern, prefix: getJobIdPrefix(spaceId, sourceId), startDatafeed: true, @@ -78,7 +78,12 @@ export const callSetupMlModuleAPI = async ( return setupMlModuleResponsePayloadRT.decode(response).getOrElseL(throwErrors(createPlainError)); }; -const setupMlModuleRequestPayloadRT = rt.type({ +const setupMlModuleTimeParamsRT = rt.partial({ + start: rt.number, + end: rt.number, +}); + +const setupMlModuleRequestParamsRT = rt.type({ indexPatternName: rt.string, prefix: rt.string, startDatafeed: rt.boolean, @@ -86,6 +91,11 @@ const setupMlModuleRequestPayloadRT = rt.type({ datafeedOverrides: rt.array(rt.object), }); +const setupMlModuleRequestPayloadRT = rt.intersection([ + setupMlModuleTimeParamsRT, + setupMlModuleRequestParamsRT, +]); + const setupMlModuleResponsePayloadRT = rt.type({ datafeeds: rt.array( rt.type({ diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index 925403e2f66fb..5761cdd041238 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -39,7 +39,7 @@ export const useLogAnalysisJobs = ({ const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( { cancelPreviousOn: 'resolution', - createPromise: async (start = null, end = null) => { + createPromise: async (start, end) => { return await callSetupMlModuleAPI( start, end, diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 9a1d9beec665e..8d0cee8953ea7 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -22,7 +22,7 @@ import euiStyled from '../../../../../../common/eui_styled_components'; import { useTrackPageview } from '../../../hooks/use_track_metric'; interface AnalysisSetupContentProps { - onCreateJobs: () => void; + onCreateJobs: () => Promise; isSettingUp: boolean; } From fb139dfe500a6ba42b506e41e4afd1d7b853da7a Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 15 Aug 2019 18:00:31 -0500 Subject: [PATCH 12/25] Add start and end time selection --- .../infra/public/pages/logs/analysis/page.tsx | 2 +- .../logs/analysis/page_setup_content.tsx | 157 ++++++++++++++++-- 2 files changed, 142 insertions(+), 17 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index 905ba15007bbf..b72571f6d1b67 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -40,7 +40,7 @@ export const AnalysisPage = () => { })} /> ) : isSetupRequired ? ( - + ) : ( )} diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 8d0cee8953ea7..2e53f5c2161a4 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useState, useMemo } from 'react'; +import moment, { Moment } from 'moment'; import { EuiPage, EuiPageBody, @@ -16,22 +17,70 @@ import { EuiTitle, EuiSpacer, EuiButton, + EuiButtonIcon, + EuiDescribedFormGroup, + EuiFormRow, + EuiDatePicker, + EuiFlexGroup, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { useTrackPageview } from '../../../hooks/use_track_metric'; interface AnalysisSetupContentProps { - onCreateJobs: () => Promise; + setupMlModule: (startTime: number | undefined, endTime: number | undefined) => Promise; isSettingUp: boolean; } +const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', { + defaultMessage: 'Start time', +}); +const endTimeLabel = i18n.translate('xpack.infra.analysisSetup.endTimeLabel', { + defaultMessage: 'End time', +}); +const startTimeDefaultDescription = i18n.translate( + 'xpack.infra.analysisSetup.startTimeDefaultDescription', + { + defaultMessage: 'now', + } +); +const endTimeDefaultDescription = i18n.translate( + 'xpack.infra.analysisSetup.endTimeDefaultDescription', + { + defaultMessage: 'indefinitely', + } +); +const clearStartTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearStartTimeLabel', { + defaultMessage: 'Clear start time', +}); +const clearEndTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearEndTimeLabel', { + defaultMessage: 'Clear end time', +}); + +function selectedDateToParam(selectedDate: Moment | null) { + if (selectedDate) { + return selectedDate.unix(); + } + return undefined; +} + export const AnalysisSetupContent: React.FunctionComponent = ({ - onCreateJobs, + setupMlModule, isSettingUp, }) => { useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); + + const [startTime, setStartTime] = useState(null); + const [endTime, setEndTime] = useState(null); + + const now = useMemo(() => moment(), []); + const selectedEndTimeIsToday = !endTime || endTime.isSame(now, 'day'); + + const onClickCreateJob = () => + setupMlModule(selectedDateToParam(startTime), selectedDateToParam(endTime)); + return ( @@ -59,20 +108,96 @@ export const AnalysisSetupContent: React.FunctionComponent - - - + + } + description={ + + } > - - + + + + {startTime && ( + setStartTime(null)} + /> + )} + + + + + + {endTime && ( + setEndTime(null)} + /> + )} + + + + + + From c36586f4cd650ef20f67807d8efde69f61eb4b42 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 16 Aug 2019 12:28:53 +0100 Subject: [PATCH 13/25] Fix syntax --- .../containers/logs/log_analysis/api/ml_setup_module_api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index 246651081bd53..e6f799ff0d50e 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -49,12 +49,12 @@ export const callSetupMlModuleAPI = async ( buckets: { date_histogram: { field: timeField, - fixed_interval: `{bucketSpan}ms`, + fixed_interval: `${bucketSpan}ms`, }, aggregations: { [timeField]: { max: { - field: [timeField], + field: `${timeField}`, }, }, doc_count_per_minute: { From 256944408ebfba6591a6076efc304b17c9406218 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 12:09:23 -0500 Subject: [PATCH 14/25] Change seconds timestamp to ms --- .../infra/public/pages/logs/analysis/page_setup_content.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 2e53f5c2161a4..cfca30ed784c2 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -60,7 +60,7 @@ const clearEndTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearEndTime function selectedDateToParam(selectedDate: Moment | null) { if (selectedDate) { - return selectedDate.unix(); + return selectedDate.valueOf(); // To ms unix timestamp } return undefined; } From fab784e3e29984d86adb8f5ea0edae7d0e04e597 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 12:15:05 -0500 Subject: [PATCH 15/25] Update wording --- .../infra/public/pages/logs/analysis/page_setup_content.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index cfca30ed784c2..80b4fd0060149 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -42,13 +42,13 @@ const endTimeLabel = i18n.translate('xpack.infra.analysisSetup.endTimeLabel', { const startTimeDefaultDescription = i18n.translate( 'xpack.infra.analysisSetup.startTimeDefaultDescription', { - defaultMessage: 'now', + defaultMessage: 'Start of log indices', } ); const endTimeDefaultDescription = i18n.translate( 'xpack.infra.analysisSetup.endTimeDefaultDescription', { - defaultMessage: 'indefinitely', + defaultMessage: 'Indefinitely', } ); const clearStartTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearStartTimeLabel', { @@ -120,7 +120,7 @@ export const AnalysisSetupContent: React.FunctionComponent } > From 3104d10a610b746be7a9b5417f7f31aec1569e79 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 14:41:51 -0500 Subject: [PATCH 16/25] Use FormControlLayout to clear datepickers --- .../logs/analysis/page_setup_content.tsx | 78 ++++++++----------- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 80b4fd0060149..aa728eb26b481 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -17,11 +17,11 @@ import { EuiTitle, EuiSpacer, EuiButton, - EuiButtonIcon, EuiDescribedFormGroup, EuiFormRow, EuiDatePicker, EuiFlexGroup, + EuiFormControlLayout, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -51,12 +51,6 @@ const endTimeDefaultDescription = i18n.translate( defaultMessage: 'Indefinitely', } ); -const clearStartTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearStartTimeLabel', { - defaultMessage: 'Clear start time', -}); -const clearEndTimeLabel = i18n.translate('xpack.infra.analysisSetup.clearEndTimeLabel', { - defaultMessage: 'Clear end time', -}); function selectedDateToParam(selectedDate: Moment | null) { if (selectedDate) { @@ -132,21 +126,17 @@ export const AnalysisSetupContent: React.FunctionComponent - - {startTime && ( - setStartTime(null)} + setStartTime(null) } : undefined} + > + - )} + - - {endTime && ( - setEndTime(null)} + setEndTime(null) } : undefined} + > + - )} + Date: Fri, 16 Aug 2019 14:42:56 -0500 Subject: [PATCH 17/25] Update wording about earlier start date --- .../infra/public/pages/logs/analysis/page_setup_content.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index aa728eb26b481..3860e3dc83b54 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -114,7 +114,7 @@ export const AnalysisSetupContent: React.FunctionComponent } > From 895cb3f283d191927b334be0bd6135679ab84991 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 14:43:29 -0500 Subject: [PATCH 18/25] Remove specific point in time wording --- .../infra/public/pages/logs/analysis/page_setup_content.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 3860e3dc83b54..72b755d8b6f0c 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -114,7 +114,7 @@ export const AnalysisSetupContent: React.FunctionComponent } > From 69d7a7b4bad218721a37e68fd67cf3a1638c62a8 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 14:49:37 -0500 Subject: [PATCH 19/25] Fix typechecking --- .../logs/log_analysis/api/ml_setup_module_api.ts | 2 ++ .../containers/logs/log_analysis/log_analysis_jobs.tsx | 8 ++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index e6f799ff0d50e..a7fbd8c10f10f 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -111,3 +111,5 @@ const setupMlModuleResponsePayloadRT = rt.type({ }) ), }); + +export type SetupMlModuleResponsePayload = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index 5761cdd041238..d84885af76b51 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -9,16 +9,12 @@ import { useMemo, useEffect, useState } from 'react'; import { values } from 'lodash'; import { bucketSpan, getJobId } from '../../../../common/log_analysis'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { callSetupMlModuleAPI } from './api/ml_setup_module_api'; +import { callSetupMlModuleAPI, SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; // combines and abstracts job and datafeed status type JobStatus = 'unknown' | 'missing' | 'inconsistent' | 'created' | 'started'; -// type JobStatus = 'unknown' | 'closed' | 'closing' | 'failed' | 'opened' | 'opening' | 'deleted'; - -// type DatafeedStatus = 'unknown' | 'started' | 'starting' | 'stopped' | 'stopping' | 'deleted'; - export const useLogAnalysisJobs = ({ indexPattern, sourceId, @@ -50,7 +46,7 @@ export const useLogAnalysisJobs = ({ bucketSpan ); }, - onResolve: ({ datafeeds, jobs }) => { + onResolve: ({ datafeeds, jobs }: SetupMlModuleResponsePayload) => { const hasSuccessfullyCreatedJobs = jobs.every(job => job.success); const hasSuccessfullyStartedDatafeeds = datafeeds.every( datafeed => datafeed.success && datafeed.started From b20e01818b7bb58148d284f94243fe3b2f3ce885 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 16:01:05 -0500 Subject: [PATCH 20/25] Reload analysis page on successful job creation --- .../logs/log_analysis/log_analysis_jobs.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index d84885af76b51..867f28dfabe74 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -6,14 +6,20 @@ import createContainer from 'constate-latest'; import { useMemo, useEffect, useState } from 'react'; -import { values } from 'lodash'; import { bucketSpan, getJobId } from '../../../../common/log_analysis'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { callSetupMlModuleAPI, SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; // combines and abstracts job and datafeed status -type JobStatus = 'unknown' | 'missing' | 'inconsistent' | 'created' | 'started'; +type JobStatus = + | 'unknown' + | 'missing' + | 'inconsistent' + | 'created' + | 'started' + | 'opening' + | 'opened'; export const useLogAnalysisJobs = ({ indexPattern, @@ -93,9 +99,10 @@ export const useLogAnalysisJobs = ({ }, []); const isSetupRequired = useMemo(() => { - const jobStates = values(jobStatus); + const jobStates = Object.values(jobStatus); return ( - jobStates.filter(state => state === 'opened' || state === 'opening').length < jobStates.length + jobStates.filter(state => ['opened', 'opening', 'created', 'started'].includes(state)) + .length < jobStates.length ); }, [jobStatus]); From 5ca200f064dbbe2125a9839fcc4d12260d9a9ff7 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Fri, 16 Aug 2019 16:24:44 -0500 Subject: [PATCH 21/25] Add error handling for setup failure --- .../logs/log_analysis/log_analysis_jobs.tsx | 6 ++++++ .../infra/public/pages/logs/analysis/page.tsx | 7 ++++++- .../pages/logs/analysis/page_setup_content.tsx | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx index 867f28dfabe74..458fc5bb8635a 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx @@ -114,6 +114,11 @@ export const useLogAnalysisJobs = ({ setupMlModuleRequest.state, ]); + const didSetupFail = useMemo( + () => !isSettingUpMlModule && setupMlModuleRequest.state !== 'uninitialized' && isSetupRequired, + [setupMlModuleRequest.state, jobStatus] + ); + return { jobStatus, isSetupRequired, @@ -121,6 +126,7 @@ export const useLogAnalysisJobs = ({ setupMlModule, setupMlModuleRequest, isSettingUpMlModule, + didSetupFail, }; }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx index b72571f6d1b67..b501b8896e61e 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page.tsx @@ -23,6 +23,7 @@ export const AnalysisPage = () => { isLoadingSetupStatus, setupMlModule, isSettingUpMlModule, + didSetupFail, } = useLogAnalysisJobs({ indexPattern: source ? source.configuration.logAlias : '', sourceId, @@ -40,7 +41,11 @@ export const AnalysisPage = () => { })} /> ) : isSetupRequired ? ( - + ) : ( )} diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 72b755d8b6f0c..162c47c56257f 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -22,6 +22,7 @@ import { EuiDatePicker, EuiFlexGroup, EuiFormControlLayout, + EuiCallOut, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -31,6 +32,7 @@ import { useTrackPageview } from '../../../hooks/use_track_metric'; interface AnalysisSetupContentProps { setupMlModule: (startTime: number | undefined, endTime: number | undefined) => Promise; isSettingUp: boolean; + didSetupFail: boolean; } const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', { @@ -51,6 +53,9 @@ const endTimeDefaultDescription = i18n.translate( defaultMessage: 'Indefinitely', } ); +const errorTitle = i18n.translate('xpack.infra.analysisSetup.errorTitle', { + defaultMessage: 'Sorry, there was an error setting up Machine Learning', +}); function selectedDateToParam(selectedDate: Moment | null) { if (selectedDate) { @@ -62,6 +67,7 @@ function selectedDateToParam(selectedDate: Moment | null) { export const AnalysisSetupContent: React.FunctionComponent = ({ setupMlModule, isSettingUp, + didSetupFail, }) => { useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); @@ -184,6 +190,16 @@ export const AnalysisSetupContent: React.FunctionComponent + {didSetupFail && ( + + + + + + )} From 09efec9b7c4db477eda23542479dda42f4d0dee6 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Mon, 19 Aug 2019 09:42:40 -0500 Subject: [PATCH 22/25] Update description ton of feature to reflect 7.4 feature set --- .../logs/analysis/page_setup_content.tsx | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 162c47c56257f..5eb455c001e9f 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -21,7 +21,6 @@ import { EuiFormRow, EuiDatePicker, EuiFlexGroup, - EuiFormControlLayout, EuiCallOut, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -105,7 +104,7 @@ export const AnalysisSetupContent: React.FunctionComponent @@ -132,17 +131,14 @@ export const AnalysisSetupContent: React.FunctionComponent - setStartTime(null) } : undefined} - > - - + setStartTime(null)} + /> - setEndTime(null) } : undefined} - > - - + setEndTime(null)} + /> Date: Mon, 19 Aug 2019 11:39:05 -0500 Subject: [PATCH 23/25] Add toggleable default message --- .../analysis_setup_timerange_form.tsx | 128 ++++++++++++++ .../logs/analysis/create_ml_jobs_button.tsx | 23 +++ .../logs/analysis/page_setup_content.tsx | 163 +++++------------- 3 files changed, 197 insertions(+), 117 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/analysis/create_ml_jobs_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx new file mode 100644 index 0000000000000..aae1a4e5d52ac --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx @@ -0,0 +1,128 @@ +/* + * 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, useState } from 'react'; +import moment, { Moment } from 'moment'; + +import { i18n } from '@kbn/i18n'; +import { + EuiForm, + EuiDescribedFormGroup, + EuiFormRow, + EuiDatePicker, + EuiFlexGroup, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CreateMLJobsButton } from './create_ml_jobs_button'; + +const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', { + defaultMessage: 'Start time', +}); +const endTimeLabel = i18n.translate('xpack.infra.analysisSetup.endTimeLabel', { + defaultMessage: 'End time', +}); +const startTimeDefaultDescription = i18n.translate( + 'xpack.infra.analysisSetup.startTimeDefaultDescription', + { + defaultMessage: 'Start of log indices', + } +); +const endTimeDefaultDescription = i18n.translate( + 'xpack.infra.analysisSetup.endTimeDefaultDescription', + { + defaultMessage: 'Indefinitely', + } +); + +function selectedDateToParam(selectedDate: Moment | null) { + if (selectedDate) { + return selectedDate.valueOf(); // To ms unix timestamp + } + return undefined; +} + +export const AnalysisSetupTimerangeForm: React.FunctionComponent<{ + isSettingUp: boolean; + setupMlModule: (startTime: number | undefined, endTime: number | undefined) => Promise; +}> = ({ isSettingUp, setupMlModule }) => { + const [startTime, setStartTime] = useState(null); + const [endTime, setEndTime] = useState(null); + + const now = useMemo(() => moment(), []); + const selectedEndTimeIsToday = !endTime || endTime.isSame(now, 'day'); + + const onClickCreateJob = () => + setupMlModule(selectedDateToParam(startTime), selectedDateToParam(endTime)); + + return ( + + + } + description={ + + } + > + + + setStartTime(null)} + /> + + + + + setEndTime(null)} + /> + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/create_ml_jobs_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/create_ml_jobs_button.tsx new file mode 100644 index 0000000000000..24caec70ed841 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/create_ml_jobs_button.tsx @@ -0,0 +1,23 @@ +/* + * 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 from 'react'; +import { EuiButton } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +export const CreateMLJobsButton: React.FunctionComponent<{ + isLoading: boolean; + onClick: () => void; +}> = ({ isLoading, onClick }) => { + return ( + + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx index 5eb455c001e9f..248d4d7bbb3b8 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState, useMemo } from 'react'; -import moment, { Moment } from 'moment'; +import React, { useState } from 'react'; import { + EuiButtonEmpty, EuiPage, EuiPageBody, EuiPageContent, @@ -16,11 +16,6 @@ import { EuiText, EuiTitle, EuiSpacer, - EuiButton, - EuiDescribedFormGroup, - EuiFormRow, - EuiDatePicker, - EuiFlexGroup, EuiCallOut, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -28,41 +23,19 @@ import { FormattedMessage } from '@kbn/i18n/react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { useTrackPageview } from '../../../hooks/use_track_metric'; +import { AnalysisSetupTimerangeForm } from './analysis_setup_timerange_form'; +import { CreateMLJobsButton } from './create_ml_jobs_button'; + interface AnalysisSetupContentProps { - setupMlModule: (startTime: number | undefined, endTime: number | undefined) => Promise; + setupMlModule: (startTime?: number | undefined, endTime?: number | undefined) => Promise; isSettingUp: boolean; didSetupFail: boolean; } -const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', { - defaultMessage: 'Start time', -}); -const endTimeLabel = i18n.translate('xpack.infra.analysisSetup.endTimeLabel', { - defaultMessage: 'End time', -}); -const startTimeDefaultDescription = i18n.translate( - 'xpack.infra.analysisSetup.startTimeDefaultDescription', - { - defaultMessage: 'Start of log indices', - } -); -const endTimeDefaultDescription = i18n.translate( - 'xpack.infra.analysisSetup.endTimeDefaultDescription', - { - defaultMessage: 'Indefinitely', - } -); const errorTitle = i18n.translate('xpack.infra.analysisSetup.errorTitle', { defaultMessage: 'Sorry, there was an error setting up Machine Learning', }); -function selectedDateToParam(selectedDate: Moment | null) { - if (selectedDate) { - return selectedDate.valueOf(); // To ms unix timestamp - } - return undefined; -} - export const AnalysisSetupContent: React.FunctionComponent = ({ setupMlModule, isSettingUp, @@ -71,14 +44,7 @@ export const AnalysisSetupContent: React.FunctionComponent(null); - const [endTime, setEndTime] = useState(null); - - const now = useMemo(() => moment(), []); - const selectedEndTimeIsToday = !endTime || endTime.isSame(now, 'day'); - - const onClickCreateJob = () => - setupMlModule(selectedDateToParam(startTime), selectedDateToParam(endTime)); + const [showTimeRangeForm, setShowTimeRangeForm] = useState(false); return ( @@ -104,85 +70,36 @@ export const AnalysisSetupContent: React.FunctionComponent - - - } - description={ - + + - } - > - - - setStartTime(null)} - /> - - - - - setEndTime(null)} - /> - - - - - - + + ) : ( + <> + + + {' '} + setShowTimeRangeForm(true)}> + + + + + setupMlModule()} /> + + )} {didSetupFail && ( @@ -208,3 +125,15 @@ const AnalysisPageContent = euiStyled(EuiPageContent)` const AnalysisSetupPage = euiStyled(EuiPage)` height: 100%; `; + +const ByDefaultText = euiStyled(EuiText).attrs({ size: 's' })` + & .euiButtonEmpty { + font-size: inherit; + line-height: inherit; + height: initial; + } + + & .euiButtonEmpty__content { + padding: 0; + } +`; From c7a33dcf6eb56bfe4b0e276101ac0b3ce28450c4 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Mon, 19 Aug 2019 15:18:43 -0500 Subject: [PATCH 24/25] Revert to EuiFormControlLayout until eui changes are pushed --- .../analysis_setup_timerange_form.tsx | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx index aae1a4e5d52ac..120670db83e8a 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/analysis_setup_timerange_form.tsx @@ -14,6 +14,7 @@ import { EuiFormRow, EuiDatePicker, EuiFlexGroup, + EuiFormControlLayout, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { CreateMLJobsButton } from './create_ml_jobs_button'; @@ -82,14 +83,17 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{ label={startTimeLabel} > - setStartTime(null)} - /> + setStartTime(null) } : undefined} + > + + - setEndTime(null)} - /> + setEndTime(null) } : undefined}> + + From 41ca5e45d60a0a707a04a31851feba1fcb53f279 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 22 Aug 2019 12:40:55 +0100 Subject: [PATCH 25/25] Remove sample data index if user has it set --- .../log_analysis/api/ml_setup_module_api.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts index a7fbd8c10f10f..5185a6f250ace 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_setup_module_api.ts @@ -12,6 +12,21 @@ import { throwErrors, createPlainError } from '../../../../../common/runtime_typ const MODULE_ID = 'logs_ui_analysis'; +// This is needed due to: https://github.com/elastic/kibana/issues/43671 +const removeSampleDataIndex = (indexPattern: string) => { + const SAMPLE_DATA_INDEX = 'kibana_sample_data_logs*'; + const indices = indexPattern.split(','); + const sampleDataIndex = indices.findIndex((index: string) => { + return index === SAMPLE_DATA_INDEX; + }); + if (sampleDataIndex > -1) { + indices.splice(sampleDataIndex, 1); + return indices.join(','); + } else { + return indexPattern; + } +}; + export const callSetupMlModuleAPI = async ( start: number | undefined, end: number | undefined, @@ -28,7 +43,7 @@ export const callSetupMlModuleAPI = async ( setupMlModuleRequestPayloadRT.encode({ start, end, - indexPatternName: indexPattern, + indexPatternName: removeSampleDataIndex(indexPattern), prefix: getJobIdPrefix(spaceId, sourceId), startDatafeed: true, jobOverrides: [