From cc8035ecf942d29679f2e732699073789f92bb19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 13 Nov 2019 18:38:10 +0100 Subject: [PATCH 01/10] Rename log rate page components to be more specific --- .../plugins/infra/public/pages/logs/index.tsx | 4 ++-- .../first_use.tsx | 0 .../{analysis => log_entry_rate}/index.ts | 0 .../{analysis => log_entry_rate}/page.tsx | 14 ++++++------- .../page_content.tsx | 18 ++++++++--------- .../page_providers.tsx | 2 +- .../page_results_content.tsx | 2 +- .../page_setup_content.tsx | 20 +++++++++---------- .../page_setup_status_unknown.tsx | 2 +- .../page_unavailable_content.tsx | 2 +- .../sections/analyze_in_ml_button.tsx | 0 .../sections/anomalies/chart.tsx | 0 .../sections/anomalies/expanded_row.tsx | 0 .../sections/anomalies/index.tsx | 0 .../sections/anomalies/table.tsx | 0 .../sections/helpers/data_formatters.tsx | 0 .../sections/log_rate/bar_chart.tsx | 0 .../sections/log_rate/index.tsx | 0 .../setup/index.ts | 0 .../analysis_setup_indices_form.tsx | 0 .../analysis_setup_timerange_form.tsx | 0 .../setup/initial_configuration_step/index.ts | 0 .../initial_configuration_step.tsx | 0 .../process_step/create_ml_jobs_button.tsx | 0 .../setup/process_step/index.ts | 0 .../setup/process_step/process_step.tsx | 0 .../process_step/recreate_ml_jobs_button.tsx | 0 .../setup/setup_steps.tsx | 6 +++--- 28 files changed, 35 insertions(+), 35 deletions(-) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/first_use.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/index.ts (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page.tsx (53%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_content.tsx (76%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_providers.tsx (91%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_results_content.tsx (99%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_setup_content.tsx (84%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_setup_status_unknown.tsx (92%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/page_unavailable_content.tsx (95%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/analyze_in_ml_button.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/anomalies/chart.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/anomalies/expanded_row.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/anomalies/index.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/anomalies/table.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/helpers/data_formatters.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/log_rate/bar_chart.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/sections/log_rate/index.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/index.ts (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/initial_configuration_step/analysis_setup_indices_form.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/initial_configuration_step/analysis_setup_timerange_form.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/initial_configuration_step/index.ts (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/initial_configuration_step/initial_configuration_step.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/process_step/create_ml_jobs_button.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/process_step/index.ts (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/process_step/process_step.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/process_step/recreate_ml_jobs_button.tsx (100%) rename x-pack/legacy/plugins/infra/public/pages/logs/{analysis => log_entry_rate}/setup/setup_steps.tsx (93%) 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 895d95b1471a0..609d79e729d1d 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx @@ -21,7 +21,7 @@ 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 { LogEntryRatePage } from './log_entry_rate'; import { useLogAnalysisCapabilities, LogAnalysisCapabilities, @@ -98,7 +98,7 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag - + { +export const LogEntryRatePage = () => { return ( - - - + + + - + ); }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx similarity index 76% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_content.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index 04d7520c0ca88..808a66e040cd9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -11,12 +11,12 @@ import { isSetupStatusWithResults } from '../../../../common/log_analysis'; import { LoadingPage } from '../../../components/loading_page'; import { LogAnalysisCapabilities, LogAnalysisJobs } from '../../../containers/logs/log_analysis'; import { Source } from '../../../containers/source'; -import { AnalysisResultsContent } from './page_results_content'; -import { AnalysisSetupContent } from './page_setup_content'; -import { AnalysisUnavailableContent } from './page_unavailable_content'; -import { AnalysisSetupStatusUnknownContent } from './page_setup_status_unknown'; +import { LogEntryRateResultsContent } from './page_results_content'; +import { LogEntryRateSetupContent } from './page_setup_content'; +import { LogEntryRateUnavailableContent } from './page_unavailable_content'; +import { LogEntryRateSetupStatusUnknownContent } from './page_setup_status_unknown'; -export const AnalysisPageContent = () => { +export const LogEntryRatePageContent = () => { const { sourceId } = useContext(Source.Context); const { hasLogAnalysisCapabilites } = useContext(LogAnalysisCapabilities.Context); @@ -35,7 +35,7 @@ export const AnalysisPageContent = () => { }, []); if (!hasLogAnalysisCapabilites) { - return ; + return ; } else if (setupStatus === 'initializing') { return ( { /> ); } else if (setupStatus === 'unknown') { - return ; + return ; } else if (isSetupStatusWithResults(setupStatus)) { return ( - ); } else { return ( - { +export const LogEntryRatePageProviders: React.FunctionComponent = ({ children }) => { const { sourceId, source } = useContext(Source.Context); const spaceId = useKibanaSpaceId(); 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/log_entry_rate/page_results_content.tsx similarity index 99% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index 7fa9ff3c93db7..e600bfc66c93f 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -38,7 +38,7 @@ import { LogRateResults } from './sections/log_rate'; const JOB_STATUS_POLLING_INTERVAL = 30000; -export const AnalysisResultsContent = ({ +export const LogEntryRateResultsContent = ({ sourceId, isFirstUse, }: { 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/log_entry_rate/page_setup_content.tsx similarity index 84% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx index 097cccf5dca33..6fe248acc5d62 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx @@ -20,7 +20,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { SetupStatus } from '../../../../common/log_analysis'; import { useTrackPageview } from '../../../hooks/use_track_metric'; -import { AnalysisSetupSteps } from './setup'; +import { LogEntryRateSetupSteps } from './setup'; type SetupHandler = ( indices: string[], @@ -28,7 +28,7 @@ type SetupHandler = ( endTime: number | undefined ) => void; -interface AnalysisSetupContentProps { +interface LogEntryRateSetupContentProps { availableIndices: string[]; cleanupAndSetup: SetupHandler; errorMessages: string[]; @@ -37,7 +37,7 @@ interface AnalysisSetupContentProps { viewResults: () => void; } -export const AnalysisSetupContent: React.FunctionComponent = ({ +export const LogEntryRateSetupContent: React.FunctionComponent = ({ availableIndices, cleanupAndSetup, errorMessages, @@ -49,9 +49,9 @@ export const AnalysisSetupContent: React.FunctionComponent + - - - + - + ); }; // !important due to https://github.com/elastic/eui/issues/2232 -const AnalysisPageContent = euiStyled(EuiPageContent)` +const LogEntryRateSetupPageContent = euiStyled(EuiPageContent)` max-width: 768px !important; `; -const AnalysisSetupPage = euiStyled(EuiPage)` +const LogEntryRateSetupPage = euiStyled(EuiPage)` height: 100%; `; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_status_unknown.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx similarity index 92% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_status_unknown.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx index 953b0841ffe92..4c685bd42b937 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_setup_status_unknown.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx @@ -14,7 +14,7 @@ interface Props { retry: () => void; } -export const AnalysisSetupStatusUnknownContent: React.FunctionComponent = ({ +export const LogEntryRateSetupStatusUnknownContent: React.FunctionComponent = ({ retry, }: Props) => ( = () => ( +export const LogEntryRateUnavailableContent: React.FunctionComponent<{}> = () => ( diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/analyze_in_ml_button.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/analyze_in_ml_button.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/analyze_in_ml_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/chart.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/chart.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/expanded_row.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/table.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/helpers/data_formatters.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/helpers/data_formatters.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/bar_chart.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/bar_chart.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/bar_chart.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/index.ts b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/index.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/index.ts rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/index.ts diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_indices_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_indices_form.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_timerange_form.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_timerange_form.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/index.ts b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/index.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/index.ts rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/index.ts diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/initial_configuration_step.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/initial_configuration_step.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/initial_configuration_step.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/initial_configuration_step.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/create_ml_jobs_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/create_ml_jobs_button.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/create_ml_jobs_button.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/create_ml_jobs_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/index.ts b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/index.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/index.ts rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/index.ts diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/process_step.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/process_step.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/process_step.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/process_step.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/recreate_ml_jobs_button.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/recreate_ml_jobs_button.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/process_step/recreate_ml_jobs_button.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/recreate_ml_jobs_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/setup_steps.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx similarity index 93% rename from x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/setup_steps.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx index aebb44d4c9372..073b12560bd13 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/setup_steps.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx @@ -19,7 +19,7 @@ type SetupHandler = ( endTime: number | undefined ) => void; -interface AnalysisSetupStepsProps { +interface LogEntryRateSetupStepsProps { availableIndices: string[]; cleanupAndSetup: SetupHandler; errorMessages: string[]; @@ -28,14 +28,14 @@ interface AnalysisSetupStepsProps { viewResults: () => void; } -export const AnalysisSetupSteps: React.FunctionComponent = ({ +export const LogEntryRateSetupSteps: React.FunctionComponent = ({ availableIndices, cleanupAndSetup: cleanupAndSetupModule, errorMessages, setup: setupModule, setupStatus, viewResults, -}: AnalysisSetupStepsProps) => { +}: LogEntryRateSetupStepsProps) => { const { setup, cleanupAndSetup, From a2d319e50de2f2f80fa7fa73bb5d549bf21dd658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 14 Nov 2019 16:15:28 +0100 Subject: [PATCH 02/10] Introduce specific useLogEntryRateJobs hook --- .../common/log_analysis/job_parameters.ts | 6 ++-- .../logs/log_analysis/log_analysis_jobs.tsx | 27 +++++++------- .../infra/public/containers/source/index.ts | 2 +- .../infra/public/containers/source/source.tsx | 1 + .../logs/log_entry_rate/page_content.tsx | 5 +-- .../logs/log_entry_rate/page_providers.tsx | 12 +++---- .../log_entry_rate/page_results_content.tsx | 6 ++-- .../use_log_entry_rate_jobs.tsx | 36 +++++++++++++++++++ 8 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx 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 5cfe38394a2ce..59694d25b7259 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 @@ -4,17 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -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) => +export const getJobId = (spaceId: string, sourceId: string, jobType: string) => `${getJobIdPrefix(spaceId, sourceId)}${jobType}`; -export const getDatafeedId = (spaceId: string, sourceId: string, jobType: JobType) => +export const getDatafeedId = (spaceId: string, sourceId: string, jobType: string) => `datafeed-${getJobId(spaceId, sourceId, jobType)}`; export const getAllModuleJobIds = (spaceId: string, sourceId: string) => [ 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 163f0e39d1228..d5eebf7a2228a 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 @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import createContainer from 'constate'; import { useMemo, useCallback, useEffect } from 'react'; import { callGetMlModuleAPI } from './api/ml_get_module'; @@ -15,15 +14,17 @@ import { callSetupMlModuleAPI, SetupMlModuleResponsePayload } from './api/ml_set import { useLogAnalysisCleanup } from './log_analysis_cleanup'; import { useStatusState } from './log_analysis_status_state'; -const MODULE_ID = 'logs_ui_analysis'; - -export const useLogAnalysisJobs = ({ +export const useLogAnalysisJobs = ({ indexPattern, + jobTypes, + moduleId, sourceId, spaceId, timeField, }: { indexPattern: string; + jobTypes: JobType[]; + moduleId: string; sourceId: string; spaceId: string; timeField: string; @@ -40,7 +41,7 @@ export const useLogAnalysisJobs = ({ cancelPreviousOn: 'resolution', createPromise: async () => { dispatch({ type: 'fetchingModuleDefinition' }); - return await callGetMlModuleAPI(MODULE_ID); + return await callGetMlModuleAPI(moduleId); }, onResolve: response => { dispatch({ @@ -67,7 +68,7 @@ export const useLogAnalysisJobs = ({ ) => { dispatch({ type: 'startedSetup' }); return await callSetupMlModuleAPI( - MODULE_ID, + moduleId, start, end, spaceId, @@ -143,10 +144,14 @@ export const useLogAnalysisJobs = ({ }, [fetchModuleDefinition]); const jobIds = useMemo(() => { - return { - 'log-entry-rate': getJobId(spaceId, sourceId, 'log-entry-rate'), - }; - }, [sourceId, spaceId]); + return jobTypes.reduce( + (accumulatedJobIds, jobType) => ({ + ...accumulatedJobIds, + [jobType]: getJobId(spaceId, sourceId, jobType), + }), + {} as Record + ); + }, [jobTypes, sourceId, spaceId]); return { availableIndices, @@ -164,5 +169,3 @@ export const useLogAnalysisJobs = ({ jobIds, }; }; - -export const LogAnalysisJobs = createContainer(useLogAnalysisJobs); diff --git a/x-pack/legacy/plugins/infra/public/containers/source/index.ts b/x-pack/legacy/plugins/infra/public/containers/source/index.ts index 9442836f2a6c6..5911decf21774 100644 --- a/x-pack/legacy/plugins/infra/public/containers/source/index.ts +++ b/x-pack/legacy/plugins/infra/public/containers/source/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { Source, useSource } from './source'; +export * from './source'; diff --git a/x-pack/legacy/plugins/infra/public/containers/source/source.tsx b/x-pack/legacy/plugins/infra/public/containers/source/source.tsx index 955529c9759c4..4729f7aa31f0b 100644 --- a/x-pack/legacy/plugins/infra/public/containers/source/source.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/source/source.tsx @@ -176,3 +176,4 @@ export const useSource = ({ sourceId }: { sourceId: string }) => { }; export const Source = createContainer(useSource); +export const [SourceProvider, useSourceContext] = Source; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index 808a66e040cd9..117253fb5ed94 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -9,12 +9,13 @@ import React, { useContext, useEffect } from 'react'; import { isSetupStatusWithResults } from '../../../../common/log_analysis'; import { LoadingPage } from '../../../components/loading_page'; -import { LogAnalysisCapabilities, LogAnalysisJobs } from '../../../containers/logs/log_analysis'; +import { LogAnalysisCapabilities } from '../../../containers/logs/log_analysis'; import { Source } from '../../../containers/source'; import { LogEntryRateResultsContent } from './page_results_content'; import { LogEntryRateSetupContent } from './page_setup_content'; import { LogEntryRateUnavailableContent } from './page_unavailable_content'; import { LogEntryRateSetupStatusUnknownContent } from './page_setup_status_unknown'; +import { useLogEntryRateJobsContext } from './use_log_entry_rate_jobs'; export const LogEntryRatePageContent = () => { const { sourceId } = useContext(Source.Context); @@ -28,7 +29,7 @@ export const LogEntryRatePageContent = () => { setup, setupStatus, viewResults, - } = useContext(LogAnalysisJobs.Context); + } = useLogEntryRateJobsContext(); useEffect(() => { fetchJobStatus(); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx index 26cede333c1b4..dad7fa1e4cb02 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx @@ -4,24 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useContext } from 'react'; +import React from 'react'; -import { LogAnalysisJobs } from '../../../containers/logs/log_analysis'; -import { Source } from '../../../containers/source'; +import { useSourceContext } from '../../../containers/source'; import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; +import { LogEntryRateJobsProvider } from './use_log_entry_rate_jobs'; export const LogEntryRatePageProviders: React.FunctionComponent = ({ children }) => { - const { sourceId, source } = useContext(Source.Context); + const { sourceId, source } = useSourceContext(); const spaceId = useKibanaSpaceId(); return ( - {children} - + ); }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index e600bfc66c93f..8cc2170cac1ea 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -17,14 +17,13 @@ import { import numeral from '@elastic/numeral'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; -import React, { useCallback, useContext, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { TimeRange } from '../../../../common/http_api/shared/time_range'; import { bucketSpan } from '../../../../common/log_analysis'; import { LoadingOverlayWrapper } from '../../../components/loading_overlay_wrapper'; import { - LogAnalysisJobs, StringTimeRange, useLogAnalysisResults, useLogAnalysisResultsUrlState, @@ -35,6 +34,7 @@ import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; import { FirstUseCallout } from './first_use'; import { AnomaliesResults } from './sections/anomalies'; import { LogRateResults } from './sections/log_rate'; +import { useLogEntryRateJobsContext } from './use_log_entry_rate_jobs'; const JOB_STATUS_POLLING_INTERVAL = 30000; @@ -145,7 +145,7 @@ export const LogEntryRateResultsContent = ({ viewSetupForReconfiguration, viewSetupForUpdate, jobIds, - } = useContext(LogAnalysisJobs.Context); + } = useLogEntryRateJobsContext(); useInterval(() => { fetchJobStatus(); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx new file mode 100644 index 0000000000000..1ab02906d2955 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx @@ -0,0 +1,36 @@ +/* + * 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'; + +import { useLogAnalysisJobs } from '../../../containers/logs/log_analysis'; + +const jobTypes = ['log-entry-rate']; + +export const useLogEntryRateJobs = ({ + indexPattern, + sourceId, + spaceId, + timeField, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; + timeField: string; +}) => { + return useLogAnalysisJobs({ + indexPattern, + jobTypes, + moduleId: 'logs_ui_analysis', + sourceId, + spaceId, + timeField, + }); +}; + +export const [LogEntryRateJobsProvider, useLogEntryRateJobsContext] = createContainer( + useLogEntryRateJobs +); From 3344f326bc994e0843092db17a9765991fdd57b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Tue, 19 Nov 2019 22:59:47 +0100 Subject: [PATCH 03/10] Move log rate result hooks into the pages dirs --- .../log_analysis/results/log_entry_rate.ts | 12 ++- .../containers/logs/log_analysis/index.ts | 2 - .../logs/log_analysis/log_entry_rate.tsx | 50 ------------ .../log_entry_rate/page_results_content.tsx | 69 +++++++++------- .../sections/anomalies/expanded_row.tsx | 4 +- .../sections/anomalies/index.tsx | 4 +- .../sections/anomalies/table.tsx | 4 +- .../sections/helpers/data_formatters.tsx | 26 ++++--- .../sections/log_rate/index.tsx | 2 +- .../service_calls}/get_log_entry_rate.ts | 0 .../use_log_entry_rate_results.ts} | 78 ++++++++++--------- .../use_log_entry_rate_results_url_state.tsx} | 7 +- 12 files changed, 113 insertions(+), 145 deletions(-) delete mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_entry_rate.tsx rename x-pack/legacy/plugins/infra/public/{containers/logs/log_analysis/api => pages/logs/log_entry_rate/service_calls}/get_log_entry_rate.ts (100%) rename x-pack/legacy/plugins/infra/public/{containers/logs/log_analysis/log_analysis_results.tsx => pages/logs/log_entry_rate/use_log_entry_rate_results.ts} (58%) rename x-pack/legacy/plugins/infra/public/{containers/logs/log_analysis/log_analysis_results_url_state.tsx => pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx} (96%) diff --git a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/results/log_entry_rate.ts b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/results/log_entry_rate.ts index 5a1412fd8f3d4..dfc3d2aabd11a 100644 --- a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/results/log_entry_rate.ts +++ b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/results/log_entry_rate.ts @@ -29,7 +29,7 @@ export type GetLogEntryRateRequestPayload = rt.TypeOf; + +export const logEntryRateHistogramBucketRT = rt.type({ partitions: rt.array(logEntryRatePartitionRT), startTime: rt.number, }); +export type LogEntryRateHistogramBucket = rt.TypeOf; + export const getLogEntryRateSuccessReponsePayloadRT = rt.type({ data: rt.type({ bucketDuration: rt.number, - histogramBuckets: rt.array(logEntryRateHistogramBucket), + histogramBuckets: rt.array(logEntryRateHistogramBucketRT), totalNumberOfLogEntries: rt.number, }), }); 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 cbe3b2ef1e9b8..247387a2a583e 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 @@ -7,6 +7,4 @@ export * from './log_analysis_capabilities'; export * from './log_analysis_cleanup'; export * from './log_analysis_jobs'; -export * from './log_analysis_results'; -export * from './log_analysis_results_url_state'; export * from './log_analysis_status_state'; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_entry_rate.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_entry_rate.tsx deleted file mode 100644 index 8b21a7e829894..0000000000000 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_entry_rate.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 } from 'react'; - -import { GetLogEntryRateSuccessResponsePayload } from '../../../../common/http_api/log_analysis'; -import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { callGetLogEntryRateAPI } from './api/get_log_entry_rate'; - -type LogEntryRateResults = GetLogEntryRateSuccessResponsePayload['data']; - -export const useLogEntryRate = ({ - sourceId, - startTime, - endTime, - bucketDuration, -}: { - sourceId: string; - startTime: number; - endTime: number; - bucketDuration: number; -}) => { - const [logEntryRate, setLogEntryRate] = useState(null); - - const [getLogEntryRateRequest, getLogEntryRate] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - return await callGetLogEntryRateAPI(sourceId, startTime, endTime, bucketDuration); - }, - onResolve: response => { - setLogEntryRate(response.data); - }, - }, - [sourceId, startTime, endTime, bucketDuration] - ); - - const isLoading = useMemo(() => getLogEntryRateRequest.state === 'pending', [ - getLogEntryRateRequest.state, - ]); - - return { - getLogEntryRate, - isLoading, - logEntryRate, - }; -}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index 8cc2170cac1ea..aaef8f5ed6f8c 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -17,17 +17,12 @@ import { import numeral from '@elastic/numeral'; import { FormattedMessage } from '@kbn/i18n/react'; import moment from 'moment'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState, useEffect } from 'react'; import euiStyled from '../../../../../../common/eui_styled_components'; import { TimeRange } from '../../../../common/http_api/shared/time_range'; import { bucketSpan } from '../../../../common/log_analysis'; import { LoadingOverlayWrapper } from '../../../components/loading_overlay_wrapper'; -import { - StringTimeRange, - useLogAnalysisResults, - useLogAnalysisResultsUrlState, -} from '../../../containers/logs/log_analysis'; import { useInterval } from '../../../hooks/use_interval'; import { useTrackPageview } from '../../../hooks/use_track_metric'; import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; @@ -35,6 +30,11 @@ import { FirstUseCallout } from './first_use'; import { AnomaliesResults } from './sections/anomalies'; import { LogRateResults } from './sections/log_rate'; import { useLogEntryRateJobsContext } from './use_log_entry_rate_jobs'; +import { useLogEntryRateResults } from './use_log_entry_rate_results'; +import { + StringTimeRange, + useLogAnalysisResultsUrlState, +} from './use_log_entry_rate_results_url_state'; const JOB_STATUS_POLLING_INTERVAL = 30000; @@ -65,32 +65,20 @@ export const LogEntryRateResultsContent = ({ lastChangedTime: Date.now(), })); - const bucketDuration = useMemo(() => { - // This function takes the current time range in ms, - // works out the bucket interval we'd need to always - // display 100 data points, and then takes that new - // value and works out the nearest multiple of - // 900000 (15 minutes) to it, so that we don't end up with - // jaggy bucket boundaries between the ML buckets and our - // aggregation buckets. - const msRange = moment(queryTimeRange.value.endTime).diff( - moment(queryTimeRange.value.startTime) - ); - const bucketIntervalInMs = msRange / 100; - const result = bucketSpan * Math.round(bucketIntervalInMs / bucketSpan); - const roundedResult = parseInt(Number(result).toFixed(0), 10); - return roundedResult < bucketSpan ? bucketSpan : roundedResult; - }, [queryTimeRange.value.startTime, queryTimeRange.value.endTime]); + const bucketDuration = useMemo( + () => getBucketDuration(queryTimeRange.value.startTime, queryTimeRange.value.endTime), + [queryTimeRange.value.endTime, queryTimeRange.value.startTime] + ); - const { isLoading, logRateResults } = useLogAnalysisResults({ + const { getLogEntryRate, isLoading, logEntryRate } = useLogEntryRateResults({ sourceId, startTime: queryTimeRange.value.startTime, endTime: queryTimeRange.value.endTime, bucketDuration, - lastRequestTime: queryTimeRange.lastChangedTime, }); - const hasResults = useMemo(() => logRateResults && logRateResults.histogramBuckets.length > 0, [ - logRateResults, + + const hasResults = useMemo(() => (logEntryRate?.histogramBuckets?.length ?? 0) > 0, [ + logEntryRate, ]); const handleQueryTimeRangeChange = useCallback( @@ -147,6 +135,10 @@ export const LogEntryRateResultsContent = ({ jobIds, } = useLogEntryRateJobsContext(); + useEffect(() => { + getLogEntryRate(); + }, [getLogEntryRate, queryTimeRange.lastChangedTime]); + useInterval(() => { fetchJobStatus(); }, JOB_STATUS_POLLING_INTERVAL); @@ -168,7 +160,7 @@ export const LogEntryRateResultsContent = ({ - {logRateResults ? ( + {logEntryRate ? ( - {numeral(logRateResults.totalNumberOfLogEntries).format('0.00a')} + {numeral(logEntryRate.totalNumberOfLogEntries).format('0.00a')} ), @@ -210,7 +202,7 @@ export const LogEntryRateResultsContent = ({ {isFirstUse && !hasResults ? : null} @@ -223,7 +215,7 @@ export const LogEntryRateResultsContent = ({ jobStatus={jobStatus['log-entry-rate']} viewSetupForReconfiguration={viewSetupForReconfiguration} viewSetupForUpdate={viewSetupForUpdate} - results={logRateResults} + results={logEntryRate} setTimeRange={handleChartTimeRangeChange} setupStatus={setupStatus} timeRange={queryTimeRange.value} @@ -250,6 +242,23 @@ const stringToNumericTimeRange = (timeRange: StringTimeRange): TimeRange => ({ ).valueOf(), }); +/** + * This function takes the current time range in ms, + * works out the bucket interval we'd need to always + * display 100 data points, and then takes that new + * value and works out the nearest multiple of + * 900000 (15 minutes) to it, so that we don't end up with + * jaggy bucket boundaries between the ML buckets and our + * aggregation buckets. + */ +const getBucketDuration = (startTime: number, endTime: number) => { + const msRange = moment(endTime).diff(moment(startTime)); + const bucketIntervalInMs = msRange / 100; + const result = bucketSpan * Math.round(bucketIntervalInMs / bucketSpan); + const roundedResult = parseInt(Number(result).toFixed(0), 10); + return roundedResult < bucketSpan ? bucketSpan : roundedResult; +}; + // This is needed due to the flex-basis: 100% !important; rule that // kicks in on small screens via media queries breaking when using direction="column" export const ResultsContentPage = euiStyled(EuiPage)` diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx index 0586f5282ddf7..c4a39f64d2b11 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import numeral from '@elastic/numeral'; import { EuiFlexGroup, EuiFlexItem, EuiStat, EuiSpacer } from '@elastic/eui'; import { AnomaliesChart } from './chart'; -import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results'; +import { LogEntryRateResults } from '../../use_log_entry_rate_results'; import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; import { getLogEntryRateSeriesForPartition, @@ -21,7 +21,7 @@ import { AnalyzeInMlButton } from '../analyze_in_ml_button'; export const AnomaliesTableExpandedRow: React.FunctionComponent<{ partitionId: string; topAnomalyScore: number; - results: LogRateResults; + results: LogEntryRateResults; setTimeRange: (timeRange: TimeRange) => void; timeRange: TimeRange; jobId: string; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx index e870c2d442719..4b8affb332ded 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx @@ -18,7 +18,7 @@ import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; import euiStyled from '../../../../../../../../common/eui_styled_components'; -import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results'; +import { LogEntryRateResults } from '../../use_log_entry_rate_results'; import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; import { JobStatus, SetupStatus } from '../../../../../../common/log_analysis'; import { @@ -36,7 +36,7 @@ import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay export const AnomaliesResults: React.FunctionComponent<{ isLoading: boolean; jobStatus: JobStatus; - results: LogRateResults | null; + results: LogEntryRateResults | null; setTimeRange: (timeRange: TimeRange) => void; setupStatus: SetupStatus; timeRange: TimeRange; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx index c0016d07c290b..2057d75f72354 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/table.tsx @@ -9,7 +9,7 @@ import { EuiBasicTable, EuiButtonIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; -import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results'; +import { LogEntryRateResults } from '../../use_log_entry_rate_results'; import { AnomaliesTableExpandedRow } from './expanded_row'; import { formatAnomalyScore, getFriendlyNameForPartitionId } from '../helpers/data_formatters'; import euiStyled from '../../../../../../../../common/eui_styled_components'; @@ -50,7 +50,7 @@ const maxAnomalyScoreColumnName = i18n.translate( ); export const AnomaliesTable: React.FunctionComponent<{ - results: LogRateResults; + results: LogEntryRateResults; setTimeRange: (timeRange: TimeRange) => void; timeRange: TimeRange; jobId: string; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx index 74a3b5f80a577..f9b85fc4e20c2 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/helpers/data_formatters.tsx @@ -6,18 +6,19 @@ import { RectAnnotationDatum } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import { LogRateResults } from '../../../../../containers/logs/log_analysis/log_analysis_results'; -export type MLSeverityScoreCategories = 'warning' | 'minor' | 'major' | 'critical'; -type MLSeverityScores = Record; -const ML_SEVERITY_SCORES: MLSeverityScores = { +import { LogEntryRateResults } from '../../use_log_entry_rate_results'; + +const ML_SEVERITY_SCORES = { warning: 3, minor: 25, major: 50, critical: 75, }; -export const getLogEntryRatePartitionedSeries = (results: LogRateResults) => { +export type MLSeverityScoreCategories = keyof typeof ML_SEVERITY_SCORES; + +export const getLogEntryRatePartitionedSeries = (results: LogEntryRateResults) => { return results.histogramBuckets.reduce>( (buckets, bucket) => { return [ @@ -33,7 +34,7 @@ export const getLogEntryRatePartitionedSeries = (results: LogRateResults) => { ); }; -export const getLogEntryRateCombinedSeries = (results: LogRateResults) => { +export const getLogEntryRateCombinedSeries = (results: LogEntryRateResults) => { return results.histogramBuckets.reduce>( (buckets, bucket) => { return [ @@ -50,7 +51,10 @@ export const getLogEntryRateCombinedSeries = (results: LogRateResults) => { ); }; -export const getLogEntryRateSeriesForPartition = (results: LogRateResults, partitionId: string) => { +export const getLogEntryRateSeriesForPartition = ( + results: LogEntryRateResults, + partitionId: string +) => { return results.partitionBuckets[partitionId].buckets.reduce< Array<{ time: number; value: number }> >((buckets, bucket) => { @@ -64,7 +68,7 @@ export const getLogEntryRateSeriesForPartition = (results: LogRateResults, parti }, []); }; -export const getAnnotationsForPartition = (results: LogRateResults, partitionId: string) => { +export const getAnnotationsForPartition = (results: LogEntryRateResults, partitionId: string) => { return results.partitionBuckets[partitionId].buckets.reduce< Record >( @@ -106,13 +110,13 @@ export const getAnnotationsForPartition = (results: LogRateResults, partitionId: }; export const getTotalNumberOfLogEntriesForPartition = ( - results: LogRateResults, + results: LogEntryRateResults, partitionId: string ) => { return results.partitionBuckets[partitionId].totalNumberOfLogEntries; }; -export const getAnnotationsForAll = (results: LogRateResults) => { +export const getAnnotationsForAll = (results: LogEntryRateResults) => { return results.histogramBuckets.reduce>( (annotatedBucketsBySeverity, bucket) => { const maxAnomalyScoresByPartition = bucket.partitions.reduce< @@ -169,7 +173,7 @@ export const getAnnotationsForAll = (results: LogRateResults) => { ); }; -export const getTopAnomalyScoreAcrossAllPartitions = (results: LogRateResults) => { +export const getTopAnomalyScoreAcrossAllPartitions = (results: LogEntryRateResults) => { const allTopScores = Object.values(results.partitionBuckets).reduce( (scores: number[], partition) => { return [...scores, partition.topAnomalyScore]; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx index 44805520f3b9e..a11dc9d4d607a 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx @@ -8,7 +8,7 @@ import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle, EuiText } from import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; -import { LogRateResults as Results } from '../../../../../containers/logs/log_analysis/log_analysis_results'; +import { LogEntryRateResults as Results } from '../../use_log_entry_rate_results'; import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; import { LogEntryRateBarChart } from './bar_chart'; import { getLogEntryRatePartitionedSeries } from '../helpers/data_formatters'; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/get_log_entry_rate.ts b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_rate.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/get_log_entry_rate.ts rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_rate.ts diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results.ts similarity index 58% rename from x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results.ts index 81a80fb565a4b..de2b873001cce 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results.ts @@ -4,75 +4,77 @@ * you may not use this file except in compliance with the Elastic License. */ -import createContainer from 'constate'; -import { useMemo, useEffect } from 'react'; +import { useMemo, useState } from 'react'; -import { useLogEntryRate } from './log_entry_rate'; -import { GetLogEntryRateSuccessResponsePayload } from '../../../../common/http_api/log_analysis'; +import { + GetLogEntryRateSuccessResponsePayload, + LogEntryRateHistogramBucket, + LogEntryRatePartition, +} from '../../../../common/http_api/log_analysis'; +import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { callGetLogEntryRateAPI } from './service_calls/get_log_entry_rate'; -type PartitionBucket = { +type PartitionBucket = LogEntryRatePartition & { startTime: number; -} & GetLogEntryRateSuccessResponsePayload['data']['histogramBuckets'][0]['partitions'][0]; +}; type PartitionRecord = Record< string, { buckets: PartitionBucket[]; topAnomalyScore: number; totalNumberOfLogEntries: number } >; -export interface LogRateResults { +export interface LogEntryRateResults { bucketDuration: number; totalNumberOfLogEntries: number; - histogramBuckets: GetLogEntryRateSuccessResponsePayload['data']['histogramBuckets']; + histogramBuckets: LogEntryRateHistogramBucket[]; partitionBuckets: PartitionRecord; } -export const useLogAnalysisResults = ({ +export const useLogEntryRateResults = ({ sourceId, startTime, endTime, bucketDuration = 15 * 60 * 1000, - lastRequestTime, }: { sourceId: string; startTime: number; endTime: number; - bucketDuration?: number; - lastRequestTime: number; + bucketDuration: number; }) => { - const { isLoading: isLoadingLogEntryRate, logEntryRate, getLogEntryRate } = useLogEntryRate({ - sourceId, - startTime, - endTime, - bucketDuration, - }); - - const isLoading = useMemo(() => isLoadingLogEntryRate, [isLoadingLogEntryRate]); + const [logEntryRate, setLogEntryRate] = useState(null); - useEffect(() => { - getLogEntryRate(); - }, [sourceId, startTime, endTime, bucketDuration, lastRequestTime]); + const [getLogEntryRateRequest, getLogEntryRate] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await callGetLogEntryRateAPI(sourceId, startTime, endTime, bucketDuration); + }, + onResolve: ({ data }) => { + setLogEntryRate({ + bucketDuration: data.bucketDuration, + totalNumberOfLogEntries: data.totalNumberOfLogEntries, + histogramBuckets: data.histogramBuckets, + partitionBuckets: formatLogEntryRateResultsByPartition(data), + }); + }, + onReject: () => { + setLogEntryRate(null); + }, + }, + [sourceId, startTime, endTime, bucketDuration] + ); - const logRateResults: LogRateResults | null = useMemo(() => { - if (logEntryRate) { - return { - bucketDuration: logEntryRate.bucketDuration, - totalNumberOfLogEntries: logEntryRate.totalNumberOfLogEntries, - histogramBuckets: logEntryRate.histogramBuckets, - partitionBuckets: formatLogEntryRateResultsByPartition(logEntryRate), - }; - } else { - return null; - } - }, [logEntryRate]); + const isLoading = useMemo(() => getLogEntryRateRequest.state === 'pending', [ + getLogEntryRateRequest.state, + ]); return { + getLogEntryRate, isLoading, - logRateResults, + logEntryRate, }; }; -export const LogAnalysisResults = createContainer(useLogAnalysisResults); - const formatLogEntryRateResultsByPartition = ( results: GetLogEntryRateSuccessResponsePayload['data'] ): PartitionRecord => { diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results_url_state.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx similarity index 96% rename from x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results_url_state.tsx rename to x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx index 19fb7f238fc04..017be6be49e16 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_results_url_state.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_results_url_state.tsx @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useEffect } from 'react'; -import * as rt from 'io-ts'; -import { identity, constant } from 'fp-ts/lib/function'; import { fold } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; +import * as rt from 'io-ts'; +import { useEffect } from 'react'; + import { useUrlState } from '../../../utils/use_url_state'; const autoRefreshRT = rt.union([ From 222df2ac7f1a54bb00ea2bd1f762a6af0246afb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 20 Nov 2019 12:04:17 +0100 Subject: [PATCH 04/10] Move ml link button to common components dir --- .../analyze_in_ml_button.tsx | 9 ++++---- .../logging/log_analysis_results/index.ts | 7 ++++++ .../sections/anomalies/expanded_row.tsx | 23 +++++++++---------- .../sections/anomalies/index.tsx | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) rename x-pack/legacy/plugins/infra/public/{pages/logs/log_entry_rate/sections => components/logging/log_analysis_results}/analyze_in_ml_button.tsx (96%) create mode 100644 x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/index.ts diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/analyze_in_ml_button.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx similarity index 96% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/analyze_in_ml_button.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx index ef81f229034bd..c5d83e1c205cc 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/analyze_in_ml_button.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/analyze_in_ml_button.tsx @@ -4,14 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import url from 'url'; import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import React from 'react'; +import { encode } from 'rison-node'; import chrome from 'ui/chrome'; import { QueryString } from 'ui/utils/query_string'; -import { encode } from 'rison-node'; -import { TimeRange } from '../../../../../common/http_api/shared/time_range'; +import url from 'url'; + +import { TimeRange } from '../../../../common/http_api/shared/time_range'; export const AnalyzeInMlButton: React.FunctionComponent<{ jobId: string; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/index.ts b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/index.ts new file mode 100644 index 0000000000000..8a4ceb70252a3 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_results/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 './analyze_in_ml_button'; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx index c4a39f64d2b11..f8a7f12364cf9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/expanded_row.tsx @@ -4,19 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiStat } from '@elastic/eui'; import numeral from '@elastic/numeral'; -import { EuiFlexGroup, EuiFlexItem, EuiStat, EuiSpacer } from '@elastic/eui'; -import { AnomaliesChart } from './chart'; -import { LogEntryRateResults } from '../../use_log_entry_rate_results'; +import { i18n } from '@kbn/i18n'; +import React, { useMemo } from 'react'; + import { TimeRange } from '../../../../../../common/http_api/shared/time_range'; +import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results'; +import { LogEntryRateResults } from '../../use_log_entry_rate_results'; import { - getLogEntryRateSeriesForPartition, getAnnotationsForPartition, + getLogEntryRateSeriesForPartition, getTotalNumberOfLogEntriesForPartition, } from '../helpers/data_formatters'; -import { AnalyzeInMlButton } from '../analyze_in_ml_button'; +import { AnomaliesChart } from './chart'; export const AnomaliesTableExpandedRow: React.FunctionComponent<{ partitionId: string; @@ -28,14 +29,12 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{ }> = ({ results, timeRange, setTimeRange, partitionId, jobId }) => { const logEntryRateSeries = useMemo( () => - results && results.histogramBuckets - ? getLogEntryRateSeriesForPartition(results, partitionId) - : [], + results?.histogramBuckets ? getLogEntryRateSeriesForPartition(results, partitionId) : [], [results, partitionId] ); const anomalyAnnotations = useMemo( () => - results && results.histogramBuckets + results?.histogramBuckets ? getAnnotationsForPartition(results, partitionId) : { warning: [], @@ -47,7 +46,7 @@ export const AnomaliesTableExpandedRow: React.FunctionComponent<{ ); const totalNumberOfLogEntries = useMemo( () => - results && results.histogramBuckets + results?.histogramBuckets ? getTotalNumberOfLogEntriesForPartition(results, partitionId) : undefined, [results, partitionId] diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx index 4b8affb332ded..38aa4b068c9e9 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx @@ -30,7 +30,7 @@ import { import { AnomaliesChart } from './chart'; import { AnomaliesTable } from './table'; import { LogAnalysisJobProblemIndicator } from '../../../../../components/logging/log_analysis_job_status'; -import { AnalyzeInMlButton } from '../analyze_in_ml_button'; +import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results'; import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; export const AnomaliesResults: React.FunctionComponent<{ From 32075b6a21281f9989af463544e7dc2fed00424e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 20 Nov 2019 20:08:09 +0100 Subject: [PATCH 05/10] Remove most job specifics from setup state hook --- .../log_analysis/api/ml_setup_module_api.ts | 77 ++++---- .../logs/log_analysis/log_analysis_jobs.tsx | 31 ++- .../log_analysis_status_state.tsx | 185 +++++++++++------- .../use_log_entry_rate_jobs.tsx | 4 +- 4 files changed, 181 insertions(+), 116 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 1c937513c7950..f80e875ab587f 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,7 +12,7 @@ import { kfetch } from 'ui/kfetch'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; import { getJobIdPrefix } from '../../../../../common/log_analysis'; -import { jobCustomSettingsRT } from './ml_api_types'; +// import { jobCustomSettingsRT } from './ml_api_types'; export const callSetupMlModuleAPI = async ( moduleId: string, @@ -21,8 +21,8 @@ export const callSetupMlModuleAPI = async ( spaceId: string, sourceId: string, indexPattern: string, - timeField: string, - bucketSpan: number + jobOverrides: SetupMlModuleJobOverrides[] = [], + datafeedOverrides: SetupMlModuleDatafeedOverrides[] = [] ) => { const response = await kfetch({ method: 'POST', @@ -34,25 +34,27 @@ export const callSetupMlModuleAPI = async ( indexPatternName: indexPattern, prefix: getJobIdPrefix(spaceId, sourceId), startDatafeed: true, - jobOverrides: [ - { - job_id: 'log-entry-rate' as const, - analysis_config: { - bucket_span: `${bucketSpan}ms`, - }, - data_description: { - time_field: timeField, - }, - custom_settings: { - logs_source_config: { - indexPattern, - timestampField: timeField, - bucketSpan, - }, - }, - }, - ], - datafeedOverrides: [], + jobOverrides, + datafeedOverrides, + // jobOverrides: [ + // { + // job_id: 'log-entry-rate' as const, + // analysis_config: { + // bucket_span: `${bucketSpan}ms`, + // }, + // data_description: { + // time_field: timeField, + // }, + // custom_settings: { + // logs_source_config: { + // indexPattern, + // timestampField: timeField, + // bucketSpan, + // }, + // }, + // }, + // ], + // datafeedOverrides: [], }) ), }); @@ -68,23 +70,30 @@ const setupMlModuleTimeParamsRT = rt.partial({ end: rt.number, }); -const setupMlModuleLogEntryRateJobOverridesRT = rt.type({ - job_id: rt.literal('log-entry-rate'), - analysis_config: rt.type({ - bucket_span: rt.string, - }), - data_description: rt.type({ - time_field: rt.string, - }), - custom_settings: jobCustomSettingsRT, -}); +const setupMlModuleJobOverridesRT = rt.object; + +type SetupMlModuleJobOverrides = rt.TypeOf; + +const setupMlModuleDatafeedOverridesRT = rt.object; + +type SetupMlModuleDatafeedOverrides = rt.TypeOf; +// const setupMlModuleLogEntryRateJobOverridesRT = rt.type({ +// job_id: rt.literal('log-entry-rate'), +// analysis_config: rt.type({ +// bucket_span: rt.string, +// }), +// data_description: rt.type({ +// time_field: rt.string, +// }), +// custom_settings: jobCustomSettingsRT, +// }); const setupMlModuleRequestParamsRT = rt.type({ indexPatternName: rt.string, prefix: rt.string, startDatafeed: rt.boolean, - jobOverrides: rt.array(setupMlModuleLogEntryRateJobOverridesRT), - datafeedOverrides: rt.array(rt.object), + jobOverrides: rt.array(setupMlModuleJobOverridesRT), + datafeedOverrides: rt.array(setupMlModuleDatafeedOverridesRT), }); const setupMlModuleRequestPayloadRT = rt.intersection([ 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 d5eebf7a2228a..2d5d47c3004d0 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 @@ -20,20 +20,20 @@ export const useLogAnalysisJobs = ({ moduleId, sourceId, spaceId, - timeField, + jobParameters, }: { indexPattern: string; jobTypes: JobType[]; moduleId: string; sourceId: string; spaceId: string; - timeField: string; + jobParameters: { timestampField: string }; }) => { const { cleanupMLResources } = useLogAnalysisCleanup({ sourceId, spaceId }); - const [statusState, dispatch] = useStatusState({ + const [statusState, dispatch] = useStatusState(jobTypes, { bucketSpan, indexPattern, - timestampField: timeField, + timestampField: jobParameters.timestampField, }); const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( @@ -74,8 +74,25 @@ export const useLogAnalysisJobs = ({ spaceId, sourceId, indices.join(','), - timeField, - bucketSpan + [ + { + job_id: 'log-entry-rate' as const, + analysis_config: { + bucket_span: `${bucketSpan}ms`, + }, + data_description: { + time_field: jobParameters.timestampField, + }, + custom_settings: { + logs_source_config: { + indexPattern, + timestampField: jobParameters.timestampField, + bucketSpan, + }, + }, + }, + ], + [] ); }, onResolve: ({ datafeeds, jobs }: SetupMlModuleResponsePayload) => { @@ -85,7 +102,7 @@ export const useLogAnalysisJobs = ({ dispatch({ type: 'failedSetup' }); }, }, - [spaceId, sourceId, timeField, bucketSpan] + [spaceId, sourceId, jobParameters.timestampField, bucketSpan] ); const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx index 1f4c924ea3da5..a1bbda88caef8 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx @@ -11,8 +11,8 @@ import { getJobId, isJobStatusWithResults, JobStatus, - JobType, - jobTypeRT, + // JobType, + // jobTypeRT, SetupStatus, } from '../../../../common/log_analysis'; import { FetchJobStatusResponsePayload, JobSummary } from './api/ml_get_jobs_summary_api'; @@ -20,7 +20,7 @@ import { GetMlModuleResponsePayload, JobDefinition } from './api/ml_get_module'; import { SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; import { MandatoryProperty } from '../../../../common/utility_types'; -interface StatusReducerState { +interface StatusReducerState { jobDefinitions: JobDefinition[]; jobStatus: Record; jobSummaries: JobSummary[]; @@ -65,42 +65,60 @@ type StatusReducerAction = | { type: 'requestedJobDefinitionUpdate' } | { type: 'viewedResults' }; -const createInitialState = (sourceConfiguration: JobSourceConfiguration): StatusReducerState => ({ +const createInitialState = ({ + jobTypes, + sourceConfiguration, +}: { + jobTypes: JobType[]; + sourceConfiguration: JobSourceConfiguration; +}): StatusReducerState => ({ jobDefinitions: [], - jobStatus: { - 'log-entry-rate': 'unknown', - }, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'unknown', + }), + {} as Record + ), jobSummaries: [], lastSetupErrorMessages: [], setupStatus: 'initializing', sourceConfiguration, }); -function statusReducer(state: StatusReducerState, action: StatusReducerAction): StatusReducerState { +const createStatusReducer = (jobTypes: JobType[]) => ( + state: StatusReducerState, + action: StatusReducerAction +): StatusReducerState => { switch (action.type) { case 'startedSetup': { return { ...state, - jobStatus: { - 'log-entry-rate': 'initializing', - }, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'initializing', + }), + {} as Record + ), setupStatus: 'pending', }; } case 'finishedSetup': { const { jobs, datafeeds, spaceId, sourceId } = action; - const nextJobStatus = { - ...state.jobStatus, - 'log-entry-rate': - hasSuccessfullyCreatedJob(getJobId(spaceId, sourceId, 'log-entry-rate'))(jobs) && - hasSuccessfullyStartedDatafeed(getDatafeedId(spaceId, sourceId, 'log-entry-rate'))( - datafeeds - ) - ? ('started' as JobStatus) - : ('failed' as JobStatus), - }; - const nextSetupStatus = Object.values(nextJobStatus).every(jobState => - ['started'].includes(jobState) + const nextJobStatus = jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: + hasSuccessfullyCreatedJob(getJobId(spaceId, sourceId, jobType))(jobs) && + hasSuccessfullyStartedDatafeed(getDatafeedId(spaceId, sourceId, jobType))(datafeeds) + ? 'started' + : 'failed', + }), + {} as Record + ); + const nextSetupStatus = Object.values(nextJobStatus).every( + jobState => jobState === 'started' ) ? 'succeeded' : 'failed'; @@ -122,10 +140,13 @@ function statusReducer(state: StatusReducerState, action: StatusReducerAction): case 'failedSetup': { return { ...state, - jobStatus: { - ...state.jobStatus, - 'log-entry-rate': 'failed', - }, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'failed', + }), + {} as Record + ), setupStatus: 'failed', }; } @@ -140,10 +161,13 @@ function statusReducer(state: StatusReducerState, action: StatusReducerAction): const { payload: jobSummaries, spaceId, sourceId } = action; const { jobDefinitions, setupStatus, sourceConfiguration } = state; - const nextJobStatus = { - ...state.jobStatus, - 'log-entry-rate': getJobStatus(getJobId(spaceId, sourceId, 'log-entry-rate'))(jobSummaries), - }; + const nextJobStatus = jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: getJobStatus(getJobId(spaceId, sourceId, jobType))(jobSummaries), + }), + {} as Record + ); const nextSetupStatus = getSetupStatus( spaceId, sourceId, @@ -164,10 +188,13 @@ function statusReducer(state: StatusReducerState, action: StatusReducerAction): return { ...state, setupStatus: 'unknown', - jobStatus: { - ...state.jobStatus, - 'log-entry-rate': 'unknown', - }, + jobStatus: jobTypes.reduce( + (accumulatedJobStatus, jobType) => ({ + ...accumulatedJobStatus, + [jobType]: 'unknown', + }), + {} as Record + ), }; } case 'fetchedModuleDefinition': { @@ -230,7 +257,7 @@ function statusReducer(state: StatusReducerState, action: StatusReducerAction): return state; } } -} +}; const hasSuccessfullyCreatedJob = (jobId: string) => ( jobSetupResponses: SetupMlModuleResponsePayload['jobs'] @@ -281,7 +308,7 @@ const getJobStatus = (jobId: string) => (jobSummaries: FetchJobStatusResponsePay } )[0] || 'missing'; -const getSetupStatus = ( +const getSetupStatus = ( spaceId: string, sourceId: string, sourceConfiguration: JobSourceConfiguration, @@ -289,44 +316,47 @@ const getSetupStatus = ( jobDefinitions: JobDefinition[], jobSummaries: JobSummary[] ) => (previousSetupStatus: SetupStatus) => - Object.entries(everyJobStatus).reduce((setupStatus, [jobType, jobStatus]) => { - if (!jobTypeRT.is(jobType)) { - return setupStatus; - } + Object.entries(everyJobStatus).reduce( + (setupStatus, [jobType, jobStatus]) => { + // if (!jobTypeRT.is(jobType)) { + // return setupStatus; + // } - const jobId = getJobId(spaceId, sourceId, jobType); - const jobDefinition = jobDefinitions.find(({ id }) => id === jobType); + const jobId = getJobId(spaceId, sourceId, jobType); + const jobDefinition = jobDefinitions.find(({ id }) => id === jobType); - if (jobStatus === 'missing') { - return 'required'; - } else if ( - setupStatus === 'required' || - setupStatus === 'requiredForUpdate' || - setupStatus === 'requiredForReconfiguration' - ) { - return setupStatus; - } else if ( - setupStatus === 'skippedButUpdatable' || - (jobDefinition && - !isJobRevisionCurrent( - jobId, - jobDefinition.config.custom_settings.job_revision || 0 - )(jobSummaries)) - ) { - return 'skippedButUpdatable'; - } else if ( - setupStatus === 'skippedButReconfigurable' || - !isJobConfigurationConsistent(jobId, sourceConfiguration)(jobSummaries) - ) { - return 'skippedButReconfigurable'; - } else if (setupStatus === 'hiddenAfterSuccess') { - return setupStatus; - } else if (setupStatus === 'skipped' || isJobStatusWithResults(jobStatus)) { - return 'skipped'; - } + if (jobStatus === 'missing') { + return 'required'; + } else if ( + setupStatus === 'required' || + setupStatus === 'requiredForUpdate' || + setupStatus === 'requiredForReconfiguration' + ) { + return setupStatus; + } else if ( + setupStatus === 'skippedButUpdatable' || + (jobDefinition && + !isJobRevisionCurrent( + jobId, + jobDefinition.config.custom_settings.job_revision || 0 + )(jobSummaries)) + ) { + return 'skippedButUpdatable'; + } else if ( + setupStatus === 'skippedButReconfigurable' || + !isJobConfigurationConsistent(jobId, sourceConfiguration)(jobSummaries) + ) { + return 'skippedButReconfigurable'; + } else if (setupStatus === 'hiddenAfterSuccess') { + return setupStatus; + } else if (setupStatus === 'skipped' || isJobStatusWithResults(jobStatus)) { + return 'skipped'; + } - return setupStatus; - }, previousSetupStatus); + return setupStatus; + }, + previousSetupStatus + ); const isJobRevisionCurrent = (jobId: string, currentRevision: number) => ( jobSummaries: FetchJobStatusResponsePayload @@ -377,8 +407,15 @@ const isIndexPatternSubset = (indexPatternSubset: string, indexPatternSuperset: const hasError = (value: Value): value is MandatoryProperty => value.error != null; -export const useStatusState = (sourceConfiguration: JobSourceConfiguration) => { - return useReducer(statusReducer, sourceConfiguration, createInitialState); +export const useStatusState = ( + jobTypes: JobType[], + sourceConfiguration: JobSourceConfiguration +) => { + return useReducer( + createStatusReducer(jobTypes), + { jobTypes, sourceConfiguration }, + createInitialState + ); }; interface JobSourceConfiguration { diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx index 1ab02906d2955..69efa41c10a1b 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx @@ -27,7 +27,9 @@ export const useLogEntryRateJobs = ({ moduleId: 'logs_ui_analysis', sourceId, spaceId, - timeField, + jobParameters: { + timestampField: timeField, + }, }); }; From 4aea65ebcf81623ec6a95225886acd1a14e77f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 21 Nov 2019 17:06:25 +0100 Subject: [PATCH 06/10] Parameterize api call helpers with job types --- .../common/log_analysis/job_parameters.ts | 12 +++-- .../logs/log_analysis/api/ml_api_types.ts | 8 ++-- .../logs/log_analysis/api/ml_cleanup.ts | 37 ++++++++++++---- .../api/ml_get_jobs_summary_api.ts | 10 +++-- .../log_analysis/log_analysis_cleanup.tsx | 44 +++++++++++-------- .../logs/log_analysis/log_analysis_jobs.tsx | 25 +++++------ .../log_analysis_status_state.tsx | 13 ++---- .../logs/log_entry_rate/page_content.tsx | 2 + .../use_log_entry_rate_jobs.tsx | 4 +- 9 files changed, 90 insertions(+), 65 deletions(-) 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 59694d25b7259..4d437527477c9 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 @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import * as rt from 'io-ts'; + export const bucketSpan = 900000; export const getJobIdPrefix = (spaceId: string, sourceId: string) => @@ -15,6 +17,10 @@ export const getJobId = (spaceId: string, sourceId: string, jobType: string) => export const getDatafeedId = (spaceId: string, sourceId: string, jobType: string) => `datafeed-${getJobId(spaceId, sourceId, jobType)}`; -export const getAllModuleJobIds = (spaceId: string, sourceId: string) => [ - getJobId(spaceId, sourceId, 'log-entry-rate'), -]; +export const jobSourceConfigurationRT = rt.type({ + indexPattern: rt.string, + timestampField: rt.string, + bucketSpan: rt.number, +}); + +export type JobSourceConfiguration = rt.TypeOf; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts index deb3d528e42c2..de2e0e5ab510b 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts @@ -6,11 +6,9 @@ import * as rt from 'io-ts'; +import { jobSourceConfigurationRT } from '../../../../../common/log_analysis'; + export const jobCustomSettingsRT = rt.partial({ job_revision: rt.number, - logs_source_config: rt.partial({ - indexPattern: rt.string, - timestampField: rt.string, - bucketSpan: rt.number, - }), + logs_source_config: rt.partial(jobSourceConfigurationRT.props), }); diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts index 209da920c4c8b..841e1d90b2ce5 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts @@ -9,17 +9,22 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { kfetch } from 'ui/kfetch'; -import { getAllModuleJobIds, getDatafeedId } from '../../../../../common/log_analysis'; + +import { getDatafeedId, getJobId } from '../../../../../common/log_analysis'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; -export const callDeleteJobs = async (spaceId: string, sourceId: string) => { +export const callDeleteJobs = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { // NOTE: Deleting the jobs via this API will delete the datafeeds at the same time const deleteJobsResponse = await kfetch({ method: 'POST', pathname: '/api/ml/jobs/delete_jobs', body: JSON.stringify( deleteJobsRequestPayloadRT.encode({ - jobIds: getAllModuleJobIds(spaceId, sourceId), + jobIds: jobTypes.map(jobType => getJobId(spaceId, sourceId, jobType)), }) ), }); @@ -42,15 +47,24 @@ export const callGetJobDeletionTasks = async () => { ); }; -export const callStopDatafeed = async (spaceId: string, sourceId: string) => { +export const callStopDatafeeds = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { // Stop datafeed due to https://github.com/elastic/kibana/issues/44652 const stopDatafeedResponse = await kfetch({ method: 'POST', - pathname: `/api/ml/datafeeds/${getDatafeedId(spaceId, sourceId, 'log-entry-rate')}/_stop`, + pathname: '/api/ml/jobs/stop_datafeeds', + body: JSON.stringify( + stopDatafeedsRequestPayloadRT.encode({ + datafeedIds: jobTypes.map(jobType => getDatafeedId(spaceId, sourceId, jobType)), + }) + ), }); return pipe( - stopDatafeedResponsePayloadRT.decode(stopDatafeedResponse), + stopDatafeedsResponsePayloadRT.decode(stopDatafeedResponse), fold(throwErrors(createPlainError), identity) ); }; @@ -72,6 +86,13 @@ export const getJobDeletionTasksResponsePayloadRT = rt.type({ jobIds: rt.array(rt.string), }); -export const stopDatafeedResponsePayloadRT = rt.type({ - stopped: rt.boolean, +export const stopDatafeedsRequestPayloadRT = rt.type({ + datafeedIds: rt.array(rt.string), }); + +export const stopDatafeedsResponsePayloadRT = rt.record( + rt.string, + rt.type({ + stopped: rt.boolean, + }) +); 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 index 6171d10b5f1aa..91e517b0db008 100644 --- 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 @@ -12,15 +12,19 @@ import { kfetch } from 'ui/kfetch'; import { jobCustomSettingsRT } from './ml_api_types'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; -import { getAllModuleJobIds } from '../../../../../common/log_analysis'; +import { getJobId } from '../../../../../common/log_analysis'; -export const callJobsSummaryAPI = async (spaceId: string, sourceId: string) => { +export const callJobsSummaryAPI = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { const response = await kfetch({ method: 'POST', pathname: '/api/ml/jobs/jobs_summary', body: JSON.stringify( fetchJobStatusRequestPayloadRT.encode({ - jobIds: getAllModuleJobIds(spaceId, sourceId), + jobIds: jobTypes.map(jobType => getJobId(spaceId, sourceId, jobType)), }) ), }); diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx index 1b79d3c1ef786..2147c2bc104cc 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx @@ -4,35 +4,35 @@ * you may not use this file except in compliance with the Elastic License. */ -import createContainer from 'constate'; import { useMemo } from 'react'; + +import { getJobId } from '../../../../common/log_analysis'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { callDeleteJobs, callStopDatafeed, callGetJobDeletionTasks } from './api/ml_cleanup'; -import { getAllModuleJobIds } from '../../../../common/log_analysis'; +import { callDeleteJobs, callGetJobDeletionTasks, callStopDatafeeds } from './api/ml_cleanup'; -export const useLogAnalysisCleanup = ({ +export const useLogAnalysisCleanup = ({ sourceId, spaceId, + jobTypes, }: { sourceId: string; spaceId: string; + jobTypes: JobType[]; }) => { const [cleanupMLResourcesRequest, cleanupMLResources] = useTrackedPromise( { cancelPreviousOn: 'resolution', createPromise: async () => { try { - await callStopDatafeed(spaceId, sourceId); + await callStopDatafeeds(spaceId, sourceId, jobTypes); } catch (err) { - // Datefeed has been deleted / doesn't exist, proceed with deleting jobs anyway - if (err && err.res && err.res.status === 404) { - return await deleteJobs(spaceId, sourceId); - } else { + // Proceed only if datafeed has been deleted or didn't exist in the first place + if (err?.res?.status !== 404) { throw err; } } - return await deleteJobs(spaceId, sourceId); + return await deleteJobs(spaceId, sourceId, jobTypes); }, }, [spaceId, sourceId] @@ -48,20 +48,26 @@ export const useLogAnalysisCleanup = ({ }; }; -export const LogAnalysisCleanup = createContainer(useLogAnalysisCleanup); - -const deleteJobs = async (spaceId: string, sourceId: string) => { - const deleteJobsResponse = await callDeleteJobs(spaceId, sourceId); - await waitUntilJobsAreDeleted(spaceId, sourceId); +const deleteJobs = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + const deleteJobsResponse = await callDeleteJobs(spaceId, sourceId, jobTypes); + await waitUntilJobsAreDeleted(spaceId, sourceId, jobTypes); return deleteJobsResponse; }; -const waitUntilJobsAreDeleted = async (spaceId: string, sourceId: string) => { +const waitUntilJobsAreDeleted = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + const moduleJobIds = jobTypes.map(jobType => getJobId(spaceId, sourceId, jobType)); while (true) { - const response = await callGetJobDeletionTasks(); - const jobIdsBeingDeleted = response.jobIds; - const moduleJobIds = getAllModuleJobIds(spaceId, sourceId); + const { jobIds: jobIdsBeingDeleted } = await callGetJobDeletionTasks(); const needToWait = jobIdsBeingDeleted.some(jobId => moduleJobIds.includes(jobId)); + if (needToWait) { await timeout(1000); } else { 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 2d5d47c3004d0..a3bcaba0c5970 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useMemo, useCallback, useEffect } from 'react'; +import { useMemo, useCallback } from 'react'; import { callGetMlModuleAPI } from './api/ml_get_module'; import { bucketSpan, getJobId } from '../../../../common/log_analysis'; @@ -20,20 +20,20 @@ export const useLogAnalysisJobs = ({ moduleId, sourceId, spaceId, - jobParameters, + timestampField, }: { indexPattern: string; jobTypes: JobType[]; moduleId: string; sourceId: string; spaceId: string; - jobParameters: { timestampField: string }; + timestampField: string; }) => { - const { cleanupMLResources } = useLogAnalysisCleanup({ sourceId, spaceId }); + const { cleanupMLResources } = useLogAnalysisCleanup({ sourceId, spaceId, jobTypes }); const [statusState, dispatch] = useStatusState(jobTypes, { bucketSpan, indexPattern, - timestampField: jobParameters.timestampField, + timestampField, }); const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( @@ -55,7 +55,7 @@ export const useLogAnalysisJobs = ({ dispatch({ type: 'failedFetchingModuleDefinition' }); }, }, - [] + [moduleId] ); const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( @@ -81,12 +81,12 @@ export const useLogAnalysisJobs = ({ bucket_span: `${bucketSpan}ms`, }, data_description: { - time_field: jobParameters.timestampField, + time_field: timestampField, }, custom_settings: { logs_source_config: { indexPattern, - timestampField: jobParameters.timestampField, + timestampField, bucketSpan, }, }, @@ -102,7 +102,7 @@ export const useLogAnalysisJobs = ({ dispatch({ type: 'failedSetup' }); }, }, - [spaceId, sourceId, jobParameters.timestampField, bucketSpan] + [moduleId, spaceId, sourceId, timestampField, bucketSpan] ); const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( @@ -110,7 +110,7 @@ export const useLogAnalysisJobs = ({ cancelPreviousOn: 'resolution', createPromise: async () => { dispatch({ type: 'fetchingJobStatuses' }); - return await callJobsSummaryAPI(spaceId, sourceId); + return await callJobsSummaryAPI(spaceId, sourceId, jobTypes); }, onResolve: response => { dispatch({ type: 'fetchedJobStatuses', payload: response, spaceId, sourceId }); @@ -156,10 +156,6 @@ export const useLogAnalysisJobs = ({ dispatch({ type: 'requestedJobDefinitionUpdate' }); }, []); - useEffect(() => { - fetchModuleDefinition(); - }, [fetchModuleDefinition]); - const jobIds = useMemo(() => { return jobTypes.reduce( (accumulatedJobIds, jobType) => ({ @@ -173,6 +169,7 @@ export const useLogAnalysisJobs = ({ return { availableIndices, fetchJobStatus, + fetchModuleDefinition, isLoadingSetupStatus, jobStatus: statusState.jobStatus, lastSetupErrorMessages: statusState.lastSetupErrorMessages, diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx index a1bbda88caef8..db554fdbe2ffd 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx @@ -7,13 +7,12 @@ import { useReducer } from 'react'; import { + JobSourceConfiguration, + JobStatus, + SetupStatus, getDatafeedId, getJobId, isJobStatusWithResults, - JobStatus, - // JobType, - // jobTypeRT, - SetupStatus, } from '../../../../common/log_analysis'; import { FetchJobStatusResponsePayload, JobSummary } from './api/ml_get_jobs_summary_api'; import { GetMlModuleResponsePayload, JobDefinition } from './api/ml_get_module'; @@ -417,9 +416,3 @@ export const useStatusState = ( createInitialState ); }; - -interface JobSourceConfiguration { - bucketSpan: number; - indexPattern: string; - timestampField: string; -} diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index 117253fb5ed94..49ce681bc8479 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -25,6 +25,7 @@ export const LogEntryRatePageContent = () => { availableIndices, cleanupAndSetup, fetchJobStatus, + fetchModuleDefinition, lastSetupErrorMessages, setup, setupStatus, @@ -32,6 +33,7 @@ export const LogEntryRatePageContent = () => { } = useLogEntryRateJobsContext(); useEffect(() => { + fetchModuleDefinition(); fetchJobStatus(); }, []); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx index 69efa41c10a1b..2bcb0c6a69695 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx @@ -27,9 +27,7 @@ export const useLogEntryRateJobs = ({ moduleId: 'logs_ui_analysis', sourceId, spaceId, - jobParameters: { - timestampField: timeField, - }, + timestampField: timeField, }); }; From 02aa0e26247bdfaed5ad45b8e63e36d3eea3c3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 21 Nov 2019 20:12:20 +0100 Subject: [PATCH 07/10] Move job overrides out of the generic jobs hook --- .../log_analysis/api/ml_setup_module_api.ts | 34 +------------- .../logs/log_analysis/log_analysis_jobs.tsx | 44 ++++++++----------- .../log_analysis_status_state.tsx | 4 -- .../use_log_entry_rate_jobs.tsx | 28 ++++++++++++ 4 files changed, 49 insertions(+), 61 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 f80e875ab587f..80a4f975cdd57 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,7 +12,6 @@ import { kfetch } from 'ui/kfetch'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; import { getJobIdPrefix } from '../../../../../common/log_analysis'; -// import { jobCustomSettingsRT } from './ml_api_types'; export const callSetupMlModuleAPI = async ( moduleId: string, @@ -36,25 +35,6 @@ export const callSetupMlModuleAPI = async ( startDatafeed: true, jobOverrides, datafeedOverrides, - // jobOverrides: [ - // { - // job_id: 'log-entry-rate' as const, - // analysis_config: { - // bucket_span: `${bucketSpan}ms`, - // }, - // data_description: { - // time_field: timeField, - // }, - // custom_settings: { - // logs_source_config: { - // indexPattern, - // timestampField: timeField, - // bucketSpan, - // }, - // }, - // }, - // ], - // datafeedOverrides: [], }) ), }); @@ -72,21 +52,11 @@ const setupMlModuleTimeParamsRT = rt.partial({ const setupMlModuleJobOverridesRT = rt.object; -type SetupMlModuleJobOverrides = rt.TypeOf; +export type SetupMlModuleJobOverrides = rt.TypeOf; const setupMlModuleDatafeedOverridesRT = rt.object; -type SetupMlModuleDatafeedOverrides = rt.TypeOf; -// const setupMlModuleLogEntryRateJobOverridesRT = rt.type({ -// job_id: rt.literal('log-entry-rate'), -// analysis_config: rt.type({ -// bucket_span: rt.string, -// }), -// data_description: rt.type({ -// time_field: rt.string, -// }), -// custom_settings: jobCustomSettingsRT, -// }); +export type SetupMlModuleDatafeedOverrides = rt.TypeOf; const setupMlModuleRequestParamsRT = rt.type({ indexPatternName: rt.string, 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 a3bcaba0c5970..e54d8381e8272 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 @@ -4,25 +4,36 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useMemo, useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; -import { callGetMlModuleAPI } from './api/ml_get_module'; -import { bucketSpan, getJobId } from '../../../../common/log_analysis'; +import { getJobId } from '../../../../common/log_analysis'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; -import { callSetupMlModuleAPI, SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; +import { callGetMlModuleAPI } from './api/ml_get_module'; +import { + callSetupMlModuleAPI, + SetupMlModuleDatafeedOverrides, + SetupMlModuleJobOverrides, + SetupMlModuleResponsePayload, +} from './api/ml_setup_module_api'; import { useLogAnalysisCleanup } from './log_analysis_cleanup'; import { useStatusState } from './log_analysis_status_state'; export const useLogAnalysisJobs = ({ + bucketSpan, + datafeedOverrides, indexPattern, + jobOverrides, jobTypes, moduleId, sourceId, spaceId, timestampField, }: { + bucketSpan: number; + datafeedOverrides: SetupMlModuleDatafeedOverrides[]; indexPattern: string; + jobOverrides: SetupMlModuleJobOverrides[]; jobTypes: JobType[]; moduleId: string; sourceId: string; @@ -74,25 +85,8 @@ export const useLogAnalysisJobs = ({ spaceId, sourceId, indices.join(','), - [ - { - job_id: 'log-entry-rate' as const, - analysis_config: { - bucket_span: `${bucketSpan}ms`, - }, - data_description: { - time_field: timestampField, - }, - custom_settings: { - logs_source_config: { - indexPattern, - timestampField, - bucketSpan, - }, - }, - }, - ], - [] + jobOverrides, + datafeedOverrides ); }, onResolve: ({ datafeeds, jobs }: SetupMlModuleResponsePayload) => { @@ -102,7 +96,7 @@ export const useLogAnalysisJobs = ({ dispatch({ type: 'failedSetup' }); }, }, - [moduleId, spaceId, sourceId, timestampField, bucketSpan] + [moduleId, spaceId, sourceId, timestampField, bucketSpan, jobOverrides, datafeedOverrides] ); const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( @@ -115,7 +109,7 @@ export const useLogAnalysisJobs = ({ onResolve: response => { dispatch({ type: 'fetchedJobStatuses', payload: response, spaceId, sourceId }); }, - onReject: err => { + onReject: () => { dispatch({ type: 'failedFetchingJobStatuses' }); }, }, diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx index db554fdbe2ffd..ec4214d3f9103 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx @@ -317,10 +317,6 @@ const getSetupStatus = ( ) => (previousSetupStatus: SetupStatus) => Object.entries(everyJobStatus).reduce( (setupStatus, [jobType, jobStatus]) => { - // if (!jobTypeRT.is(jobType)) { - // return setupStatus; - // } - const jobId = getJobId(spaceId, sourceId, jobType); const jobDefinition = jobDefinitions.find(({ id }) => id === jobType); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx index 2bcb0c6a69695..5ee4b95ae814f 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx @@ -5,7 +5,9 @@ */ import createContainer from 'constate'; +import { useMemo } from 'react'; +import { bucketSpan } from '../../../../common/log_analysis'; import { useLogAnalysisJobs } from '../../../containers/logs/log_analysis'; const jobTypes = ['log-entry-rate']; @@ -21,8 +23,34 @@ export const useLogEntryRateJobs = ({ spaceId: string; timeField: string; }) => { + const jobOverrides = useMemo( + () => [ + { + job_id: 'log-entry-rate' as const, + analysis_config: { + bucket_span: `${bucketSpan}ms`, + }, + data_description: { + time_field: timeField, + }, + custom_settings: { + logs_source_config: { + indexPattern, + timestampField: timeField, + bucketSpan, + }, + }, + }, + ], + [bucketSpan, timeField, indexPattern] + ); + const datafeedOverrides = useMemo(() => [], []); + return useLogAnalysisJobs({ + bucketSpan, + datafeedOverrides, indexPattern, + jobOverrides, jobTypes, moduleId: 'logs_ui_analysis', sourceId, From 1d16d063ce6e3b8aacd9a68c8fa661a2692950ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Tue, 26 Nov 2019 00:29:27 +0100 Subject: [PATCH 08/10] Further abstract module management and validation --- .../http_api/log_analysis/validation/index.ts | 2 +- .../{indices.ts => log_entry_rate_indices.ts} | 14 +- .../common/log_analysis/job_parameters.ts | 2 + .../logs/log_analysis/api/ml_api_types.ts | 21 ++ .../logs/log_analysis/api/ml_cleanup.ts | 2 + ...tterns_validate.ts => validate_indices.ts} | 14 +- .../containers/logs/log_analysis/index.ts | 5 +- .../log_analysis_capabilities.tsx | 2 +- .../log_analysis/log_analysis_cleanup.tsx | 52 ++--- .../logs/log_analysis/log_analysis_jobs.tsx | 180 ------------------ .../logs/log_analysis/log_analysis_module.tsx | 167 ++++++++++++++++ ...ate.tsx => log_analysis_module_status.tsx} | 2 +- .../log_analysis/log_analysis_module_types.ts | 36 ++++ .../log_analysis/log_analysis_setup_state.tsx | 92 +++++---- .../logs/log_analysis/ml_api_types.ts | 28 --- .../logs/log_entry_rate/module_descriptor.ts | 107 +++++++++++ .../logs/log_entry_rate/page_content.tsx | 18 +- .../logs/log_entry_rate/page_providers.tsx | 9 +- .../log_entry_rate/page_results_content.tsx | 4 +- .../log_entry_rate/page_setup_content.tsx | 26 +-- .../analysis_setup_indices_form.tsx | 17 +- .../logs/log_entry_rate/setup/setup_steps.tsx | 24 ++- .../use_log_entry_rate_jobs.tsx | 64 ------- .../use_log_entry_rate_module.tsx | 45 +++++ .../plugins/infra/server/infra_server.ts | 8 +- .../infra/server/routes/log_analysis/index.ts | 2 +- .../log_analysis/results/log_entry_rate.ts | 5 +- .../{index_patterns => validation}/index.ts | 2 +- .../validate.ts => validation/indices.ts} | 25 +-- 29 files changed, 544 insertions(+), 431 deletions(-) rename x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/{indices.ts => log_entry_rate_indices.ts} (74%) rename x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/{index_patterns_validate.ts => validate_indices.ts} (70%) delete 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/log_analysis_module.tsx rename x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/{log_analysis_status_state.tsx => log_analysis_module_status.tsx} (99%) create mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts delete mode 100644 x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/module_descriptor.ts delete mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_jobs.tsx create mode 100644 x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_module.tsx rename x-pack/legacy/plugins/infra/server/routes/log_analysis/{index_patterns => validation}/index.ts (89%) rename x-pack/legacy/plugins/infra/server/routes/log_analysis/{index_patterns/validate.ts => validation/indices.ts} (74%) diff --git a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/index.ts b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/index.ts index 727faca69298e..f23ef7ee7c302 100644 --- a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/index.ts +++ b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './indices'; +export * from './log_entry_rate_indices'; diff --git a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/indices.ts b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/log_entry_rate_indices.ts similarity index 74% rename from x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/indices.ts rename to x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/log_entry_rate_indices.ts index 62d81dc136853..5b2509074f6ed 100644 --- a/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/indices.ts +++ b/x-pack/legacy/plugins/infra/common/http_api/log_analysis/validation/log_entry_rate_indices.ts @@ -6,14 +6,24 @@ import * as rt from 'io-ts'; -export const LOG_ANALYSIS_VALIDATION_INDICES_PATH = '/api/infra/log_analysis/validation/indices'; +export const LOG_ANALYSIS_VALIDATE_INDICES_PATH = + '/api/infra/log_analysis/validation/log_entry_rate_indices'; /** * Request types */ +export const validationIndicesFieldSpecificationRT = rt.type({ + name: rt.string, + validTypes: rt.array(rt.string), +}); + +export type ValidationIndicesFieldSpecification = rt.TypeOf< + typeof validationIndicesFieldSpecificationRT +>; + export const validationIndicesRequestPayloadRT = rt.type({ data: rt.type({ - timestampField: rt.string, + fields: rt.array(validationIndicesFieldSpecificationRT), indices: rt.array(rt.string), }), }); 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 4d437527477c9..626e90b65a7d8 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 @@ -8,6 +8,8 @@ import * as rt from 'io-ts'; export const bucketSpan = 900000; +export const partitionField = 'event.dataset'; + export const getJobIdPrefix = (spaceId: string, sourceId: string) => `kibana-logs-ui-${spaceId}-${sourceId}-`; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts index de2e0e5ab510b..9d4d419ceebe3 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_api_types.ts @@ -12,3 +12,24 @@ export const jobCustomSettingsRT = rt.partial({ job_revision: rt.number, logs_source_config: rt.partial(jobSourceConfigurationRT.props), }); + +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/containers/logs/log_analysis/api/ml_cleanup.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts index 841e1d90b2ce5..5054f607fa5dc 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts @@ -82,6 +82,8 @@ export const deleteJobsResponsePayloadRT = rt.record( }) ); +export type DeleteJobsResponsePayload = rt.TypeOf; + export const getJobDeletionTasksResponsePayloadRT = rt.type({ jobIds: rt.array(rt.string), }); diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/index_patterns_validate.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts similarity index 70% rename from x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/index_patterns_validate.ts rename to x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts index 440ee10e4223d..0d2e9b673488e 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/index_patterns_validate.ts +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts @@ -10,20 +10,22 @@ import { identity } from 'fp-ts/lib/function'; import { kfetch } from 'ui/kfetch'; import { - LOG_ANALYSIS_VALIDATION_INDICES_PATH, + LOG_ANALYSIS_VALIDATE_INDICES_PATH, + ValidationIndicesFieldSpecification, validationIndicesRequestPayloadRT, validationIndicesResponsePayloadRT, } from '../../../../../common/http_api'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; -export const callIndexPatternsValidate = async (timestampField: string, indices: string[]) => { +export const callValidateIndicesAPI = async ( + indices: string[], + fields: ValidationIndicesFieldSpecification[] +) => { const response = await kfetch({ method: 'POST', - pathname: LOG_ANALYSIS_VALIDATION_INDICES_PATH, - body: JSON.stringify( - validationIndicesRequestPayloadRT.encode({ data: { timestampField, indices } }) - ), + pathname: LOG_ANALYSIS_VALIDATE_INDICES_PATH, + body: JSON.stringify(validationIndicesRequestPayloadRT.encode({ data: { indices, fields } })), }); return pipe( 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 247387a2a583e..eb044c86e50fe 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 @@ -6,5 +6,6 @@ export * from './log_analysis_capabilities'; export * from './log_analysis_cleanup'; -export * from './log_analysis_jobs'; -export * from './log_analysis_status_state'; +export * from './log_analysis_module'; +export * from './log_analysis_module_status'; +export * from './log_analysis_module_types'; 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 index 7ac7d051e6783..35a3ac737ada3 100644 --- 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 @@ -15,7 +15,7 @@ import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { getMlCapabilitiesResponsePayloadRT, GetMlCapabilitiesResponsePayload, -} from './ml_api_types'; +} from './api/ml_api_types'; import { throwErrors, createPlainError } from '../../../../common/runtime_types'; export const useLogAnalysisCapabilities = () => { diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx index 2147c2bc104cc..a37d18cc33cfd 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx @@ -4,48 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useMemo } from 'react'; - import { getJobId } from '../../../../common/log_analysis'; -import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { callDeleteJobs, callGetJobDeletionTasks, callStopDatafeeds } from './api/ml_cleanup'; -export const useLogAnalysisCleanup = ({ - sourceId, - spaceId, - jobTypes, -}: { - sourceId: string; - spaceId: string; - jobTypes: JobType[]; -}) => { - const [cleanupMLResourcesRequest, cleanupMLResources] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - try { - await callStopDatafeeds(spaceId, sourceId, jobTypes); - } catch (err) { - // Proceed only if datafeed has been deleted or didn't exist in the first place - if (err?.res?.status !== 404) { - throw err; - } - } - - return await deleteJobs(spaceId, sourceId, jobTypes); - }, - }, - [spaceId, sourceId] - ); - - const isCleaningUp = useMemo(() => cleanupMLResourcesRequest.state === 'pending', [ - cleanupMLResourcesRequest.state, - ]); +export const cleanUpJobsAndDatafeeds = async ( + spaceId: string, + sourceId: string, + jobTypes: JobType[] +) => { + try { + await callStopDatafeeds(spaceId, sourceId, jobTypes); + } catch (err) { + // Proceed only if datafeed has been deleted or didn't exist in the first place + if (err?.res?.status !== 404) { + throw err; + } + } - return { - cleanupMLResources, - isCleaningUp, - }; + return await deleteJobs(spaceId, sourceId, jobTypes); }; const deleteJobs = async ( 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 deleted file mode 100644 index cb685c2e54dc5..0000000000000 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_jobs.tsx +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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 { useCallback, useMemo } from 'react'; - -import { getJobId } from '../../../../common/log_analysis'; -import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { callJobsSummaryAPI } from './api/ml_get_jobs_summary_api'; -import { callGetMlModuleAPI } from './api/ml_get_module'; -import { - callSetupMlModuleAPI, - SetupMlModuleDatafeedOverrides, - SetupMlModuleJobOverrides, - SetupMlModuleResponsePayload, -} from './api/ml_setup_module_api'; -import { useLogAnalysisCleanup } from './log_analysis_cleanup'; -import { useStatusState } from './log_analysis_status_state'; - -export const useLogAnalysisJobs = ({ - bucketSpan, - datafeedOverrides, - indexPattern, - jobOverrides, - jobTypes, - moduleId, - sourceId, - spaceId, - timestampField, -}: { - bucketSpan: number; - datafeedOverrides: SetupMlModuleDatafeedOverrides[]; - indexPattern: string; - jobOverrides: SetupMlModuleJobOverrides[]; - jobTypes: JobType[]; - moduleId: string; - sourceId: string; - spaceId: string; - timestampField: string; -}) => { - const { cleanupMLResources } = useLogAnalysisCleanup({ sourceId, spaceId, jobTypes }); - const [statusState, dispatch] = useStatusState(jobTypes, { - bucketSpan, - indexPattern, - timestampField, - }); - - const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - dispatch({ type: 'fetchingModuleDefinition' }); - return await callGetMlModuleAPI(moduleId); - }, - onResolve: response => { - dispatch({ - type: 'fetchedModuleDefinition', - spaceId, - sourceId, - moduleDefinition: response, - }); - }, - onReject: () => { - dispatch({ type: 'failedFetchingModuleDefinition' }); - }, - }, - [moduleId] - ); - - const [setupMlModuleRequest, setupMlModule] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async ( - indices: string[], - start: number | undefined, - end: number | undefined - ) => { - dispatch({ type: 'startedSetup' }); - return await callSetupMlModuleAPI( - moduleId, - start, - end, - spaceId, - sourceId, - indices.join(','), - jobOverrides, - datafeedOverrides - ); - }, - onResolve: ({ datafeeds, jobs }: SetupMlModuleResponsePayload) => { - dispatch({ type: 'finishedSetup', datafeeds, jobs, spaceId, sourceId }); - }, - onReject: () => { - dispatch({ type: 'failedSetup' }); - }, - }, - [moduleId, spaceId, sourceId, timestampField, bucketSpan, jobOverrides, datafeedOverrides] - ); - - const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( - { - cancelPreviousOn: 'resolution', - createPromise: async () => { - dispatch({ type: 'fetchingJobStatuses' }); - return await callJobsSummaryAPI(spaceId, sourceId, jobTypes); - }, - onResolve: jobResponse => { - dispatch({ type: 'fetchedJobStatuses', payload: jobResponse, spaceId, sourceId }); - }, - onReject: () => { - dispatch({ type: 'failedFetchingJobStatuses' }); - }, - }, - [spaceId, sourceId] - ); - - const isLoadingSetupStatus = useMemo( - () => - fetchJobStatusRequest.state === 'pending' || fetchModuleDefinitionRequest.state === 'pending', - [fetchJobStatusRequest.state, fetchModuleDefinitionRequest.state] - ); - - const availableIndices = useMemo(() => indexPattern.split(','), [indexPattern]); - - const viewResults = useCallback(() => { - dispatch({ type: 'viewedResults' }); - }, []); - - const cleanupAndSetup = useCallback( - (indices: string[], start: number | undefined, end: number | undefined) => { - dispatch({ type: 'startedSetup' }); - cleanupMLResources() - .then(() => { - setupMlModule(indices, start, end); - }) - .catch(() => { - dispatch({ type: 'failedSetup' }); - }); - }, - [cleanupMLResources, setupMlModule] - ); - - const viewSetupForReconfiguration = useCallback(() => { - dispatch({ type: 'requestedJobConfigurationUpdate' }); - }, []); - - const viewSetupForUpdate = useCallback(() => { - dispatch({ type: 'requestedJobDefinitionUpdate' }); - }, []); - - const jobIds = useMemo(() => { - return jobTypes.reduce( - (accumulatedJobIds, jobType) => ({ - ...accumulatedJobIds, - [jobType]: getJobId(spaceId, sourceId, jobType), - }), - {} as Record - ); - }, [jobTypes, sourceId, spaceId]); - - return { - availableIndices, - fetchJobStatus, - fetchModuleDefinition, - isLoadingSetupStatus, - jobStatus: statusState.jobStatus, - lastSetupErrorMessages: statusState.lastSetupErrorMessages, - cleanupAndSetup, - setup: setupMlModule, - setupMlModuleRequest, - setupStatus: statusState.setupStatus, - timestampField: timeField, - viewSetupForReconfiguration, - viewSetupForUpdate, - viewResults, - jobIds, - }; -}; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx new file mode 100644 index 0000000000000..189b58d7923f8 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx @@ -0,0 +1,167 @@ +/* + * 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 { useCallback, useMemo } from 'react'; + +import { useTrackedPromise } from '../../../utils/use_tracked_promise'; +import { useModuleStatus } from './log_analysis_module_status'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './log_analysis_module_types'; + +export const useLogAnalysisModule = ({ + sourceConfiguration, + moduleDescriptor, +}: { + sourceConfiguration: ModuleSourceConfiguration; + moduleDescriptor: ModuleDescriptor; +}) => { + const { spaceId, sourceId, timestampField, indices } = sourceConfiguration; + const [moduleStatus, dispatchModuleStatus] = useModuleStatus(moduleDescriptor.jobTypes, { + bucketSpan: moduleDescriptor.bucketSpan, + indexPattern: indices.join(','), + timestampField, + }); + + const [fetchModuleDefinitionRequest, fetchModuleDefinition] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + dispatchModuleStatus({ type: 'fetchingModuleDefinition' }); + return await moduleDescriptor.getModuleDefinition(); + }, + onResolve: response => { + dispatchModuleStatus({ + type: 'fetchedModuleDefinition', + spaceId, + sourceId, + moduleDefinition: response, + }); + }, + onReject: () => { + dispatchModuleStatus({ type: 'failedFetchingModuleDefinition' }); + }, + }, + [moduleDescriptor.getModuleDefinition, spaceId, sourceId] + ); + + const [fetchJobStatusRequest, fetchJobStatus] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + dispatchModuleStatus({ type: 'fetchingJobStatuses' }); + return await moduleDescriptor.getJobSummary(spaceId, sourceId); + }, + onResolve: jobResponse => { + dispatchModuleStatus({ + type: 'fetchedJobStatuses', + payload: jobResponse, + spaceId, + sourceId, + }); + }, + onReject: () => { + dispatchModuleStatus({ type: 'failedFetchingJobStatuses' }); + }, + }, + [spaceId, sourceId] + ); + + const isLoadingModuleStatus = useMemo( + () => + fetchJobStatusRequest.state === 'pending' || fetchModuleDefinitionRequest.state === 'pending', + [fetchJobStatusRequest.state, fetchModuleDefinitionRequest.state] + ); + + const [, setUpModule] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async ( + selectedIndices: string[], + start: number | undefined, + end: number | undefined + ) => { + dispatchModuleStatus({ type: 'startedSetup' }); + return await moduleDescriptor.setUpModule(start, end, { + indices: selectedIndices, + sourceId, + spaceId, + timestampField, + }); + }, + onResolve: ({ datafeeds, jobs }) => { + dispatchModuleStatus({ type: 'finishedSetup', datafeeds, jobs, spaceId, sourceId }); + }, + onReject: () => { + dispatchModuleStatus({ type: 'failedSetup' }); + }, + }, + [moduleDescriptor.setUpModule, spaceId, sourceId, timestampField] + ); + + const [cleanUpModuleRequest, cleanUpModule] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await moduleDescriptor.cleanUpModule(spaceId, sourceId); + }, + }, + [spaceId, sourceId] + ); + + const isCleaningUp = useMemo(() => cleanUpModuleRequest.state === 'pending', [ + cleanUpModuleRequest.state, + ]); + + const cleanUpAndSetUpModule = useCallback( + (selectedIndices: string[], start: number | undefined, end: number | undefined) => { + dispatchModuleStatus({ type: 'startedSetup' }); + cleanUpModule() + .then(() => { + setUpModule(selectedIndices, start, end); + }) + .catch(() => { + dispatchModuleStatus({ type: 'failedSetup' }); + }); + }, + [cleanUpModule, setUpModule] + ); + + const viewSetupForReconfiguration = useCallback(() => { + dispatchModuleStatus({ type: 'requestedJobConfigurationUpdate' }); + }, []); + + const viewSetupForUpdate = useCallback(() => { + dispatchModuleStatus({ type: 'requestedJobDefinitionUpdate' }); + }, []); + + const viewResults = useCallback(() => { + dispatchModuleStatus({ type: 'viewedResults' }); + }, []); + + const jobIds = useMemo(() => moduleDescriptor.getJobIds(spaceId, sourceId), [ + moduleDescriptor.getJobIds, + spaceId, + sourceId, + ]); + + return { + cleanUpAndSetUpModule, + cleanUpModule, + fetchJobStatus, + fetchModuleDefinition, + isCleaningUp, + isLoadingModuleStatus, + jobIds, + jobStatus: moduleStatus.jobStatus, + lastSetupErrorMessages: moduleStatus.lastSetupErrorMessages, + moduleDescriptor, + setUpModule, + setupStatus: moduleStatus.setupStatus, + sourceConfiguration, + viewResults, + viewSetupForReconfiguration, + viewSetupForUpdate, + }; +}; diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx similarity index 99% rename from x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx rename to x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx index ec4214d3f9103..6d634538cd7fe 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_status_state.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx @@ -402,7 +402,7 @@ const isIndexPatternSubset = (indexPatternSubset: string, indexPatternSuperset: const hasError = (value: Value): value is MandatoryProperty => value.error != null; -export const useStatusState = ( +export const useModuleStatus = ( jobTypes: JobType[], sourceConfiguration: JobSourceConfiguration ) => { diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts new file mode 100644 index 0000000000000..dc9f25b492635 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts @@ -0,0 +1,36 @@ +/* + * 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 { DeleteJobsResponsePayload } from './api/ml_cleanup'; +import { FetchJobStatusResponsePayload } from './api/ml_get_jobs_summary_api'; +import { GetMlModuleResponsePayload } from './api/ml_get_module'; +import { SetupMlModuleResponsePayload } from './api/ml_setup_module_api'; +import { ValidationIndicesResponsePayload } from '../../../../common/http_api/log_analysis'; + +export interface ModuleDescriptor { + moduleId: string; + jobTypes: JobType[]; + bucketSpan: number; + getJobIds: (spaceId: string, sourceId: string) => Record; + getJobSummary: (spaceId: string, sourceId: string) => Promise; + getModuleDefinition: () => Promise; + setUpModule: ( + start: number | undefined, + end: number | undefined, + sourceConfiguration: ModuleSourceConfiguration + ) => Promise; + cleanUpModule: (spaceId: string, sourceId: string) => Promise; + validateSetupIndices: ( + sourceConfiguration: ModuleSourceConfiguration + ) => Promise; +} + +export interface ModuleSourceConfiguration { + indices: string[]; + sourceId: string; + spaceId: string; + timestampField: string; +} diff --git a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_setup_state.tsx b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_setup_state.tsx index c965c50bedccc..275c0194be3b2 100644 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_setup_state.tsx +++ b/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/log_analysis_setup_state.tsx @@ -4,15 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { useState, useCallback, useMemo, useEffect } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { ValidationIndicesError } from '../../../../common/http_api'; import { isExampleDataIndex } from '../../../../common/log_analysis'; -import { - ValidationIndicesError, - ValidationIndicesResponsePayload, -} from '../../../../common/http_api'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; -import { callIndexPatternsValidate } from './api/index_patterns_validate'; +import { ModuleDescriptor, ModuleSourceConfiguration } from './log_analysis_module_types'; type SetupHandler = ( indices: string[], @@ -25,53 +22,69 @@ export type ValidationIndicesUIError = | { error: 'NETWORK_ERROR' } | { error: 'TOO_FEW_SELECTED_INDICES' }; -export interface ValidatedIndex { - index: string; - errors: ValidationIndicesError[]; +interface ValidIndex { + validity: 'valid'; + name: string; isSelected: boolean; } -interface AnalysisSetupStateArguments { - availableIndices: string[]; +interface InvalidIndex { + validity: 'invalid'; + name: string; + errors: ValidationIndicesError[]; +} + +export type ValidatedIndex = ValidIndex | InvalidIndex; + +interface AnalysisSetupStateArguments { cleanupAndSetupModule: SetupHandler; + moduleDescriptor: ModuleDescriptor; setupModule: SetupHandler; - timestampField: string; + sourceConfiguration: ModuleSourceConfiguration; } const fourWeeksInMs = 86400000 * 7 * 4; -export const useAnalysisSetupState = ({ - availableIndices, +export const useAnalysisSetupState = ({ cleanupAndSetupModule, + moduleDescriptor: { validateSetupIndices }, setupModule, - timestampField, -}: AnalysisSetupStateArguments) => { + sourceConfiguration, +}: AnalysisSetupStateArguments) => { const [startTime, setStartTime] = useState(Date.now() - fourWeeksInMs); const [endTime, setEndTime] = useState(undefined); - // Prepare the validation - const [validatedIndices, setValidatedIndices] = useState( - availableIndices.map(index => ({ - index, - errors: [], - isSelected: false, - })) - ); + const [validatedIndices, setValidatedIndices] = useState([]); + const [validateIndicesRequest, validateIndices] = useTrackedPromise( { cancelPreviousOn: 'resolution', createPromise: async () => { - return await callIndexPatternsValidate(timestampField, availableIndices); + return await validateSetupIndices(sourceConfiguration); }, - onResolve: ({ data }: ValidationIndicesResponsePayload) => { - setValidatedIndices( - availableIndices.map(index => { - const errors = data.errors.filter(error => error.index === index); - return { - index, - errors, - isSelected: errors.length === 0 && !isExampleDataIndex(index), - }; + onResolve: ({ data: { errors } }) => { + setValidatedIndices(previousValidatedIndices => + sourceConfiguration.indices.map(indexName => { + const previousValidatedIndex = previousValidatedIndices.filter( + ({ name }) => name === indexName + )[0]; + const indexValiationErrors = errors.filter(({ index }) => index === indexName); + if (indexValiationErrors.length > 0) { + return { + validity: 'invalid', + name: indexName, + errors: indexValiationErrors, + }; + } else { + return { + validity: 'valid', + name: indexName, + isSelected: + previousValidatedIndex?.validity === 'valid' + ? previousValidatedIndex?.isSelected + : !isExampleDataIndex(indexName), + }; + } }) ); }, @@ -79,7 +92,7 @@ export const useAnalysisSetupState = ({ setValidatedIndices([]); }, }, - [availableIndices, timestampField] + [sourceConfiguration.indices] ); useEffect(() => { @@ -87,7 +100,10 @@ export const useAnalysisSetupState = ({ }, [validateIndices]); const selectedIndexNames = useMemo( - () => validatedIndices.filter(i => i.isSelected).map(i => i.index), + () => + validatedIndices + .filter(index => index.validity === 'valid' && index.isSelected) + .map(i => i.name), [validatedIndices] ); @@ -120,7 +136,9 @@ export const useAnalysisSetupState = ({ } return validatedIndices.reduce((errors, index) => { - return selectedIndexNames.includes(index.index) ? errors.concat(index.errors) : errors; + return index.validity === 'invalid' && selectedIndexNames.includes(index.name) + ? [...errors, ...index.errors] + : errors; }, []); }, [selectedIndexNames, validatedIndices, validateIndicesRequest.state]); 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 deleted file mode 100644 index ee70edc31d49b..0000000000000 --- a/x-pack/legacy/plugins/infra/public/containers/logs/log_analysis/ml_api_types.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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/log_entry_rate/module_descriptor.ts b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/module_descriptor.ts new file mode 100644 index 0000000000000..52be313264335 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/module_descriptor.ts @@ -0,0 +1,107 @@ +/* + * 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 { bucketSpan, getJobId, partitionField } from '../../../../common/log_analysis'; + +import { + ModuleDescriptor, + ModuleSourceConfiguration, + cleanUpJobsAndDatafeeds, +} from '../../../containers/logs/log_analysis'; +import { callJobsSummaryAPI } from '../../../containers/logs/log_analysis/api/ml_get_jobs_summary_api'; +import { callGetMlModuleAPI } from '../../../containers/logs/log_analysis/api/ml_get_module'; +import { callSetupMlModuleAPI } from '../../../containers/logs/log_analysis/api/ml_setup_module_api'; +import { callValidateIndicesAPI } from '../../../containers/logs/log_analysis/api/validate_indices'; + +const jobTypes = ['log-entry-rate']; +const moduleId = 'logs_ui_analysis'; + +type JobType = typeof jobTypes[0]; + +const getJobIds = (spaceId: string, sourceId: string) => + jobTypes.reduce( + (accumulatedJobIds, jobType) => ({ + ...accumulatedJobIds, + [jobType]: getJobId(spaceId, sourceId, jobType), + }), + {} as Record + ); + +const getJobSummary = async (spaceId: string, sourceId: string) => { + const response = await callJobsSummaryAPI(spaceId, sourceId, jobTypes); + const jobIds = Object.values(getJobIds(spaceId, sourceId)); + + return response.filter(jobSummary => jobIds.includes(jobSummary.id)); +}; + +const getModuleDefinition = async () => { + return await callGetMlModuleAPI(moduleId); +}; + +const setUpModule = async ( + start: number | undefined, + end: number | undefined, + { spaceId, sourceId, indices, timestampField }: ModuleSourceConfiguration +) => { + const indexNamePattern = indices.join(','); + const jobOverrides = [ + { + job_id: 'log-entry-rate' as const, + analysis_config: { + bucket_span: `${bucketSpan}ms`, + }, + data_description: { + time_field: timestampField, + }, + custom_settings: { + logs_source_config: { + indexPattern: indexNamePattern, + timestampField, + bucketSpan, + }, + }, + }, + ]; + + return callSetupMlModuleAPI( + moduleId, + start, + end, + spaceId, + sourceId, + indexNamePattern, + jobOverrides + ); +}; + +const cleanUpModule = async (spaceId: string, sourceId: string) => { + return await cleanUpJobsAndDatafeeds(spaceId, sourceId, jobTypes); +}; + +const validateSetupIndices = async ({ indices, timestampField }: ModuleSourceConfiguration) => { + return await callValidateIndicesAPI(indices, [ + { + name: timestampField, + validTypes: ['date'], + }, + { + name: partitionField, + validTypes: ['keyword'], + }, + ]); +}; + +export const logEntryRateModule: ModuleDescriptor = { + moduleId, + jobTypes, + bucketSpan, + getJobIds, + getJobSummary, + getModuleDefinition, + setUpModule, + cleanUpModule, + validateSetupIndices, +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx index cfca8823fb524..e62164cb17b2c 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_content.tsx @@ -15,23 +15,23 @@ import { LogEntryRateResultsContent } from './page_results_content'; import { LogEntryRateSetupContent } from './page_setup_content'; import { LogEntryRateUnavailableContent } from './page_unavailable_content'; import { LogEntryRateSetupStatusUnknownContent } from './page_setup_status_unknown'; -import { useLogEntryRateJobsContext } from './use_log_entry_rate_jobs'; +import { useLogEntryRateModuleContext } from './use_log_entry_rate_module'; export const LogEntryRatePageContent = () => { const { sourceId } = useContext(Source.Context); const { hasLogAnalysisCapabilites } = useContext(LogAnalysisCapabilities.Context); const { - availableIndices, - cleanupAndSetup, + cleanUpAndSetUpModule: cleanupAndSetup, fetchJobStatus, fetchModuleDefinition, lastSetupErrorMessages, - setup, + moduleDescriptor, + setUpModule, setupStatus, - timestampField, + sourceConfiguration, viewResults, - } = useLogEntryRateJobsContext(); + } = useLogEntryRateModuleContext(); useEffect(() => { fetchModuleDefinition(); @@ -60,12 +60,12 @@ export const LogEntryRatePageContent = () => { } else { return ( ); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx index dad7fa1e4cb02..4eae02a9470bf 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx @@ -8,20 +8,21 @@ import React from 'react'; import { useSourceContext } from '../../../containers/source'; import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; -import { LogEntryRateJobsProvider } from './use_log_entry_rate_jobs'; +// import { LogEntryRateJobsProvider } from './use_log_entry_rate_jobs'; +import { LogEntryRateModuleProvider } from './use_log_entry_rate_module'; export const LogEntryRatePageProviders: React.FunctionComponent = ({ children }) => { const { sourceId, source } = useSourceContext(); const spaceId = useKibanaSpaceId(); return ( - {children} - + ); }; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index aaef8f5ed6f8c..3598ca3556707 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -29,7 +29,7 @@ import { useKibanaUiSetting } from '../../../utils/use_kibana_ui_setting'; import { FirstUseCallout } from './first_use'; import { AnomaliesResults } from './sections/anomalies'; import { LogRateResults } from './sections/log_rate'; -import { useLogEntryRateJobsContext } from './use_log_entry_rate_jobs'; +import { useLogEntryRateModuleContext } from './use_log_entry_rate_module'; import { useLogEntryRateResults } from './use_log_entry_rate_results'; import { StringTimeRange, @@ -133,7 +133,7 @@ export const LogEntryRateResultsContent = ({ viewSetupForReconfiguration, viewSetupForUpdate, jobIds, - } = useLogEntryRateJobsContext(); + } = useLogEntryRateModuleContext(); useEffect(() => { getLogEntryRate(); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx index 5453e4aa2874c..ce0b95d4748f4 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx @@ -4,21 +4,23 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; import { EuiPage, EuiPageBody, EuiPageContent, + EuiPageContentBody, EuiPageContentHeader, EuiPageContentHeaderSection, - EuiPageContentBody, + EuiSpacer, EuiText, EuiTitle, - EuiSpacer, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import React from 'react'; + import euiStyled from '../../../../../../common/eui_styled_components'; import { SetupStatus } from '../../../../common/log_analysis'; +import { ModuleDescriptor, ModuleSourceConfiguration } from '../../../containers/logs/log_analysis'; import { useTrackPageview } from '../../../hooks/use_track_metric'; import { LogEntryRateSetupSteps } from './setup'; @@ -28,25 +30,25 @@ type SetupHandler = ( endTime: number | undefined ) => void; -interface LogEntryRateSetupContentProps { - availableIndices: string[]; +interface LogEntryRateSetupContentProps { cleanupAndSetup: SetupHandler; errorMessages: string[]; + moduleDescriptor: ModuleDescriptor; setup: SetupHandler; setupStatus: SetupStatus; - timestampField: string; + sourceConfiguration: ModuleSourceConfiguration; viewResults: () => void; } -export const LogEntryRateSetupContent: React.FunctionComponent = ({ - availableIndices, +export const LogEntryRateSetupContent = ({ cleanupAndSetup, errorMessages, setup, setupStatus, - timestampField, viewResults, -}) => { + moduleDescriptor, + sourceConfiguration, +}: LogEntryRateSetupContentProps) => { useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); @@ -79,13 +81,13 @@ export const LogEntryRateSetupContent: React.FunctionComponent diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx index 585a65b9ad1c8..91662c49adace 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx @@ -25,7 +25,7 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{ onChangeSelectedIndices( indices.map(index => { const checkbox = event.currentTarget; - return index.index === checkbox.id ? { ...index, isSelected: checkbox.checked } : index; + return index.name === checkbox.id ? { ...index, isSelected: checkbox.checked } : index; }) ); }, @@ -35,22 +35,21 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{ const choices = useMemo( () => indices.map(index => { - const validIndex = index.errors.length === 0; const checkbox = ( {index.index}} + key={index.name} + id={index.name} + label={{index.name}} onChange={handleCheckboxChange} - checked={index.isSelected} - disabled={!validIndex} + checked={index.validity === 'valid' && index.isSelected} + disabled={index.validity === 'invalid'} /> ); - return validIndex ? ( + return index.validity === 'valid' ? ( checkbox ) : ( -
+
{checkbox}
); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx index 26d9c1a013725..967c69dfae950 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx @@ -12,6 +12,10 @@ import { SetupStatus } from '../../../../../common/log_analysis'; import { useAnalysisSetupState } from '../../../../containers/logs/log_analysis/log_analysis_setup_state'; import { InitialConfigurationStep } from './initial_configuration_step'; import { ProcessStep } from './process_step'; +import { + ModuleDescriptor, + ModuleSourceConfiguration, +} from '../../../../containers/logs/log_analysis'; type SetupHandler = ( indices: string[], @@ -19,25 +23,25 @@ type SetupHandler = ( endTime: number | undefined ) => void; -interface LogEntryRateSetupStepsProps { - availableIndices: string[]; +interface LogEntryRateSetupStepsProps { cleanupAndSetup: SetupHandler; errorMessages: string[]; setup: SetupHandler; setupStatus: SetupStatus; - timestampField: string; viewResults: () => void; + moduleDescriptor: ModuleDescriptor; + sourceConfiguration: ModuleSourceConfiguration; } -export const LogEntryRateSetupSteps: React.FunctionComponent = ({ - availableIndices, +export const LogEntryRateSetupSteps = ({ cleanupAndSetup: cleanupAndSetupModule, errorMessages, setup: setupModule, setupStatus, - timestampField, viewResults, -}: LogEntryRateSetupStepsProps) => { + moduleDescriptor, + sourceConfiguration, +}: LogEntryRateSetupStepsProps) => { const { setup, cleanupAndSetup, @@ -50,10 +54,10 @@ export const LogEntryRateSetupSteps: React.FunctionComponent { - const jobOverrides = useMemo( - () => [ - { - job_id: 'log-entry-rate' as const, - analysis_config: { - bucket_span: `${bucketSpan}ms`, - }, - data_description: { - time_field: timeField, - }, - custom_settings: { - logs_source_config: { - indexPattern, - timestampField: timeField, - bucketSpan, - }, - }, - }, - ], - [bucketSpan, timeField, indexPattern] - ); - const datafeedOverrides = useMemo(() => [], []); - - return useLogAnalysisJobs({ - bucketSpan, - datafeedOverrides, - indexPattern, - jobOverrides, - jobTypes, - moduleId: 'logs_ui_analysis', - sourceId, - spaceId, - timestampField: timeField, - }); -}; - -export const [LogEntryRateJobsProvider, useLogEntryRateJobsContext] = createContainer( - useLogEntryRateJobs -); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_module.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_module.tsx new file mode 100644 index 0000000000000..ab6a6578601bf --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_module.tsx @@ -0,0 +1,45 @@ +/* + * 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'; +import { useMemo } from 'react'; + +import { + useLogAnalysisModule, + ModuleSourceConfiguration, +} from '../../../containers/logs/log_analysis'; +import { logEntryRateModule } from './module_descriptor'; + +export const useLogEntryRateModule = ({ + indexPattern, + sourceId, + spaceId, + timestampField, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; + timestampField: string; +}) => { + const sourceConfiguration: ModuleSourceConfiguration = useMemo( + () => ({ + indices: indexPattern.split(','), + sourceId, + spaceId, + timestampField, + }), + [indexPattern] + ); + + return useLogAnalysisModule({ + moduleDescriptor: logEntryRateModule, + sourceConfiguration, + }); +}; + +export const [LogEntryRateModuleProvider, useLogEntryRateModuleContext] = createContainer( + useLogEntryRateModule +); diff --git a/x-pack/legacy/plugins/infra/server/infra_server.ts b/x-pack/legacy/plugins/infra/server/infra_server.ts index 0093a6c21af57..1915d2ee2080c 100644 --- a/x-pack/legacy/plugins/infra/server/infra_server.ts +++ b/x-pack/legacy/plugins/infra/server/infra_server.ts @@ -14,8 +14,8 @@ import { createSourceStatusResolvers } from './graphql/source_status'; import { createSourcesResolvers } from './graphql/sources'; import { InfraBackendLibs } from './lib/infra_types'; import { - initLogAnalysisGetLogEntryRateRoute, - initIndexPatternsValidateRoute, + initGetLogEntryRateRoute, + initValidateLogAnalysisIndicesRoute, } from './routes/log_analysis'; import { initMetricExplorerRoute } from './routes/metrics_explorer'; import { initMetadataRoute } from './routes/metadata'; @@ -35,8 +35,8 @@ export const initInfraServer = (libs: InfraBackendLibs) => { libs.framework.registerGraphQLEndpoint('/api/infra/graphql', schema); initIpToHostName(libs); - initLogAnalysisGetLogEntryRateRoute(libs); - initIndexPatternsValidateRoute(libs); + initGetLogEntryRateRoute(libs); + initValidateLogAnalysisIndicesRoute(libs); initMetricExplorerRoute(libs); initMetadataRoute(libs); }; diff --git a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index.ts b/x-pack/legacy/plugins/infra/server/routes/log_analysis/index.ts index 7364d167efe47..378e32cb3582c 100644 --- a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index.ts +++ b/x-pack/legacy/plugins/infra/server/routes/log_analysis/index.ts @@ -5,4 +5,4 @@ */ export * from './results'; -export * from './index_patterns'; +export * from './validation'; diff --git a/x-pack/legacy/plugins/infra/server/routes/log_analysis/results/log_entry_rate.ts b/x-pack/legacy/plugins/infra/server/routes/log_analysis/results/log_entry_rate.ts index fc06ea48f4353..672ee2e793425 100644 --- a/x-pack/legacy/plugins/infra/server/routes/log_analysis/results/log_entry_rate.ts +++ b/x-pack/legacy/plugins/infra/server/routes/log_analysis/results/log_entry_rate.ts @@ -19,10 +19,7 @@ import { import { throwErrors } from '../../../../common/runtime_types'; import { NoLogRateResultsIndexError } from '../../../lib/log_analysis'; -export const initLogAnalysisGetLogEntryRateRoute = ({ - framework, - logAnalysis, -}: InfraBackendLibs) => { +export const initGetLogEntryRateRoute = ({ framework, logAnalysis }: InfraBackendLibs) => { framework.registerRoute({ method: 'POST', path: LOG_ANALYSIS_GET_LOG_ENTRY_RATE_PATH, diff --git a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/index.ts b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/index.ts similarity index 89% rename from x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/index.ts rename to x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/index.ts index a85e119e7318a..727faca69298e 100644 --- a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/index.ts +++ b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './validate'; +export * from './indices'; diff --git a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/validate.ts b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts similarity index 74% rename from x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/validate.ts rename to x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts index 0a369adb7ca29..78aa3ad96cb3b 100644 --- a/x-pack/legacy/plugins/infra/server/routes/log_analysis/index_patterns/validate.ts +++ b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts @@ -11,7 +11,7 @@ import { identity } from 'fp-ts/lib/function'; import { InfraBackendLibs } from '../../../lib/infra_types'; import { - LOG_ANALYSIS_VALIDATION_INDICES_PATH, + LOG_ANALYSIS_VALIDATE_INDICES_PATH, validationIndicesRequestPayloadRT, validationIndicesResponsePayloadRT, ValidationIndicesError, @@ -19,19 +19,17 @@ import { import { throwErrors } from '../../../../common/runtime_types'; -const partitionField = 'event.dataset'; - -export const initIndexPatternsValidateRoute = ({ framework }: InfraBackendLibs) => { +export const initValidateLogAnalysisIndicesRoute = ({ framework }: InfraBackendLibs) => { framework.registerRoute({ method: 'POST', - path: LOG_ANALYSIS_VALIDATION_INDICES_PATH, + path: LOG_ANALYSIS_VALIDATE_INDICES_PATH, handler: async (req, res) => { const payload = pipe( validationIndicesRequestPayloadRT.decode(req.payload), fold(throwErrors(Boom.badRequest), identity) ); - const { timestampField, indices } = payload.data; + const { fields, indices } = payload.data; const errors: ValidationIndicesError[] = []; // Query each pattern individually, to map correctly the errors @@ -39,7 +37,7 @@ export const initIndexPatternsValidateRoute = ({ framework }: InfraBackendLibs) indices.map(async index => { const fieldCaps = await framework.callWithRequest(req, 'fieldCaps', { index, - fields: `${timestampField},${partitionField}`, + fields: fields.map(field => field.name), }); if (fieldCaps.indices.length === 0) { @@ -50,26 +48,23 @@ export const initIndexPatternsValidateRoute = ({ framework }: InfraBackendLibs) return; } - ([ - [timestampField, 'date'], - [partitionField, 'keyword'], - ] as const).forEach(([field, fieldType]) => { - const fieldMetadata = fieldCaps.fields[field]; + fields.forEach(({ name: fieldName, validTypes }) => { + const fieldMetadata = fieldCaps.fields[fieldName]; if (fieldMetadata === undefined) { errors.push({ error: 'FIELD_NOT_FOUND', index, - field, + field: fieldName, }); } else { const fieldTypes = Object.keys(fieldMetadata); - if (fieldTypes.length > 1 || fieldTypes[0] !== fieldType) { + if (!fieldTypes.every(fieldType => validTypes.includes(fieldType))) { errors.push({ error: `FIELD_NOT_VALID`, index, - field, + field: fieldName, }); } } From adb3ea22b2bcf25b59eb40dbb137d8adb7a4e9c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Thu, 28 Nov 2019 17:33:46 +0100 Subject: [PATCH 09/10] Rename telemetry keys for the log rate tab --- .../public/pages/logs/log_entry_rate/page_results_content.tsx | 4 ++-- .../public/pages/logs/log_entry_rate/page_setup_content.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx index 3598ca3556707..be637bc29a0db 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx @@ -45,8 +45,8 @@ export const LogEntryRateResultsContent = ({ sourceId: string; isFirstUse: boolean; }) => { - useTrackPageview({ app: 'infra_logs', path: 'analysis_results' }); - useTrackPageview({ app: 'infra_logs', path: 'analysis_results', delay: 15000 }); + useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_results' }); + useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_results', delay: 15000 }); const [dateFormat] = useKibanaUiSetting('dateFormat', 'MMMM D, YYYY h:mm A'); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx index ce0b95d4748f4..6c04404b91231 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_content.tsx @@ -49,8 +49,8 @@ export const LogEntryRateSetupContent = ({ moduleDescriptor, sourceConfiguration, }: LogEntryRateSetupContentProps) => { - useTrackPageview({ app: 'infra_logs', path: 'analysis_setup' }); - useTrackPageview({ app: 'infra_logs', path: 'analysis_setup', delay: 15000 }); + useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup' }); + useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup', delay: 15000 }); return ( From 099de5cf38a153fd14a6eb65e5a9c7498a63f88b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Tue, 10 Dec 2019 17:46:27 +0100 Subject: [PATCH 10/10] Remove left-over comment --- .../infra/public/pages/logs/log_entry_rate/page_providers.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx index 4eae02a9470bf..67c8ea7660a26 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_providers.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { useSourceContext } from '../../../containers/source'; import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; -// import { LogEntryRateJobsProvider } from './use_log_entry_rate_jobs'; import { LogEntryRateModuleProvider } from './use_log_entry_rate_module'; export const LogEntryRatePageProviders: React.FunctionComponent = ({ children }) => {