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 626e90b65a7d8..8c08e24d8665d 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 categoriesMessageField = 'message'; + export const partitionField = 'event.dataset'; export const getJobIdPrefix = (spaceId: string, sourceId: string) => diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/index.ts b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/index.ts new file mode 100644 index 0000000000000..c7a49a90a7886 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/index.ts @@ -0,0 +1,13 @@ +/* + * 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 './setup_page'; + +export * from './initial_configuration_step'; +export * from './process_step'; + +export * from './ml_unavailable_prompt'; +export * from './setup_status_unknown_prompt'; 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/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx similarity index 95% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_indices_form.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx index 5a4c21670191e..3334e565f70f7 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/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx @@ -8,11 +8,9 @@ import { EuiCode, EuiDescribedFormGroup, EuiFormRow, EuiCheckbox, EuiToolTip } f import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { useCallback, useMemo } from 'react'; -import { - ValidatedIndex, - ValidationIndicesUIError, -} from '../../../../../containers/logs/log_analysis/log_analysis_setup_state'; -import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper'; + +import { LoadingOverlayWrapper } from '../../../loading_overlay_wrapper'; +import { ValidatedIndex, ValidationIndicesUIError } from './validation'; export const AnalysisSetupIndicesForm: React.FunctionComponent<{ indices: ValidatedIndex[]; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx similarity index 98% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_timerange_form.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx index 02a25bf134fef..f45d274169497 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/analysis_setup_timerange_form.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx @@ -17,7 +17,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import moment, { Moment } from 'moment'; import React, { useMemo } from 'react'; -import { euiStyled } from '../../../../../../../../common/eui_styled_components'; +import { euiStyled } from '../../../../../../../common/eui_styled_components'; const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', { defaultMessage: 'Start time', diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/index.ts b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/index.ts similarity index 90% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/index.ts rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/index.ts index c44079f0e19df..e76bc2e34e240 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/index.ts +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/index.ts @@ -5,3 +5,4 @@ */ export * from './initial_configuration_step'; +export * from './validation'; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/initial_configuration_step.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx similarity index 85% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/initial_configuration_step.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx index 3b5497fb91864..2494b802cdb5b 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/initial_configuration_step/initial_configuration_step.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx @@ -5,16 +5,14 @@ */ import { EuiSpacer, EuiForm, EuiCallOut } from '@elastic/eui'; +import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; import { AnalysisSetupIndicesForm } from './analysis_setup_indices_form'; import { AnalysisSetupTimerangeForm } from './analysis_setup_timerange_form'; -import { - ValidatedIndex, - ValidationIndicesUIError, -} from '../../../../../containers/logs/log_analysis/log_analysis_setup_state'; +import { ValidatedIndex, ValidationIndicesUIError } from './validation'; interface InitialConfigurationStepProps { setStartTime: (startTime: number | undefined) => void; @@ -27,6 +25,13 @@ interface InitialConfigurationStepProps { validationErrors?: ValidationIndicesUIError[]; } +export const createInitialConfigurationStep = ( + props: InitialConfigurationStepProps +): EuiContainedStepProps => ({ + title: initialConfigurationStepTitle, + children: , +}); + export const InitialConfigurationStep: React.FunctionComponent = ({ setStartTime, setEndTime, @@ -67,6 +72,13 @@ const errorCalloutTitle = i18n.translate( } ); +const initialConfigurationStepTitle = i18n.translate( + 'xpack.infra.analysisSetup.configurationStepTitle', + { + defaultMessage: 'Configuration', + } +); + const ValidationErrors: React.FC<{ errors: ValidationIndicesUIError[] }> = ({ errors }) => { if (errors.length === 0) { return null; diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/validation.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/validation.tsx new file mode 100644 index 0000000000000..8b733f66ef4a8 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/validation.tsx @@ -0,0 +1,26 @@ +/* + * 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 { ValidationIndicesError } from '../../../../../common/http_api'; + +export type ValidationIndicesUIError = + | ValidationIndicesError + | { error: 'NETWORK_ERROR' } + | { error: 'TOO_FEW_SELECTED_INDICES' }; + +interface ValidIndex { + validity: 'valid'; + name: string; + isSelected: boolean; +} + +interface InvalidIndex { + validity: 'invalid'; + name: string; + errors: ValidationIndicesError[]; +} + +export type ValidatedIndex = ValidIndex | InvalidIndex; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_unavailable_content.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/ml_unavailable_prompt.tsx similarity index 73% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_unavailable_content.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/ml_unavailable_prompt.tsx index c77e5d408fe5f..63e1bb23a2d82 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_unavailable_content.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/ml_unavailable_prompt.tsx @@ -4,26 +4,27 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import { EuiButton, EuiEmptyPrompt, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiEmptyPrompt, EuiLink, EuiButton } from '@elastic/eui'; +import React from 'react'; + import euiStyled from '../../../../../../common/eui_styled_components'; -export const LogEntryRateUnavailableContent: React.FunctionComponent<{}> = () => ( +export const MlUnavailablePrompt: React.FunctionComponent<{}> = () => ( } body={

= () => } actions={ - {i18n.translate('xpack.infra.logs.analysisPage.unavailable.mlAppButton', { + {i18n.translate('xpack.infra.logs.analysis.mlAppButton', { defaultMessage: 'Open Machine Learning', })} diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/create_ml_jobs_button.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/create_ml_jobs_button.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/create_ml_jobs_button.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/create_ml_jobs_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/index.ts b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/index.ts similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/index.ts rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/index.ts diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/process_step.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/process_step.tsx similarity index 79% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/process_step.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/process_step.tsx index 978e45e26b733..a15c7335b4acb 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/process_step.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/process_step.tsx @@ -14,28 +14,42 @@ import { EuiCallOut, EuiCode, } from '@elastic/eui'; +import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React from 'react'; -import { SetupStatus } from '../../../../../../common/log_analysis'; +import { SetupStatus } from '../../../../../common/log_analysis'; import { CreateMLJobsButton } from './create_ml_jobs_button'; import { RecreateMLJobsButton } from './recreate_ml_jobs_button'; interface ProcessStepProps { - cleanupAndSetup: () => void; + cleanUpAndSetUp: () => void; errorMessages: string[]; isConfigurationValid: boolean; - setup: () => void; + setUp: () => void; setupStatus: SetupStatus; viewResults: () => void; } +export const createProcessStep = (props: ProcessStepProps): EuiContainedStepProps => ({ + title: processStepTitle, + children: , + status: + props.setupStatus === 'pending' + ? 'incomplete' + : props.setupStatus === 'failed' + ? 'danger' + : props.setupStatus === 'succeeded' + ? 'complete' + : undefined, +}); + export const ProcessStep: React.FunctionComponent = ({ - cleanupAndSetup, + cleanUpAndSetUp, errorMessages, isConfigurationValid, - setup, + setUp, setupStatus, viewResults, }) => { @@ -66,7 +80,7 @@ export const ProcessStep: React.FunctionComponent = ({ ))} - + = ({ ) : setupStatus === 'requiredForUpdate' || setupStatus === 'requiredForReconfiguration' ? ( - + ) : ( - + )} ); @@ -102,3 +116,7 @@ const errorCalloutTitle = i18n.translate( defaultMessage: 'An error occurred', } ); + +const processStepTitle = i18n.translate('xpack.infra.analysisSetup.actionStepTitle', { + defaultMessage: 'Create ML job', +}); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/recreate_ml_jobs_button.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/recreate_ml_jobs_button.tsx similarity index 100% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/process_step/recreate_ml_jobs_button.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/process_step/recreate_ml_jobs_button.tsx diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_page.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_page.tsx new file mode 100644 index 0000000000000..a1c35aff0cf83 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_page.tsx @@ -0,0 +1,59 @@ +/* + * 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 { + CommonProps, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiTitle, +} from '@elastic/eui'; +import React from 'react'; + +import euiStyled from '../../../../../../common/eui_styled_components'; + +export const LogAnalysisSetupPage: React.FunctionComponent = ({ + children, + ...rest +}) => { + return ( + + + + {children} + + + + ); +}; + +export const LogAnalysisSetupPageHeader: React.FunctionComponent = ({ children }) => ( + + + +

{children}

+ + + +); + +export const LogAnalysisSetupPageContent = EuiPageContentBody; + +// !important due to https://github.com/elastic/eui/issues/2232 +const LogEntryRateSetupPageContent = euiStyled(EuiPageContent)` + max-width: 768px !important; +`; + +const LogEntryRateSetupPage = euiStyled(EuiPage)` + height: 100%; +`; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_status_unknown_prompt.tsx similarity index 79% rename from x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx rename to x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_status_unknown_prompt.tsx index 4c685bd42b937..f65ff6a1eec78 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_setup_status_unknown.tsx +++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/setup_status_unknown_prompt.tsx @@ -14,21 +14,21 @@ interface Props { retry: () => void; } -export const LogEntryRateSetupStatusUnknownContent: React.FunctionComponent = ({ +export const LogAnalysisSetupStatusUnknownPrompt: React.FunctionComponent = ({ retry, }: Props) => ( } actions={ retry()} color="primary" fill> - {i18n.translate('xpack.infra.logs.analysisPage.setupStatusUnknown.tryAgainButton', { + {i18n.translate('xpack.infra.logs.analysis.setupStatusTryAgainButton', { defaultMessage: 'Try again', })} 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 91e517b0db008..2e1ba52353bef 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 @@ -49,6 +49,7 @@ const datafeedStateRT = rt.keyof({ const jobStateRT = rt.keyof({ closed: null, closing: null, + deleting: null, failed: null, opened: null, opening: null, 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 eb044c86e50fe..185f6936662bd 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 @@ -9,3 +9,4 @@ export * from './log_analysis_cleanup'; export * from './log_analysis_module'; export * from './log_analysis_module_status'; export * from './log_analysis_module_types'; +export * from './log_analysis_setup_state'; 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 74dbb3c7a8062..9f966ed3342e6 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 @@ -6,8 +6,11 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; -import { ValidationIndicesError } from '../../../../common/http_api'; import { isExampleDataIndex } from '../../../../common/log_analysis'; +import { + ValidatedIndex, + ValidationIndicesUIError, +} from '../../../components/logging/log_analysis_setup/initial_configuration_step'; import { useTrackedPromise } from '../../../utils/use_tracked_promise'; import { ModuleDescriptor, ModuleSourceConfiguration } from './log_analysis_module_types'; @@ -17,38 +20,19 @@ type SetupHandler = ( endTime: number | undefined ) => void; -export type ValidationIndicesUIError = - | ValidationIndicesError - | { error: 'NETWORK_ERROR' } - | { error: 'TOO_FEW_SELECTED_INDICES' }; - -interface ValidIndex { - validity: 'valid'; - name: string; - isSelected: boolean; -} - -interface InvalidIndex { - validity: 'invalid'; - name: string; - errors: ValidationIndicesError[]; -} - -export type ValidatedIndex = ValidIndex | InvalidIndex; - interface AnalysisSetupStateArguments { - cleanupAndSetupModule: SetupHandler; + cleanUpAndSetUpModule: SetupHandler; moduleDescriptor: ModuleDescriptor; - setupModule: SetupHandler; + setUpModule: SetupHandler; sourceConfiguration: ModuleSourceConfiguration; } const fourWeeksInMs = 86400000 * 7 * 4; export const useAnalysisSetupState = ({ - cleanupAndSetupModule, + cleanUpAndSetUpModule, moduleDescriptor: { validateSetupIndices }, - setupModule, + setUpModule, sourceConfiguration, }: AnalysisSetupStateArguments) => { const [startTime, setStartTime] = useState(Date.now() - fourWeeksInMs); @@ -107,13 +91,13 @@ export const useAnalysisSetupState = ({ [validatedIndices] ); - const setup = useCallback(() => { - return setupModule(selectedIndexNames, startTime, endTime); - }, [setupModule, selectedIndexNames, startTime, endTime]); + const setUp = useCallback(() => { + return setUpModule(selectedIndexNames, startTime, endTime); + }, [setUpModule, selectedIndexNames, startTime, endTime]); - const cleanupAndSetup = useCallback(() => { - return cleanupAndSetupModule(selectedIndexNames, startTime, endTime); - }, [cleanupAndSetupModule, selectedIndexNames, startTime, endTime]); + const cleanUpAndSetUp = useCallback(() => { + return cleanUpAndSetUpModule(selectedIndexNames, startTime, endTime); + }, [cleanUpAndSetUpModule, selectedIndexNames, startTime, endTime]); const isValidating = useMemo( () => @@ -143,13 +127,13 @@ export const useAnalysisSetupState = ({ }, [isValidating, validateIndicesRequest.state, selectedIndexNames, validatedIndices]); return { - cleanupAndSetup, + cleanUpAndSetUp, endTime, isValidating, selectedIndexNames, setEndTime, setStartTime, - setup, + setUp, startTime, validatedIndices, setValidatedIndices, 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 4eddecf732f75..b0619fdcc2acf 100644 --- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx @@ -21,13 +21,14 @@ import { Source, useSource } from '../../containers/source'; import { StreamPage } from './stream'; import { SettingsPage } from '../shared/settings'; import { AppNavigation } from '../../components/navigation/app_navigation'; -import { LogEntryRatePage } from './log_entry_rate'; import { useLogAnalysisCapabilities, LogAnalysisCapabilities, } from '../../containers/logs/log_analysis'; import { useSourceId } from '../../containers/source_id'; import { RedirectWithQueryParams } from '../../utils/redirect_with_query_params'; +import { LogEntryCategoriesPage } from './log_entry_categories'; +import { LogEntryRatePage } from './log_entry_rate'; interface LogsPageProps extends RouteComponentProps { uiCapabilities: UICapabilities; @@ -53,6 +54,16 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag path: `${match.path}/log-rate`, }; + const logCategoriesTab = { + title: ( + <> + {logCategoriesTabTitle} + + + ), + path: `${match.path}/log-categories`, + }; + const settingsTab = { title: settingsTabTitle, path: `${match.path}/settings`, @@ -90,7 +101,7 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag @@ -99,6 +110,7 @@ export const LogsPage = injectUICapabilities(({ match, uiCapabilities }: LogsPag + + 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-categories-count' 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'], + }, + { + name: categoriesMessageField, + validTypes: ['text'], + }, + ]); +}; + +export const logEntryCategoriesModule: ModuleDescriptor = { + moduleId, + jobTypes, + bucketSpan, + getJobIds, + getJobSummary, + getModuleDefinition, + setUpModule, + cleanUpModule, + validateSetupIndices, +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page.tsx new file mode 100644 index 0000000000000..64e83a6eaa497 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import { ColumnarPage } from '../../../components/page'; +import { LogEntryCategoriesPageContent } from './page_content'; +import { LogEntryCategoriesPageProviders } from './page_providers'; + +export const LogEntryCategoriesPage = () => { + return ( + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx new file mode 100644 index 0000000000000..9a50acf622ee1 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_content.tsx @@ -0,0 +1,52 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import React, { useContext, useEffect } from 'react'; + +import { isSetupStatusWithResults } from '../../../../common/log_analysis'; +import { LoadingPage } from '../../../components/loading_page'; +import { + LogAnalysisSetupStatusUnknownPrompt, + MlUnavailablePrompt, +} from '../../../components/logging/log_analysis_setup'; +import { LogAnalysisCapabilities } from '../../../containers/logs/log_analysis'; +import { LogEntryCategoriesSetupContent } from './page_setup_content'; +import { useLogEntryCategoriesModuleContext } from './use_log_entry_categories_module'; + +export const LogEntryCategoriesPageContent = () => { + const { hasLogAnalysisCapabilites } = useContext(LogAnalysisCapabilities.Context); + + const { + fetchJobStatus, + fetchModuleDefinition, + setupStatus, + } = useLogEntryCategoriesModuleContext(); + + useEffect(() => { + fetchModuleDefinition(); + fetchJobStatus(); + }, [fetchJobStatus, fetchModuleDefinition]); + + if (!hasLogAnalysisCapabilites) { + return ; + } else if (setupStatus === 'initializing') { + return ( + + ); + } else if (setupStatus === 'unknown') { + return ; + } else if (isSetupStatusWithResults(setupStatus)) { + return null; + // return ; + } else { + return ; + } +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx new file mode 100644 index 0000000000000..619cea6eda8b7 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_providers.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import { useSourceContext } from '../../../containers/source'; +import { useKibanaSpaceId } from '../../../utils/use_kibana_space_id'; +import { LogEntryCategoriesModuleProvider } from './use_log_entry_categories_module'; + +export const LogEntryCategoriesPageProviders: 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_categories/page_setup_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_setup_content.tsx new file mode 100644 index 0000000000000..f0e90cb7ccc05 --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_setup_content.tsx @@ -0,0 +1,99 @@ +/* + * 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 { EuiSpacer, EuiSteps, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React, { useMemo } from 'react'; + +import { + createInitialConfigurationStep, + createProcessStep, + LogAnalysisSetupPage, + LogAnalysisSetupPageContent, + LogAnalysisSetupPageHeader, +} from '../../../components/logging/log_analysis_setup'; +import { useTrackPageview } from '../../../hooks/use_track_metric'; +import { useLogEntryCategoriesSetup } from './use_log_entry_categories_setup'; + +export const LogEntryCategoriesSetupContent: React.FunctionComponent = () => { + useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_setup' }); + useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_setup', delay: 15000 }); + + const { + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + } = useLogEntryCategoriesSetup(); + + const steps = useMemo( + () => [ + createInitialConfigurationStep({ + setStartTime, + setEndTime, + startTime, + endTime, + isValidating, + validatedIndices, + setValidatedIndices, + validationErrors, + }), + createProcessStep({ + cleanUpAndSetUp, + errorMessages: lastSetupErrorMessages, + isConfigurationValid: validationErrors.length <= 0, + setUp, + setupStatus, + viewResults, + }), + ], + [ + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setUp, + setValidatedIndices, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + ] + ); + + return ( + + + + + + + + + + + + + ); +}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx new file mode 100644 index 0000000000000..918c252f6350c --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_module.tsx @@ -0,0 +1,46 @@ +/* + * 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 { logEntryCategoriesModule } from './module_descriptor'; + +export const useLogEntryCategoriesModule = ({ + indexPattern, + sourceId, + spaceId, + timestampField, +}: { + indexPattern: string; + sourceId: string; + spaceId: string; + timestampField: string; +}) => { + const sourceConfiguration: ModuleSourceConfiguration = useMemo( + () => ({ + indices: indexPattern.split(','), + sourceId, + spaceId, + timestampField, + }), + [indexPattern, sourceId, spaceId, timestampField] + ); + + return useLogAnalysisModule({ + moduleDescriptor: logEntryCategoriesModule, + sourceConfiguration, + }); +}; + +export const [ + LogEntryCategoriesModuleProvider, + useLogEntryCategoriesModuleContext, +] = createContainer(useLogEntryCategoriesModule); diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_setup.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_setup.tsx new file mode 100644 index 0000000000000..c011230942d7c --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/use_log_entry_categories_setup.tsx @@ -0,0 +1,54 @@ +/* + * 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 { useAnalysisSetupState } from '../../../containers/logs/log_analysis'; +import { useLogEntryCategoriesModuleContext } from './use_log_entry_categories_module'; + +export const useLogEntryCategoriesSetup = () => { + const { + cleanUpAndSetUpModule, + lastSetupErrorMessages, + moduleDescriptor, + setUpModule, + setupStatus, + sourceConfiguration, + viewResults, + } = useLogEntryCategoriesModuleContext(); + + const { + cleanUpAndSetUp, + endTime, + isValidating, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + startTime, + validatedIndices, + validationErrors, + } = useAnalysisSetupState({ + cleanUpAndSetUpModule, + moduleDescriptor, + setUpModule, + sourceConfiguration, + }); + + return { + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + }; +}; 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 e71985f73fbb8..a80464ed42cb2 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,29 +9,19 @@ import React, { useContext, useEffect } from 'react'; import { isSetupStatusWithResults } from '../../../../common/log_analysis'; import { LoadingPage } from '../../../components/loading_page'; +import { + LogAnalysisSetupStatusUnknownPrompt, + MlUnavailablePrompt, +} from '../../../components/logging/log_analysis_setup'; 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 { useLogEntryRateModuleContext } from './use_log_entry_rate_module'; export const LogEntryRatePageContent = () => { - const { sourceId } = useContext(Source.Context); const { hasLogAnalysisCapabilites } = useContext(LogAnalysisCapabilities.Context); - const { - cleanUpAndSetUpModule: cleanupAndSetup, - fetchJobStatus, - fetchModuleDefinition, - lastSetupErrorMessages, - moduleDescriptor, - setUpModule, - setupStatus, - sourceConfiguration, - viewResults, - } = useLogEntryRateModuleContext(); + const { fetchJobStatus, fetchModuleDefinition, setupStatus } = useLogEntryRateModuleContext(); useEffect(() => { fetchModuleDefinition(); @@ -39,7 +29,7 @@ export const LogEntryRatePageContent = () => { }, [fetchJobStatus, fetchModuleDefinition]); if (!hasLogAnalysisCapabilites) { - return ; + return ; } else if (setupStatus === 'initializing') { return ( { /> ); } else if (setupStatus === 'unknown') { - return ; + return ; } else if (isSetupStatusWithResults(setupStatus)) { - return ( - - ); + return ; } else { - return ( - - ); + return ; } }; 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 be637bc29a0db..b6ab8acdea5b2 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 @@ -38,18 +38,22 @@ import { const JOB_STATUS_POLLING_INTERVAL = 30000; -export const LogEntryRateResultsContent = ({ - sourceId, - isFirstUse, -}: { - sourceId: string; - isFirstUse: boolean; -}) => { +export const LogEntryRateResultsContent: React.FunctionComponent = () => { 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'); + const { + fetchJobStatus, + jobStatus, + setupStatus, + viewSetupForReconfiguration, + viewSetupForUpdate, + jobIds, + sourceConfiguration: { sourceId }, + } = useLogEntryRateModuleContext(); + const { timeRange: selectedTimeRange, setTimeRange: setSelectedTimeRange, @@ -126,14 +130,7 @@ export const LogEntryRateResultsContent = ({ [setAutoRefresh] ); - const { - fetchJobStatus, - jobStatus, - setupStatus, - viewSetupForReconfiguration, - viewSetupForUpdate, - jobIds, - } = useLogEntryRateModuleContext(); + const isFirstUse = useMemo(() => setupStatus === 'hiddenAfterSuccess', [setupStatus]); 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 6c04404b91231..7e90cf29072e1 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,103 +4,96 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - EuiPage, - EuiPageBody, - EuiPageContent, - EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiSpacer, - EuiText, - EuiTitle, -} from '@elastic/eui'; +import { EuiSpacer, EuiSteps, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; +import React, { useMemo } from 'react'; -import euiStyled from '../../../../../../common/eui_styled_components'; -import { SetupStatus } from '../../../../common/log_analysis'; -import { ModuleDescriptor, ModuleSourceConfiguration } from '../../../containers/logs/log_analysis'; +import { + createInitialConfigurationStep, + createProcessStep, + LogAnalysisSetupPage, + LogAnalysisSetupPageContent, + LogAnalysisSetupPageHeader, +} from '../../../components/logging/log_analysis_setup'; import { useTrackPageview } from '../../../hooks/use_track_metric'; -import { LogEntryRateSetupSteps } from './setup'; - -type SetupHandler = ( - indices: string[], - startTime: number | undefined, - endTime: number | undefined -) => void; +import { useLogEntryRateSetup } from './use_log_entry_rate_setup'; -interface LogEntryRateSetupContentProps { - cleanupAndSetup: SetupHandler; - errorMessages: string[]; - moduleDescriptor: ModuleDescriptor; - setup: SetupHandler; - setupStatus: SetupStatus; - sourceConfiguration: ModuleSourceConfiguration; - viewResults: () => void; -} - -export const LogEntryRateSetupContent = ({ - cleanupAndSetup, - errorMessages, - setup, - setupStatus, - viewResults, - moduleDescriptor, - sourceConfiguration, -}: LogEntryRateSetupContentProps) => { +export const LogEntryRateSetupContent: React.FunctionComponent = () => { useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup' }); useTrackPageview({ app: 'infra_logs', path: 'log_entry_rate_setup', delay: 15000 }); + const { + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + } = useLogEntryRateSetup(); + + const steps = useMemo( + () => [ + createInitialConfigurationStep({ + setStartTime, + setEndTime, + startTime, + endTime, + isValidating, + validatedIndices, + setValidatedIndices, + validationErrors, + }), + createProcessStep({ + cleanUpAndSetUp, + errorMessages: lastSetupErrorMessages, + isConfigurationValid: validationErrors.length <= 0, + setUp, + setupStatus, + viewResults, + }), + ], + [ + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setUp, + setValidatedIndices, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + ] + ); + return ( - - - - - - -

- -

-
-
-
- - - - - - - -
-
-
+ + + + + + + + + + + + ); }; - -// !important due to https://github.com/elastic/eui/issues/2232 -const LogEntryRateSetupPageContent = euiStyled(EuiPageContent)` - max-width: 768px !important; -`; - -const LogEntryRateSetupPage = euiStyled(EuiPage)` - height: 100%; -`; 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 38aa4b068c9e9..e5e719c2d69f6 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 @@ -12,6 +12,7 @@ import { EuiStat, EuiTitle, EuiLoadingSpinner, + EuiButton, } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; @@ -97,6 +98,11 @@ export const AnomaliesResults: React.FunctionComponent<{

{title}

+ + + Recreate jobs + + 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 deleted file mode 100644 index 967c69dfae950..0000000000000 --- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/setup/setup_steps.tsx +++ /dev/null @@ -1,107 +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 { EuiSteps, EuiStepStatus } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; - -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[], - startTime: number | undefined, - endTime: number | undefined -) => void; - -interface LogEntryRateSetupStepsProps { - cleanupAndSetup: SetupHandler; - errorMessages: string[]; - setup: SetupHandler; - setupStatus: SetupStatus; - viewResults: () => void; - moduleDescriptor: ModuleDescriptor; - sourceConfiguration: ModuleSourceConfiguration; -} - -export const LogEntryRateSetupSteps = ({ - cleanupAndSetup: cleanupAndSetupModule, - errorMessages, - setup: setupModule, - setupStatus, - viewResults, - moduleDescriptor, - sourceConfiguration, -}: LogEntryRateSetupStepsProps) => { - const { - setup, - cleanupAndSetup, - setStartTime, - setEndTime, - startTime, - endTime, - isValidating, - validationErrors, - validatedIndices, - setValidatedIndices, - } = useAnalysisSetupState({ - cleanupAndSetupModule, - moduleDescriptor, - setupModule, - sourceConfiguration, - }); - - const steps = [ - { - title: i18n.translate('xpack.infra.analysisSetup.configurationStepTitle', { - defaultMessage: 'Configuration', - }), - children: ( - - ), - }, - { - title: i18n.translate('xpack.infra.analysisSetup.actionStepTitle', { - defaultMessage: 'Create ML job', - }), - children: ( - - ), - status: - setupStatus === 'pending' - ? ('incomplete' as EuiStepStatus) - : setupStatus === 'failed' - ? ('danger' as EuiStepStatus) - : setupStatus === 'succeeded' - ? ('complete' as EuiStepStatus) - : undefined, - }, - ]; - - return ; -}; diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_setup.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_setup.tsx new file mode 100644 index 0000000000000..3595b6bf830fc --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/use_log_entry_rate_setup.tsx @@ -0,0 +1,54 @@ +/* + * 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 { useAnalysisSetupState } from '../../../containers/logs/log_analysis'; +import { useLogEntryRateModuleContext } from './use_log_entry_rate_module'; + +export const useLogEntryRateSetup = () => { + const { + cleanUpAndSetUpModule, + lastSetupErrorMessages, + moduleDescriptor, + setUpModule, + setupStatus, + sourceConfiguration, + viewResults, + } = useLogEntryRateModuleContext(); + + const { + cleanUpAndSetUp, + endTime, + isValidating, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + startTime, + validatedIndices, + validationErrors, + } = useAnalysisSetupState({ + cleanUpAndSetUpModule, + moduleDescriptor, + setUpModule, + sourceConfiguration, + }); + + return { + cleanUpAndSetUp, + endTime, + isValidating, + lastSetupErrorMessages, + setEndTime, + setStartTime, + setValidatedIndices, + setUp, + setupStatus, + startTime, + validatedIndices, + validationErrors, + viewResults, + }; +}; diff --git a/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts index ba143a597b66d..fe579124cfe10 100644 --- a/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts +++ b/x-pack/legacy/plugins/infra/server/routes/log_analysis/validation/indices.ts @@ -42,8 +42,10 @@ export const initValidateLogAnalysisIndicesRoute = ({ framework }: InfraBackendL await Promise.all( indices.map(async index => { const fieldCaps = await framework.callWithRequest(requestContext, 'fieldCaps', { - index, + allow_no_indices: true, fields: fields.map(field => field.name), + ignore_unavailable: true, + index, }); if (fieldCaps.indices.length === 0) { diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js b/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js index 8da91822fcd59..cb268ffede7fa 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/__tests__/data_recognizer.js @@ -16,6 +16,7 @@ describe('ML - data recognizer', () => { 'auditbeat_process_docker_ecs', 'auditbeat_process_hosts_ecs', 'logs_ui_analysis', + 'logs_ui_categories', 'metricbeat_system_ecs', 'nginx_ecs', 'sample_data_ecommerce', diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json index 5279b18fb03b3..42ba15591e5c4 100644 --- a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/ml/log_entry_rate.json @@ -1,6 +1,6 @@ { "job_type": "anomaly_detector", - "description": "Detect anomalies in the log entry ingestion rate", + "description": "Logs UI: Detects anomalies in the log entry ingestion rate", "groups": ["logs-ui"], "analysis_config": { "bucket_span": "15m", diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json new file mode 100644 index 0000000000000..26b404ff331c6 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/logo.json @@ -0,0 +1,3 @@ +{ + "icon": "logsApp" +} diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json new file mode 100644 index 0000000000000..b31ddacde8b6d --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json @@ -0,0 +1,20 @@ +{ + "id": "logs_ui_categories", + "title": "Log entry categories", + "description": "Detect anomalies in count of log entries by category", + "type": "Logs", + "logoFile": "logo.json", + "jobs": [ + { + "id": "log-entry-categories-count", + "file": "log_entry_categories_count.json" + } + ], + "datafeeds": [ + { + "id": "datafeed-log-entry-categories-count", + "file": "datafeed_log_entry_categories_count.json", + "job_id": "log-entry-categories-count" + } + ] +} diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json new file mode 100644 index 0000000000000..6e117b4de87ea --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/datafeed_log_entry_categories_count.json @@ -0,0 +1,15 @@ +{ + "job_id": "JOB_ID", + "indices": ["INDEX_PATTERN_NAME"], + "query": { + "bool": { + "filter": [ + { + "exists": { + "field": "message" + } + } + ] + } + } +} diff --git a/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json new file mode 100644 index 0000000000000..b4fb242f16522 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/ml/log_entry_categories_count.json @@ -0,0 +1,34 @@ +{ + "job_type": "anomaly_detector", + "description": "Logs UI: Detects anomalies in count of log entries by category", + "groups": ["logs-ui"], + "analysis_config": { + "bucket_span": "15m", + "categorization_field_name": "message", + "detectors": [ + { + "by_field_name": "mlcategory", + "detector_description": "count by learned log entry category", + "function": "count", + "partition_field_name": "event.dataset", + "use_null": true + } + ], + "influencers": ["event.dataset", "mlcategory"] + }, + "analysis_limits": { + "model_memory_limit": "100mb", + "categorization_examples_limit": 1 + }, + "data_description": { + "time_field": "@timestamp", + "time_format": "epoch_ms" + }, + "model_plot_config": { + "enabled": true + }, + "custom_settings": { + "created_by": "ml-module-logs-ui-categories", + "job_revision": 0 + } +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 38043dcdf8b2b..d2373261fb1f6 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6077,13 +6077,9 @@ "xpack.infra.logs.analysis.logRateSectionNoDataTitle": "表示するデータがありません。", "xpack.infra.logs.analysis.logRateSectionTitle": "ログレート", "xpack.infra.logs.analysisPage.loadingMessage": "分析ジョブのステータスを確認中…", - "xpack.infra.logs.analysisPage.unavailable.mlAppButton": "機械学習を開く", "xpack.infra.logs.analysisPage.unavailable.mlAppLink": "機械学習アプリ", - "xpack.infra.logs.analysisPage.unavailable.mlDisabledBody": "詳細は {machineLearningAppLink} をご覧ください。", - "xpack.infra.logs.analysisPage.unavailable.mLDisabledTitle": "分析機能には機械学習が必要です", "xpack.infra.logs.highlights.goToNextHighlightButtonLabel": "次のハイライトにスキップ", "xpack.infra.logs.highlights.goToPreviousHighlightButtonLabel": "前のハイライトにスキップ", - "xpack.infra.logs.index.analysisBetaBadgeTitle": "分析", "xpack.infra.logs.index.settingsTabTitle": "設定", "xpack.infra.logs.index.streamTabTitle": "ストリーム", "xpack.infra.logs.logsAnalysisResults.onboardingSuccessContent": "機械学習ロボットがデータの収集を開始するまでしばらくお待ちください。", @@ -6174,8 +6170,6 @@ "xpack.infra.logs.analysis.overallAnomalyChartMaxScoresLabel": "最高異常スコア", "xpack.infra.logs.analysis.partitionMaxAnomalyScoreAnnotationLabel": "最高異常スコア: {maxAnomalyScore}", "xpack.infra.logs.analysis.recreateJobButtonLabel": "ML ジョブを再作成", - "xpack.infra.logs.analysisPage.setupStatusUnknown.title": "ML ジョブのステータスを特定できませんでした。", - "xpack.infra.logs.analysisPage.setupStatusUnknown.tryAgainButton": "再試行", "xpack.infra.logs.jumpToTailText": "最も新しいエントリーに移動", "xpack.infra.metricsExplorer.chartOptions.barLabel": "バー", "xpack.infra.nodeDetails.labels.availabilityZone": "アベイラビリティゾーン", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9f2e404bd8c6c..d59d50a8de1b5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6079,13 +6079,9 @@ "xpack.infra.logs.analysis.logRateSectionNoDataTitle": "没有可显示的数据。", "xpack.infra.logs.analysis.logRateSectionTitle": "日志速率", "xpack.infra.logs.analysisPage.loadingMessage": "正在检查分析作业的状态......", - "xpack.infra.logs.analysisPage.unavailable.mlAppButton": "打开 Machine Learning", "xpack.infra.logs.analysisPage.unavailable.mlAppLink": "Machine Learning 应用", - "xpack.infra.logs.analysisPage.unavailable.mlDisabledBody": "查看 {machineLearningAppLink}以了解更多信息。", - "xpack.infra.logs.analysisPage.unavailable.mLDisabledTitle": "分析功能需要 Machine Learning", "xpack.infra.logs.highlights.goToNextHighlightButtonLabel": "跳转到下一高亮条目", "xpack.infra.logs.highlights.goToPreviousHighlightButtonLabel": "跳转到上一高亮条目", - "xpack.infra.logs.index.analysisBetaBadgeTitle": "分析", "xpack.infra.logs.index.settingsTabTitle": "设置", "xpack.infra.logs.index.streamTabTitle": "流式传输", "xpack.infra.logs.logsAnalysisResults.onboardingSuccessContent": "请注意,我们的 Machine Learning 机器人若干分钟后才会开始收集数据。", @@ -6176,8 +6172,6 @@ "xpack.infra.logs.analysis.overallAnomalyChartMaxScoresLabel": "最大异常分数:", "xpack.infra.logs.analysis.partitionMaxAnomalyScoreAnnotationLabel": "最大异常分数:{maxAnomalyScore}", "xpack.infra.logs.analysis.recreateJobButtonLabel": "重新创建 ML 作业", - "xpack.infra.logs.analysisPage.setupStatusUnknown.title": "我们无法确定您的 ML 作业的状态。", - "xpack.infra.logs.analysisPage.setupStatusUnknown.tryAgainButton": "请重试", "xpack.infra.logs.jumpToTailText": "跳到最近的条目", "xpack.infra.metricsExplorer.chartOptions.barLabel": "条形图", "xpack.infra.nodeDetails.labels.availabilityZone": "可用区",