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 1/8] 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 2/8] 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 3/8] 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 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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,