diff --git a/x-pack/legacy/plugins/ml/common/types/jobs.test.js b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.test.ts similarity index 59% rename from x-pack/legacy/plugins/ml/common/types/jobs.test.js rename to x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.test.ts index 02a6500403cf38..dce107a4923184 100644 --- a/x-pack/legacy/plugins/ml/common/types/jobs.test.js +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.test.ts @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import jobConfigFarequote from './__mocks__/job_config_farequote'; -import { isMlJob, isMlJobs } from './jobs'; +// @ts-ignore importing JSON file +import jobConfigFarequote from '../__mocks__/job_config_farequote'; +import { isCombinedJobWithStats } from './combined_job'; describe('Types: Jobs', () => { test('Minimal integrity check.', () => { - expect(isMlJob(jobConfigFarequote)).toBe(true); - expect(isMlJobs([jobConfigFarequote])).toBe(true); + expect(isCombinedJobWithStats(jobConfigFarequote)).toBe(true); }); }); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/combined_job.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.ts similarity index 63% rename from x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/combined_job.ts rename to x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.ts index 435b7696af398d..6df7643c5221fb 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/combined_job.ts +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/combined_job.ts @@ -6,14 +6,25 @@ import { cloneDeep } from 'lodash'; import { Datafeed } from './datafeed'; +import { DatafeedStats } from './datafeed_stats'; import { Job } from './job'; +import { JobStats } from './job_stats'; + +export type JobWithStats = Job & JobStats; +export type DatafeedWithStats = Datafeed & DatafeedStats; // in older implementations of the job config, the datafeed was placed inside the job // for convenience. export interface CombinedJob extends Job { + calendars?: string[]; datafeed_config: Datafeed; } +export interface CombinedJobWithStats extends JobWithStats { + calendars?: string[]; + datafeed_config: DatafeedWithStats; +} + export function expandCombinedJobConfig(combinedJob: CombinedJob) { const combinedJobClone = cloneDeep(combinedJob); const job = combinedJobClone; @@ -22,3 +33,7 @@ export function expandCombinedJobConfig(combinedJob: CombinedJob) { return { job, datafeed }; } + +export function isCombinedJobWithStats(arg: any): arg is CombinedJobWithStats { + return typeof arg.job_id === 'string'; +} diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts similarity index 85% rename from x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts rename to x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts index 538b225926f652..47ff618ffa77f9 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed.ts +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexPatternTitle } from '../../../../../../../common/types/kibana'; +import { IndexPatternTitle } from '../kibana'; import { JobId } from './job'; export type DatafeedId = string; @@ -15,11 +15,8 @@ export interface Datafeed { chunking_config?: ChunkingConfig; frequency?: string; indices: IndexPatternTitle[]; - /** - * The datafeed can contain indexes and indices - */ - indexes?: IndexPatternTitle[]; - job_id?: JobId; + indexes?: IndexPatternTitle[]; // The datafeed can contain indexes and indices + job_id: JobId; query: object; query_delay?: string; script_fields?: object; diff --git a/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts new file mode 100644 index 00000000000000..f1bb56b5337ab8 --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts @@ -0,0 +1,25 @@ +/* + * 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 { Node } from './job_stats'; +import { DATAFEED_STATE } from '../../constants/states'; + +export interface DatafeedStats { + datafeed_id: string; + state: DATAFEED_STATE; + node: Node; + assignment_explanation: string; + timing_stats: TimingStats; +} + +interface TimingStats { + job_id: string; + search_count: number; + bucket_count: number; + total_search_time_ms: number; + average_search_time_per_bucket_ms: number; + exponential_average_search_time_per_hour_ms: number; +} diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/index.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/index.ts similarity index 77% rename from x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/index.ts rename to x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/index.ts index c8b71ead4b6fb4..9c299c628426a5 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/index.ts +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/index.ts @@ -5,5 +5,8 @@ */ export * from './job'; +export * from './job_stats'; export * from './datafeed'; +export * from './datafeed_stats'; export * from './combined_job'; +export * from './summary_job'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/job.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job.ts similarity index 85% rename from x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/job.ts rename to x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job.ts index 3246f8ae4b31ac..823d27e4617b26 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/job.ts +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UrlConfig } from '../../../../../../../common/types/custom_urls'; -import { CREATED_BY_LABEL } from '../../../../../../../common/constants/new_job'; +import { UrlConfig } from '../custom_urls'; +import { CREATED_BY_LABEL } from '../../constants/new_job'; export type JobId = string; export type BucketSpan = string; @@ -29,6 +29,14 @@ export interface Job { renormalization_window_days?: number; results_index_name?: string; results_retention_days?: number; + + // optional properties added when the job has been created + create_time?: number; + finished_time?: number; + job_type?: 'anomaly_detector'; + job_version?: string; + model_snapshot_id?: string; + deleting?: boolean; } export interface AnalysisConfig { diff --git a/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts new file mode 100644 index 00000000000000..2d64e70bb1f782 --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts @@ -0,0 +1,95 @@ +/* + * 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 { JOB_STATE } from '../../constants/states'; + +export interface JobStats { + job_id: string; + data_counts: DataCounts; + model_size_stats: ModelSizeStats; + forecasts_stats: ForecastsStats; + state: JOB_STATE; + node: Node; + assignment_explanation: string; + open_time: string; + timing_stats: TimingStats; +} + +export interface DataCounts { + job_id: string; + processed_record_count: number; + processed_field_count: number; + input_bytes: number; + input_field_count: number; + invalid_date_count: number; + missing_field_count: number; + out_of_order_timestamp_count: number; + empty_bucket_count: number; + sparse_bucket_count: number; + bucket_count: number; + earliest_record_timestamp: number; + latest_record_timestamp: number; + last_data_time: number; + input_record_count: number; + latest_empty_bucket_timestamp: number; + latest_sparse_bucket_timestamp: number; + latest_bucket_timestamp?: number; // stat added by the UI +} + +export interface ModelSizeStats { + job_id: string; + result_type: string; + model_bytes: number; + model_bytes_exceeded: number; + model_bytes_memory_limit: number; + total_by_field_count: number; + total_over_field_count: number; + total_partition_field_count: number; + bucket_allocation_failures_count: number; + memory_status: 'ok' | 'soft_limit' | 'hard_limit'; + categorized_doc_count: number; + total_category_count: number; + frequent_category_count: number; + rare_category_count: number; + dead_category_count: number; + categorization_status: 'ok' | 'warn'; + log_time: number; + timestamp: number; +} + +export interface ForecastsStats { + total: number; + forecasted_jobs: number; + memory_bytes?: any; + records?: any; + processing_time_ms?: any; + status?: any; +} + +export interface Node { + id: string; + name: string; + ephemeral_id: string; + transport_address: string; + attributes: { + 'transform.remote_connect'?: boolean; + 'ml.machine_memory'?: number; + 'xpack.installed'?: boolean; + 'transform.node'?: boolean; + 'ml.max_open_jobs'?: number; + }; +} + +interface TimingStats { + job_id: string; + bucket_count: number; + total_bucket_processing_time_ms: number; + minimum_bucket_processing_time_ms: number; + maximum_bucket_processing_time_ms: number; + average_bucket_processing_time_ms: number; + exponential_average_bucket_processing_time_ms: number; + exponential_average_bucket_processing_time_per_hour_ms: number; +} diff --git a/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts new file mode 100644 index 00000000000000..6cf109dc553ae5 --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/anomaly_detection_jobs/summary_job.ts @@ -0,0 +1,57 @@ +/* + * 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 { Moment } from 'moment'; + +import { CombinedJob, CombinedJobWithStats } from './combined_job'; +export { Datafeed } from './datafeed'; +export { DatafeedStats } from './datafeed_stats'; + +export interface MlSummaryJob { + id: string; + description: string; + groups: string[]; + processed_record_count?: number; + memory_status?: string; + jobState: string; + datafeedIndices: string[]; + hasDatafeed: boolean; + datafeedId: string; + datafeedState: string; + latestTimestampMs?: number; + earliestTimestampMs?: number; + latestResultsTimestampMs?: number; + fullJob?: CombinedJob; + nodeName?: string; + auditMessage?: Partial; + isSingleMetricViewerJob: boolean; + deleting?: boolean; + latestTimestampSortValue?: number; +} + +export interface AuditMessage { + job_id: string; + msgTime: number; + level: number; + highestLevel: number; + highestLevelText: string; + text: string; +} + +export type MlSummaryJobs = MlSummaryJob[]; + +export interface MlJobWithTimeRange extends CombinedJobWithStats { + timeRange: { + from: number; + to: number; + fromPx: number; + toPx: number; + fromMoment: Moment; + toMoment: Moment; + widthPx: number; + label: string; + }; +} diff --git a/x-pack/legacy/plugins/ml/common/types/jobs.ts b/x-pack/legacy/plugins/ml/common/types/jobs.ts deleted file mode 100644 index a9885048550bbf..00000000000000 --- a/x-pack/legacy/plugins/ml/common/types/jobs.ts +++ /dev/null @@ -1,97 +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 { Moment } from 'moment'; - -// TS TODO: This is not yet a fully fledged representation of the job data structure, -// but it fulfills some basic TypeScript related needs. -export interface MlJob { - analysis_config: { - bucket_span: string; - detectors: object[]; - influencers: string[]; - }; - analysis_limits: { - categorization_examples_limit: number; - model_memory_limit: string; - }; - create_time: number; - custom_settings: object; - data_counts: { - earliest_record_timestamp: number; - latest_record_timestamp: number; - }; - data_description: { - time_field: string; - time_format: string; - }; - datafeed_config: object; - description: string; - established_model_memory: number; - finished_time: number; - job_id: string; - job_type: string; - job_version: string; - model_plot_config: object; - model_size_stats: object; - model_snapshot_id: string; - model_snapshot_min_version: string; - model_snapshot_retention_days: number; - results_index_name: string; - state: string; -} - -export interface MlSummaryJob { - id: string; - description: string; - groups: string[]; - processed_record_count: number; - memory_status?: string; - jobState: string; - hasDatafeed: boolean; - datafeedId?: string; - datafeedIndices: any[]; - datafeedState?: string; - latestTimestampMs: number; - earliestTimestampMs?: number; - latestResultsTimestampMs: number; - isSingleMetricViewerJob: boolean; - nodeName?: string; - deleting?: boolean; - fullJob?: any; - auditMessage?: any; - latestTimestampSortValue?: number; -} - -export type MlSummaryJobs = MlSummaryJob[]; - -export interface MlJobWithTimeRange extends MlJob { - groups: string[]; - timeRange: { - from: number; - to: number; - fromPx: number; - toPx: number; - fromMoment: Moment; - toMoment: Moment; - widthPx: number; - label: string; - }; -} - -export function isMlJob(arg: any): arg is MlJob { - return typeof arg.job_id === 'string'; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface MlJobs extends Array {} - -export function isMlJobs(arg: any): arg is MlJobs { - if (Array.isArray(arg) === false) { - return false; - } - return arg.every((d: MlJob) => isMlJob(d)); -} diff --git a/x-pack/legacy/plugins/ml/common/types/modules.ts b/x-pack/legacy/plugins/ml/common/types/modules.ts index 3e1a2cf9ab2e62..87e19d09da30c4 100644 --- a/x-pack/legacy/plugins/ml/common/types/modules.ts +++ b/x-pack/legacy/plugins/ml/common/types/modules.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { SavedObjectAttributes } from 'src/core/public'; -import { Datafeed, Job } from '../../public/application/jobs/new_job/common/job_creator/configs'; +import { Datafeed, Job } from '../types/anomaly_detection_jobs'; export interface ModuleJob { id: string; diff --git a/x-pack/legacy/plugins/ml/common/util/job_utils.d.ts b/x-pack/legacy/plugins/ml/common/util/job_utils.d.ts index 7dcd4b20fe0bf0..bfad422e0ab48d 100644 --- a/x-pack/legacy/plugins/ml/common/util/job_utils.d.ts +++ b/x-pack/legacy/plugins/ml/common/util/job_utils.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Job } from '../../public/application/jobs/new_job/common/job_creator/configs'; +import { Job } from '../types/anomaly_detection_jobs'; export interface ValidationMessage { id: string; diff --git a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_select_service_utils.ts b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_select_service_utils.ts index 1484f0a391b671..3a215f8cfb46d3 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_select_service_utils.ts +++ b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_select_service_utils.ts @@ -9,7 +9,7 @@ import moment from 'moment'; import d3 from 'd3'; import { Dictionary } from '../../../../common/types/common'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; export function getGroupsFromJobs(jobs: MlJobWithTimeRange[]) { const groups: Dictionary = {}; diff --git a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector.tsx b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector.tsx index bd2ec2d1511a30..bd75b7be4d5ef7 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector.tsx +++ b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector.tsx @@ -24,7 +24,7 @@ import { i18n } from '@kbn/i18n'; import { useMlKibana } from '../../contexts/kibana'; import { Dictionary } from '../../../../common/types/common'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; import { ml } from '../../services/ml_api_service'; import { useUrlState } from '../../util/url_state'; // @ts-ignore diff --git a/x-pack/legacy/plugins/ml/public/application/components/job_selector/use_job_selection.ts b/x-pack/legacy/plugins/ml/public/application/components/job_selector/use_job_selection.ts index 214bb909173026..d3fad9ae6bc2c8 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/job_selector/use_job_selection.ts +++ b/x-pack/legacy/plugins/ml/public/application/components/job_selector/use_job_selection.ts @@ -10,7 +10,7 @@ import { useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { getToastNotifications } from '../../util/dependency_cache'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; import { useUrlState } from '../../util/url_state'; diff --git a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts index c60b2d55d86862..2d3c9a389110a8 100644 --- a/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/explorer/explorer_utils.d.ts @@ -6,7 +6,7 @@ import { Moment } from 'moment'; -import { CombinedJob } from '../jobs/new_job/common/job_creator/configs'; +import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; import { TimeBucketsInterval } from '../util/time_buckets'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.test.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.test.tsx index 42ee18bafd8706..923d3bf5ce59f9 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.test.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { Job } from '../../new_job/common/job_creator/configs'; +import { Job } from '../../../../../common/types/anomaly_detection_jobs'; import { CustomUrlList, CustomUrlListProps } from './list'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.tsx index 4c0956a46d669f..1b18afaf2569fa 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/list.tsx @@ -25,7 +25,7 @@ import { getTestUrl } from './utils'; import { parseInterval } from '../../../../../common/util/parse_interval'; import { TIME_RANGE_TYPE } from './constants'; import { UrlConfig, KibanaUrlConfig } from '../../../../../common/types/custom_urls'; -import { Job } from '../../new_job/common/job_creator/configs'; +import { Job } from '../../../../../common/types/anomaly_detection_jobs'; function isValidTimeRange(timeRange: KibanaUrlConfig['time_range']): boolean { // Allow empty timeRange string, which gives the 'auto' behaviour. diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts index cce0c7c29912c9..8ae61a01d5e424 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/components/custom_url_editor/utils.d.ts @@ -6,7 +6,7 @@ import { IIndexPattern } from 'src/plugins/data/common'; import { UrlConfig } from '../../../../../common/types/custom_urls'; -import { Job } from '../../new_job/common/job_creator/configs'; +import { Job } from '../../../../../common/types/anomaly_detection_jobs'; import { TimeRangeType } from './constants'; export interface TimeRange { diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx index fe6f72fd10279c..dd85934d11150b 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx @@ -35,7 +35,7 @@ import { import { withKibana } from '../../../../../../../../../../../src/plugins/kibana_react/public'; import { loadSavedDashboards, loadIndexPatterns } from '../edit_utils'; import { openCustomUrlWindow } from '../../../../../util/custom_url_utils'; -import { Job } from '../../../../new_job/common/job_creator/configs'; +import { Job } from '../../../../../../../common/types/anomaly_detection_jobs'; import { UrlConfig } from '../../../../../../../common/types/custom_urls'; import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns'; import { MlKibanaReactContextValue } from '../../../../../contexts/kibana'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts index 4530c00c105355..099f587caa0514 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts @@ -8,7 +8,12 @@ import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, Aggregation, SplitField } from '../../../../../../common/types/fields'; -import { Job, Datafeed, Detector, CustomRule } from './configs'; +import { + Job, + Datafeed, + Detector, + CustomRule, +} from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts index eb2f0f4e368a34..25ec8becd9a054 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/categorization_job_creator.ts @@ -9,7 +9,7 @@ import { IndexPattern } from '../../../../../../../../../../src/plugins/data/pub import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; import { Field, Aggregation, mlCategory } from '../../../../../../common/types/fields'; -import { Job, Datafeed, Detector } from './configs'; +import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index 5b33aa35569809..98b8a7904eda97 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -9,7 +9,15 @@ import { UrlConfig } from '../../../../../../common/types/custom_urls'; import { IndexPatternTitle } from '../../../../../../common/types/kibana'; import { ML_JOB_AGGREGATION } from '../../../../../../common/constants/aggregation_types'; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; -import { Job, Datafeed, Detector, JobId, DatafeedId, BucketSpan, CustomSettings } from './configs'; +import { + Job, + Datafeed, + Detector, + JobId, + DatafeedId, + BucketSpan, + CustomSettings, +} from '../../../../../../common/types/anomaly_detection_jobs'; import { Aggregation, Field } from '../../../../../../common/types/fields'; import { createEmptyJob, createEmptyDatafeed } from './util/default_configs'; import { mlJobService } from '../../../../services/job_service'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts index 7c5fba028d9e8f..120eee984a10b1 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts @@ -12,7 +12,7 @@ import { SplitField, AggFieldPair, } from '../../../../../../common/types/fields'; -import { Job, Datafeed, Detector } from './configs'; +import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts index 3009d68ca67caa..032ebc202142d4 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/population_job_creator.ts @@ -12,7 +12,7 @@ import { SplitField, AggFieldPair, } from '../../../../../../common/types/fields'; -import { Job, Datafeed, Detector } from './configs'; +import { Job, Datafeed, Detector } from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; import { JOB_TYPE, CREATED_BY_LABEL } from '../../../../../../common/constants/new_job'; import { getRichDetectors } from './util/general'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts index 9f3500185c2bfa..b16d624cff463d 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/single_metric_job_creator.ts @@ -8,7 +8,12 @@ import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { parseInterval } from '../../../../../../common/util/parse_interval'; import { JobCreator } from './job_creator'; import { Field, Aggregation, AggFieldPair } from '../../../../../../common/types/fields'; -import { Job, Datafeed, Detector, BucketSpan } from './configs'; +import { + Job, + Datafeed, + Detector, + BucketSpan, +} from '../../../../../../common/types/anomaly_detection_jobs'; import { createBasicDetector } from './util/default_configs'; import { ML_JOB_AGGREGATION, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/default_configs.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/default_configs.ts index 1160401478ab7e..306fd82dc87582 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/default_configs.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/default_configs.ts @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Job, Datafeed } from '../configs'; import { IndexPatternTitle } from '../../../../../../../common/types/kibana'; import { Field, Aggregation, EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields'; -import { Detector } from '../configs'; +import { Job, Datafeed, Detector } from '../../../../../../../common/types/anomaly_detection_jobs'; export function createEmptyJob(): Job { return { @@ -28,6 +27,7 @@ export function createEmptyJob(): Job { export function createEmptyDatafeed(indexPatternTitle: IndexPatternTitle): Datafeed { return { datafeed_id: '', + job_id: '', indices: [indexPatternTitle], query: {}, }; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts index 0764e276d635ea..b07d55c5b85165 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { Job, Datafeed, Detector } from '../configs'; +import { Job, Datafeed, Detector } from '../../../../../../../common/types/anomaly_detection_jobs'; import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; import { ML_JOB_AGGREGATION, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_runner/job_runner.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_runner/job_runner.ts index 9627d2e4775281..2571fe70f4a830 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_runner/job_runner.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_runner/job_runner.ts @@ -8,7 +8,7 @@ import { BehaviorSubject } from 'rxjs'; import { ml } from '../../../../services/ml_api_service'; import { mlJobService } from '../../../../services/job_service'; import { JobCreator } from '../job_creator'; -import { DatafeedId, JobId } from '../job_creator/configs'; +import { DatafeedId, JobId } from '../../../../../../common/types/anomaly_detection_jobs'; import { DATAFEED_STATE } from '../../../../../../common/constants/states'; const REFRESH_INTERVAL_MS = 100; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/util.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/util.ts index ab33afb23ef514..39e3ef2ae0007b 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/util.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/common/job_validator/util.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { BasicValidations } from './job_validator'; -import { Job, Datafeed } from '../job_creator/configs'; +import { Job, Datafeed } from '../../../../../../common/types/anomaly_detection_jobs'; import { ALLOWED_DATA_UNITS, JOB_ID_MAX_LENGTH, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/datafeed_preview_flyout/datafeed_preview_flyout.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/datafeed_preview_flyout/datafeed_preview_flyout.tsx index 7f5d2bfbe0e90c..03be38adfbbe0c 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/datafeed_preview_flyout/datafeed_preview_flyout.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/datafeed_preview_flyout/datafeed_preview_flyout.tsx @@ -18,7 +18,7 @@ import { EuiSpacer, EuiLoadingSpinner, } from '@elastic/eui'; -import { CombinedJob } from '../../../../common/job_creator/configs'; +import { CombinedJob } from '../../../../../../../../common/types/anomaly_detection_jobs'; import { MLJobEditor } from '../../../../../jobs_list/components/ml_job_editor'; import { JobCreatorContext } from '../../job_creator_context'; import { mlJobService } from '../../../../../../services/job_service'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx index 061d92b54472c7..dd5c8aa3e280a1 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx @@ -19,7 +19,7 @@ import { EuiSpacer, } from '@elastic/eui'; import { collapseLiteralStrings } from '../../../../../../../../shared_imports'; -import { Datafeed } from '../../../../common/job_creator/configs'; +import { Datafeed } from '../../../../../../../../common/types/anomaly_detection_jobs'; import { ML_EDITOR_MODE, MLJobEditor } from '../../../../../jobs_list/components/ml_job_editor'; import { isValidJson } from '../../../../../../../../common/util/validation_utils'; import { JobCreatorContext } from '../../job_creator_context'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/custom_urls_selection.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/custom_urls_selection.tsx index cd580e60c08438..2e5135d4d8840e 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/custom_urls_selection.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/custom_urls_selection.tsx @@ -9,7 +9,7 @@ import { CustomUrls } from '../../../../../../../../jobs_list/components/edit_jo import { UrlConfig } from '../../../../../../../../../../../common/types/custom_urls'; import { JobCreatorContext } from '../../../../../job_creator_context'; import { Description } from './description'; -import { CombinedJob } from '../../../../../../../common/job_creator/configs'; +import { CombinedJob } from '../../../../../../../../../../../common/types/anomaly_detection_jobs'; export const CustomUrlsSelection: FC = () => { const { jobCreator, jobCreatorUpdate } = useContext(JobCreatorContext); diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx index f996a0e9728bae..38903dd4845a67 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_view/detector_list.tsx @@ -25,7 +25,7 @@ import { JobCreatorContext } from '../../../job_creator_context'; import { AdvancedJobCreator } from '../../../../../common/job_creator'; import { Validation } from '../../../../../common/job_validator'; import { detectorToString } from '../../../../../../../util/string_utils'; -import { Detector } from '../../../../../common/job_creator/configs'; +import { Detector } from '../../../../../../../../../common/types/anomaly_detection_jobs'; interface Props { isActive: boolean; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts index 51fc226751ae2a..d1a6ca7c19a240 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts @@ -7,7 +7,7 @@ import { IndexPatternsContract } from '../../../../../../../../../../src/plugins/data/public'; import { mlJobService } from '../../../../services/job_service'; import { loadIndexPatterns, getIndexPatternIdFromName } from '../../../../util/index_utils'; -import { CombinedJob } from '../../common/job_creator/configs'; +import { CombinedJob } from '../../../../../../common/types/anomaly_detection_jobs'; import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../common/constants/new_job'; export async function preConfiguredJobRedirect(indexPatterns: IndexPatternsContract) { diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx index b2383b6c08a587..d851559815de8e 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/pages/new_job/page.tsx @@ -37,7 +37,7 @@ import { useMlContext } from '../../../../contexts/ml'; import { getTimeFilterRange } from '../../../../components/full_time_range_selector'; import { TimeBuckets } from '../../../../util/time_buckets'; import { ExistingJobsAndGroups, mlJobService } from '../../../../services/job_service'; -import { expandCombinedJobConfig } from '../../common/job_creator/configs'; +import { expandCombinedJobConfig } from '../../../../../../common/types/anomaly_detection_jobs'; import { newJobCapsService } from '../../../../services/new_job_capabilities_service'; import { EVENT_RATE_FIELD_ID } from '../../../../../../common/types/fields'; import { getNewJobDefaults } from '../../../../services/ml_server_info'; diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx index 8571ae43da587f..ac7a2093d1f81e 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx +++ b/x-pack/legacy/plugins/ml/public/application/jobs/new_job/recognize/page.tsx @@ -41,7 +41,7 @@ import { ModuleJobs } from './components/module_jobs'; import { checkForSavedObjects } from './resolvers'; import { JobSettingsForm, JobSettingsFormValues } from './components/job_settings_form'; import { TimeRange } from '../common/components'; -import { JobId } from '../common/job_creator/configs'; +import { JobId } from '../../../../../common/types/anomaly_detection_jobs'; export interface ModuleJobUI extends ModuleJob { datafeedResult?: DatafeedResponse; diff --git a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx index f638094cfb4349..3a64c623dd1298 100644 --- a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx +++ b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/actions.tsx @@ -9,7 +9,7 @@ import { EuiToolTip, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; // @ts-ignore no module file import { getLink } from '../../../jobs/jobs_list/components/job_actions/results'; -import { MlSummaryJobs } from '../../../../../common/types/jobs'; +import { MlSummaryJobs } from '../../../../../common/types/anomaly_detection_jobs'; interface Props { jobsList: MlSummaryJobs; diff --git a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx index cda03b21b0d656..5f5c3f7c28670a 100644 --- a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx +++ b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/anomaly_detection_panel.tsx @@ -21,7 +21,7 @@ import { AnomalyDetectionTable } from './table'; import { ml } from '../../../services/ml_api_service'; import { getGroupsFromJobs, getStatsBarData, getJobsWithTimerange } from './utils'; import { Dictionary } from '../../../../../common/types/common'; -import { MlSummaryJobs, MlSummaryJob } from '../../../../../common/types/jobs'; +import { MlSummaryJobs, MlSummaryJob } from '../../../../../common/types/anomaly_detection_jobs'; export type GroupsDictionary = Dictionary; diff --git a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx index cca86e2fc0e3ed..cd45721d54a684 100644 --- a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx +++ b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/table.tsx @@ -27,7 +27,7 @@ import { formatHumanReadableDateTimeSeconds } from '../../../util/date_utils'; import { ExplorerLink } from './actions'; import { getJobsFromGroup } from './utils'; import { GroupsDictionary, Group } from './anomaly_detection_panel'; -import { MlSummaryJobs } from '../../../../../common/types/jobs'; +import { MlSummaryJobs } from '../../../../../common/types/anomaly_detection_jobs'; import { StatsBar, JobStatsBarStats } from '../../../components/stats_bar'; // @ts-ignore import { JobSelectorBadge } from '../../../components/job_selector/job_selector_badge/index'; diff --git a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/utils.ts b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/utils.ts index 01848bad2670ef..eab40c0f577f86 100644 --- a/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/utils.ts +++ b/x-pack/legacy/plugins/ml/public/application/overview/components/anomaly_detection_panel/utils.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { JOB_STATE, DATAFEED_STATE } from '../../../../../common/constants/states'; import { Group, GroupsDictionary } from './anomaly_detection_panel'; -import { MlSummaryJobs, MlSummaryJob } from '../../../../../common/types/jobs'; +import { MlSummaryJobs, MlSummaryJob } from '../../../../../common/types/anomaly_detection_jobs'; export function getGroupsFromJobs( jobs: MlSummaryJobs @@ -43,7 +43,7 @@ export function getGroupsFromJobs( // if incoming job latest timestamp is greater than the last saved one, replace it if (groups[g].latest_timestamp === undefined) { groups[g].latest_timestamp = job.latestTimestampMs; - } else if (job.latestTimestampMs > groups[g].latest_timestamp) { + } else if (job.latestTimestampMs && job.latestTimestampMs > groups[g].latest_timestamp) { groups[g].latest_timestamp = job.latestTimestampMs; } } @@ -53,7 +53,7 @@ export function getGroupsFromJobs( groups.ungrouped.docs_processed += job.processed_record_count; groups.ungrouped.jobs_in_group++; // if incoming job latest timestamp is greater than the last saved one, replace it - if (job.latestTimestampMs > groups.ungrouped.latest_timestamp) { + if (job.latestTimestampMs && job.latestTimestampMs > groups.ungrouped.latest_timestamp) { groups.ungrouped.latest_timestamp = job.latestTimestampMs; } } diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx index 2c6726338d2f14..2e355c6073abd9 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/explorer.tsx @@ -9,7 +9,7 @@ import useObservable from 'react-use/lib/useObservable'; import { i18n } from '@kbn/i18n'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; import { MlRoute, PageLoader, PageProps } from '../router'; import { useRefresh } from '../use_refresh'; diff --git a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx index f8a6f6c454fc06..a41a6c83615d39 100644 --- a/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx +++ b/x-pack/legacy/plugins/ml/public/application/routing/routes/timeseriesexplorer.tsx @@ -11,7 +11,7 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; import { TimeSeriesExplorer } from '../../timeseriesexplorer'; import { getDateFormatTz, TimeRangeBounds } from '../../explorer/explorer_utils'; diff --git a/x-pack/legacy/plugins/ml/public/application/services/calendar_service.ts b/x-pack/legacy/plugins/ml/public/application/services/calendar_service.ts index f17c9f359c7b57..98001fce1cf71d 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/calendar_service.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/calendar_service.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { ml } from './ml_api_service'; import { Calendar, CalendarId } from '../../../common/types/calendars'; -import { JobId } from '../jobs/new_job/common/job_creator/configs'; +import { JobId } from '../../../common/types/anomaly_detection_jobs'; class CalendarService { /** * Assigns a job id to the calendar. diff --git a/x-pack/legacy/plugins/ml/public/application/services/forecast_service.d.ts b/x-pack/legacy/plugins/ml/public/application/services/forecast_service.d.ts index 8de903a422f340..9eff86c753da92 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/forecast_service.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/forecast_service.d.ts @@ -5,7 +5,7 @@ */ import { Observable } from 'rxjs'; -import { Job } from '../jobs/new_job/common/job_creator/configs'; +import { Job } from '../../../common/types/anomaly_detection_jobs'; export interface ForecastData { success: boolean; diff --git a/x-pack/legacy/plugins/ml/public/application/services/job_service.d.ts b/x-pack/legacy/plugins/ml/public/application/services/job_service.d.ts index b9ed83eeffba16..2134d157e1baae 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/job_service.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/job_service.d.ts @@ -5,7 +5,7 @@ */ import { SearchResponse } from 'elasticsearch'; -import { CombinedJob } from '../jobs/new_job/common/job_creator/configs'; +import { CombinedJob } from '../../../common/types/anomaly_detection_jobs'; import { Calendar } from '../../../common/types/calendars'; export interface ExistingJobsAndGroups { diff --git a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts index 6cb8eccafe1511..97e001389c5f1a 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/ml_api_service/index.d.ts @@ -11,7 +11,6 @@ import { AggFieldNamePair } from '../../../../common/types/fields'; import { Category } from '../../../../common/types/categories'; import { ExistingJobsAndGroups } from '../job_service'; import { PrivilegesResponse } from '../../../../common/types/privileges'; -import { MlJobWithTimeRange, MlSummaryJobs } from '../../../../common/types/jobs'; import { MlServerDefaults, MlServerLimits } from '../ml_server_info'; import { ES_AGGREGATION } from '../../../../common/constants/aggregation_types'; import { DataFrameAnalyticsStats } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/common'; @@ -21,7 +20,12 @@ import { DeepPartial } from '../../../../common/types/common'; import { PartitionFieldsDefinition } from '../results_service/result_service_rx'; import { annotations } from './annotations'; import { Calendar, CalendarId, UpdateCalendar } from '../../../../common/types/calendars'; -import { CombinedJob, JobId } from '../../jobs/new_job/common/job_creator/configs'; +import { + MlJobWithTimeRange, + MlSummaryJobs, + CombinedJob, + JobId, +} from '../../../../common/types/anomaly_detection_jobs'; import { CategorizationAnalyzer, CategoryFieldExample, diff --git a/x-pack/legacy/plugins/ml/public/application/services/results_service/result_service_rx.ts b/x-pack/legacy/plugins/ml/public/application/services/results_service/result_service_rx.ts index 299dfe01676947..8f701a9ebe057c 100644 --- a/x-pack/legacy/plugins/ml/public/application/services/results_service/result_service_rx.ts +++ b/x-pack/legacy/plugins/ml/public/application/services/results_service/result_service_rx.ts @@ -16,7 +16,7 @@ import { map } from 'rxjs/operators'; import _ from 'lodash'; import { Dictionary } from '../../../../common/types/common'; import { ML_MEDIAN_PERCENTS } from '../../../../common/util/job_utils'; -import { JobId } from '../../jobs/new_job/common/job_creator/configs'; +import { JobId } from '../../../../common/types/anomaly_detection_jobs'; import { ml } from '../ml_api_service'; import { ML_RESULTS_INDEX_PATTERN } from '../../../../common/constants/index_patterns'; import { CriteriaField } from './index'; diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.d.ts b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.d.ts index 1f49ec1826422a..de294ffc214216 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.d.ts +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart.d.ts @@ -7,10 +7,10 @@ import d3 from 'd3'; import { Annotation } from '../../../../../common/types/annotations'; -import { MlJob } from '../../../../../common/types/jobs'; +import { CombinedJob } from '../../../../../common/types/anomaly_detection_jobs'; interface Props { - selectedJob: MlJob; + selectedJob: CombinedJob; } interface State { diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts index 65bcc9d355fd69..978f5f68d9d8d8 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseries_search_service.ts @@ -14,7 +14,7 @@ import { isModelPlotEnabled } from '../../../common/util/job_utils'; import { buildConfigFromDetector } from '../util/chart_config_builder'; import { mlResultsService } from '../services/results_service'; import { ModelPlotOutput } from '../services/results_service/result_service_rx'; -import { Job } from '../jobs/new_job/common/job_creator/configs'; +import { Job } from '../../../common/types/anomaly_detection_jobs'; function getMetricData( job: Job, diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts index 2a4eaf1a545a1c..534c8c567359e6 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts @@ -13,7 +13,7 @@ import { } from '../../../../common/constants/search'; import { mlTimeSeriesSearchService } from '../timeseries_search_service'; import { mlResultsService, CriteriaField } from '../../services/results_service'; -import { Job } from '../../jobs/new_job/common/job_creator/configs'; +import { Job } from '../../../../common/types/anomaly_detection_jobs'; import { MAX_SCHEDULED_EVENTS, TIME_FIELD_NAME } from '../timeseriesexplorer_constants'; import { processDataForFocusAnomalies, diff --git a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/validate_job_selection.ts b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/validate_job_selection.ts index bd8f98e0428a18..d31ae710b025ee 100644 --- a/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/validate_job_selection.ts +++ b/x-pack/legacy/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/validate_job_selection.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { getToastNotifications } from '../../util/dependency_cache'; -import { MlJobWithTimeRange } from '../../../../common/types/jobs'; +import { MlJobWithTimeRange } from '../../../../common/types/anomaly_detection_jobs'; import { getTimeRangeFromSelection } from '../../components/job_selector/job_select_service_utils'; import { mlJobService } from '../../services/job_service'; diff --git a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts index 8d2a6c9955da36..020a77baa4e358 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts +++ b/x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts @@ -10,7 +10,7 @@ import numeral from '@elastic/numeral'; import { CallAPIOptions, RequestHandlerContext, SavedObjectsClientContract } from 'kibana/server'; import { IndexPatternAttributes } from 'src/plugins/data/server'; import { merge } from 'lodash'; -import { MlJob } from '../../../../../legacy/plugins/ml/common/types/jobs'; +import { CombinedJobWithStats } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; import { KibanaObjects, ModuleDataFeed, @@ -29,7 +29,6 @@ import { prefixDatafeedId, } from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { mlLog } from '../../client/log'; -// @ts-ignore import { jobServiceProvider } from '../job_service'; import { resultsServiceProvider } from '../results_service'; @@ -61,7 +60,7 @@ interface RawModuleConfig { } interface MlJobStats { - jobs: MlJob[]; + jobs: CombinedJobWithStats[]; } interface Config { diff --git a/x-pack/plugins/ml/server/models/job_service/datafeeds.js b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts similarity index 57% rename from x-pack/plugins/ml/server/models/job_service/datafeeds.js rename to x-pack/plugins/ml/server/models/job_service/datafeeds.ts index 961b712610512d..47a0d8f2546595 100644 --- a/x-pack/plugins/ml/server/models/job_service/datafeeds.js +++ b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts @@ -4,24 +4,45 @@ * you may not use this file except in compliance with the Elastic License. */ +import { APICaller } from 'src/core/server'; import { i18n } from '@kbn/i18n'; import { JOB_STATE, DATAFEED_STATE, } from '../../../../../legacy/plugins/ml/common/constants/states'; import { fillResultsWithTimeouts, isRequestTimeout } from './error_utils'; +import { + Datafeed, + DatafeedStats, +} from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; + +export interface MlDatafeedsResponse { + datafeeds: Datafeed[]; + count: number; +} +export interface MlDatafeedsStatsResponse { + datafeeds: DatafeedStats[]; + count: number; +} -export function datafeedsProvider(callWithRequest) { - async function forceStartDatafeeds(datafeedIds, start, end) { +interface Results { + [id: string]: { + started: boolean; + error?: any; + }; +} + +export function datafeedsProvider(callAsCurrentUser: APICaller) { + async function forceStartDatafeeds(datafeedIds: string[], start: number, end: number) { const jobIds = await getJobIdsByDatafeedId(); - const doStartsCalled = datafeedIds.reduce((p, c) => { - p[c] = false; - return p; - }, {}); + const doStartsCalled = datafeedIds.reduce((acc, cur) => { + acc[cur] = false; + return acc; + }, {} as { [id: string]: boolean }); - const results = {}; + const results: Results = {}; - async function doStart(datafeedId) { + async function doStart(datafeedId: string): Promise<{ started: boolean; error?: string }> { if (doStartsCalled[datafeedId] === false) { doStartsCalled[datafeedId] = true; try { @@ -30,6 +51,8 @@ export function datafeedsProvider(callWithRequest) { } catch (error) { return { started: false, error }; } + } else { + return { started: true }; } } @@ -64,10 +87,10 @@ export function datafeedsProvider(callWithRequest) { return results; } - async function openJob(jobId) { + async function openJob(jobId: string) { let opened = false; try { - const resp = await callWithRequest('ml.openJob', { jobId }); + const resp = await callAsCurrentUser('ml.openJob', { jobId }); opened = resp.opened; } catch (error) { if (error.statusCode === 409) { @@ -79,16 +102,16 @@ export function datafeedsProvider(callWithRequest) { return opened; } - async function startDatafeed(datafeedId, start, end) { - return callWithRequest('ml.startDatafeed', { datafeedId, start, end }); + async function startDatafeed(datafeedId: string, start: number, end: number) { + return callAsCurrentUser('ml.startDatafeed', { datafeedId, start, end }); } - async function stopDatafeeds(datafeedIds) { - const results = {}; + async function stopDatafeeds(datafeedIds: string[]) { + const results: Results = {}; for (const datafeedId of datafeedIds) { try { - results[datafeedId] = await callWithRequest('ml.stopDatafeed', { datafeedId }); + results[datafeedId] = await callAsCurrentUser('ml.stopDatafeed', { datafeedId }); } catch (error) { if (isRequestTimeout(error)) { return fillResultsWithTimeouts(results, datafeedId, datafeedIds, DATAFEED_STATE.STOPPED); @@ -99,24 +122,24 @@ export function datafeedsProvider(callWithRequest) { return results; } - async function forceDeleteDatafeed(datafeedId) { - return callWithRequest('ml.deleteDatafeed', { datafeedId, force: true }); + async function forceDeleteDatafeed(datafeedId: string) { + return callAsCurrentUser('ml.deleteDatafeed', { datafeedId, force: true }); } async function getDatafeedIdsByJobId() { - const datafeeds = await callWithRequest('ml.datafeeds'); - return datafeeds.datafeeds.reduce((p, c) => { - p[c.job_id] = c.datafeed_id; - return p; - }, {}); + const { datafeeds } = await callAsCurrentUser('ml.datafeeds'); + return datafeeds.reduce((acc, cur) => { + acc[cur.job_id] = cur.datafeed_id; + return acc; + }, {} as { [id: string]: string }); } async function getJobIdsByDatafeedId() { - const datafeeds = await callWithRequest('ml.datafeeds'); - return datafeeds.datafeeds.reduce((p, c) => { - p[c.datafeed_id] = c.job_id; - return p; - }, {}); + const { datafeeds } = await callAsCurrentUser('ml.datafeeds'); + return datafeeds.reduce((acc, cur) => { + acc[cur.datafeed_id] = cur.job_id; + return acc; + }, {} as { [id: string]: string }); } return { diff --git a/x-pack/plugins/ml/server/models/job_service/error_utils.js b/x-pack/plugins/ml/server/models/job_service/error_utils.ts similarity index 77% rename from x-pack/plugins/ml/server/models/job_service/error_utils.js rename to x-pack/plugins/ml/server/models/job_service/error_utils.ts index 21e45110e70930..a5c98f8dbdda6b 100644 --- a/x-pack/plugins/ml/server/models/job_service/error_utils.js +++ b/x-pack/plugins/ml/server/models/job_service/error_utils.ts @@ -11,14 +11,27 @@ import { } from '../../../../../legacy/plugins/ml/common/constants/states'; const REQUEST_TIMEOUT = 'RequestTimeout'; +type ACTION_STATE = DATAFEED_STATE | JOB_STATE; -export function isRequestTimeout(error) { +export function isRequestTimeout(error: { displayName: string }) { return error.displayName === REQUEST_TIMEOUT; } +interface Results { + [id: string]: { + [status: string]: any; + error?: any; + }; +} + // populate a results object with timeout errors // for the ids which haven't already been set -export function fillResultsWithTimeouts(results, id, ids, status) { +export function fillResultsWithTimeouts( + results: Results, + id: string, + ids: string[], + status: ACTION_STATE +) { const action = getAction(status); const extra = ids.length - Object.keys(results).length > 1 @@ -49,20 +62,20 @@ export function fillResultsWithTimeouts(results, id, ids, status) { }, }; - return ids.reduce((p, c) => { - if (results[c] === undefined) { - p[c] = { + return ids.reduce((acc, cur) => { + if (results[cur] === undefined) { + acc[cur] = { [status]: false, error, }; } else { - p[c] = results[c]; + acc[cur] = results[cur]; } - return p; - }, {}); + return acc; + }, {} as Results); } -function getAction(status) { +function getAction(status: ACTION_STATE) { let action = ''; if (status === DATAFEED_STATE.STARTED) { action = 'start'; diff --git a/x-pack/plugins/ml/server/models/job_service/groups.js b/x-pack/plugins/ml/server/models/job_service/groups.ts similarity index 70% rename from x-pack/plugins/ml/server/models/job_service/groups.js rename to x-pack/plugins/ml/server/models/job_service/groups.ts index b30e9cdc6048b7..58d71aa331ea9d 100644 --- a/x-pack/plugins/ml/server/models/job_service/groups.js +++ b/x-pack/plugins/ml/server/models/job_service/groups.ts @@ -4,17 +4,33 @@ * you may not use this file except in compliance with the Elastic License. */ +import { APICaller } from 'src/core/server'; import { CalendarManager } from '../calendar'; import { GLOBAL_CALENDAR } from '../../../../../legacy/plugins/ml/common/constants/calendars'; +import { Job } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; +import { MlJobsResponse } from './jobs'; -export function groupsProvider(callWithRequest) { - const calMngr = new CalendarManager(callWithRequest); +interface Group { + id: string; + jobIds: string[]; + calendarIds: string[]; +} + +interface Results { + [id: string]: { + success: boolean; + error?: any; + }; +} + +export function groupsProvider(callAsCurrentUser: APICaller) { + const calMngr = new CalendarManager(callAsCurrentUser); async function getAllGroups() { - const groups = {}; - const jobIds = {}; + const groups: { [id: string]: Group } = {}; + const jobIds: { [id: string]: undefined | null } = {}; const [{ jobs }, calendars] = await Promise.all([ - callWithRequest('ml.jobs'), + callAsCurrentUser('ml.jobs'), calMngr.getAllCalendars(), ]); @@ -58,12 +74,12 @@ export function groupsProvider(callWithRequest) { return Object.keys(groups).map(g => groups[g]); } - async function updateGroups(jobs) { - const results = {}; + async function updateGroups(jobs: Job[]) { + const results: Results = {}; for (const job of jobs) { const { job_id: jobId, groups } = job; try { - await callWithRequest('ml.updateJob', { jobId, body: { groups } }); + await callAsCurrentUser('ml.updateJob', { jobId, body: { groups } }); results[jobId] = { success: true }; } catch (error) { results[jobId] = { success: false, error }; diff --git a/x-pack/plugins/ml/server/models/job_service/index.js b/x-pack/plugins/ml/server/models/job_service/index.ts similarity index 87% rename from x-pack/plugins/ml/server/models/job_service/index.js rename to x-pack/plugins/ml/server/models/job_service/index.ts index 70b855e80a770c..37a1daa20cab2d 100644 --- a/x-pack/plugins/ml/server/models/job_service/index.js +++ b/x-pack/plugins/ml/server/models/job_service/index.ts @@ -4,13 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import { APICaller } from 'src/core/server'; import { datafeedsProvider } from './datafeeds'; import { jobsProvider } from './jobs'; import { groupsProvider } from './groups'; import { newJobCapsProvider } from './new_job_caps'; import { newJobChartsProvider, topCategoriesProvider } from './new_job'; -export function jobServiceProvider(callAsCurrentUser) { +export function jobServiceProvider(callAsCurrentUser: APICaller) { return { ...datafeedsProvider(callAsCurrentUser), ...jobsProvider(callAsCurrentUser), diff --git a/x-pack/plugins/ml/server/models/job_service/jobs.js b/x-pack/plugins/ml/server/models/job_service/jobs.ts similarity index 62% rename from x-pack/plugins/ml/server/models/job_service/jobs.js rename to x-pack/plugins/ml/server/models/job_service/jobs.ts index 16d3c30bb0a280..6ced623273f742 100644 --- a/x-pack/plugins/ml/server/models/job_service/jobs.js +++ b/x-pack/plugins/ml/server/models/job_service/jobs.ts @@ -5,34 +5,60 @@ */ import { i18n } from '@kbn/i18n'; +import { uniq } from 'lodash'; +import { APICaller } from 'src/core/server'; import { JOB_STATE, DATAFEED_STATE, } from '../../../../../legacy/plugins/ml/common/constants/states'; -import { datafeedsProvider } from './datafeeds'; +import { + MlSummaryJob, + AuditMessage, + Job, + JobStats, + DatafeedWithStats, + CombinedJobWithStats, +} from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; +import { datafeedsProvider, MlDatafeedsResponse, MlDatafeedsStatsResponse } from './datafeeds'; import { jobAuditMessagesProvider } from '../job_audit_messages'; import { resultsServiceProvider } from '../results_service'; -import { CalendarManager } from '../calendar'; +import { CalendarManager, Calendar } from '../calendar'; import { fillResultsWithTimeouts, isRequestTimeout } from './error_utils'; import { getLatestDataOrBucketTimestamp, isTimeSeriesViewJob, } from '../../../../../legacy/plugins/ml/common/util/job_utils'; import { groupsProvider } from './groups'; -import { uniq } from 'lodash'; -export function jobsProvider(callWithRequest) { - const { forceDeleteDatafeed, getDatafeedIdsByJobId } = datafeedsProvider(callWithRequest); - const { getAuditMessagesSummary } = jobAuditMessagesProvider(callWithRequest); - const { getLatestBucketTimestampByJob } = resultsServiceProvider(callWithRequest); - const calMngr = new CalendarManager(callWithRequest); +export interface MlJobsResponse { + jobs: Job[]; + count: number; +} + +export interface MlJobsStatsResponse { + jobs: JobStats[]; + count: number; +} + +interface Results { + [id: string]: { + [status: string]: boolean; + error?: any; + }; +} + +export function jobsProvider(callAsCurrentUser: APICaller) { + const { forceDeleteDatafeed, getDatafeedIdsByJobId } = datafeedsProvider(callAsCurrentUser); + const { getAuditMessagesSummary } = jobAuditMessagesProvider(callAsCurrentUser); + const { getLatestBucketTimestampByJob } = resultsServiceProvider(callAsCurrentUser); + const calMngr = new CalendarManager(callAsCurrentUser); - async function forceDeleteJob(jobId) { - return callWithRequest('ml.deleteJob', { jobId, force: true }); + async function forceDeleteJob(jobId: string) { + return callAsCurrentUser('ml.deleteJob', { jobId, force: true }); } - async function deleteJobs(jobIds) { - const results = {}; + async function deleteJobs(jobIds: string[]) { + const results: Results = {}; const datafeedIds = await getDatafeedIdsByJobId(); for (const jobId of jobIds) { @@ -68,11 +94,11 @@ export function jobsProvider(callWithRequest) { return results; } - async function closeJobs(jobIds) { - const results = {}; + async function closeJobs(jobIds: string[]) { + const results: Results = {}; for (const jobId of jobIds) { try { - await callWithRequest('ml.closeJob', { jobId }); + await callAsCurrentUser('ml.closeJob', { jobId }); results[jobId] = { closed: true }; } catch (error) { if (isRequestTimeout(error)) { @@ -88,7 +114,7 @@ export function jobsProvider(callWithRequest) { // if the job has failed we want to attempt a force close. // however, if we received a 409 due to the datafeed being started we should not attempt a force close. try { - await callWithRequest('ml.closeJob', { jobId, force: true }); + await callAsCurrentUser('ml.closeJob', { jobId, force: true }); results[jobId] = { closed: true }; } catch (error2) { if (isRequestTimeout(error)) { @@ -104,14 +130,14 @@ export function jobsProvider(callWithRequest) { return results; } - async function jobsSummary(jobIds = []) { - const fullJobsList = await createFullJobsList(); + async function jobsSummary(jobIds: string[] = []) { + const fullJobsList: CombinedJobWithStats[] = await createFullJobsList(); const fullJobsIds = fullJobsList.map(job => job.job_id); - const auditMessages = await getAuditMessagesSummary(fullJobsIds); - const auditMessagesByJob = auditMessages.reduce((p, c) => { - p[c.job_id] = c; - return p; - }, {}); + const auditMessages: AuditMessage[] = await getAuditMessagesSummary(fullJobsIds); + const auditMessagesByJob = auditMessages.reduce((acc, cur) => { + acc[cur.job_id] = cur; + return acc; + }, {} as { [id: string]: AuditMessage }); const deletingStr = i18n.translate('xpack.ml.models.jobService.deletingJob', { defaultMessage: 'deleting', @@ -122,11 +148,11 @@ export function jobsProvider(callWithRequest) { typeof job.datafeed_config === 'object' && Object.keys(job.datafeed_config).length > 0; const dataCounts = job.data_counts; - const tempJob = { + const tempJob: MlSummaryJob = { id: job.job_id, description: job.description || '', groups: Array.isArray(job.groups) ? job.groups.sort() : [], - processed_record_count: job.data_counts.processed_record_count, + processed_record_count: job.data_counts?.processed_record_count, memory_status: job.model_size_stats ? job.model_size_stats.memory_status : '', jobState: job.deleting === true ? deletingStr : job.state, hasDatafeed, @@ -135,11 +161,11 @@ export function jobsProvider(callWithRequest) { datafeedIndices: hasDatafeed && job.datafeed_config.indices ? job.datafeed_config.indices : [], datafeedState: hasDatafeed && job.datafeed_config.state ? job.datafeed_config.state : '', - latestTimestampMs: dataCounts.latest_record_timestamp, - earliestTimestampMs: dataCounts.earliest_record_timestamp, + latestTimestampMs: dataCounts?.latest_record_timestamp, + earliestTimestampMs: dataCounts?.earliest_record_timestamp, latestResultsTimestampMs: getLatestDataOrBucketTimestamp( - dataCounts.latest_record_timestamp, - dataCounts.latest_bucket_timestamp + dataCounts?.latest_record_timestamp as number, + dataCounts?.latest_bucket_timestamp as number ), isSingleMetricViewerJob: isTimeSeriesViewJob(job), nodeName: job.node ? job.node.name : undefined, @@ -149,7 +175,11 @@ export function jobsProvider(callWithRequest) { tempJob.fullJob = job; } const auditMessage = auditMessagesByJob[tempJob.id]; - if (auditMessage !== undefined && job.create_time <= auditMessage.msgTime) { + if ( + auditMessage !== undefined && + job.create_time !== undefined && + job.create_time <= auditMessage.msgTime + ) { tempJob.auditMessage = { level: auditMessage.highestLevel, text: auditMessage.highestLevelText, @@ -163,19 +193,19 @@ export function jobsProvider(callWithRequest) { async function jobsWithTimerange() { const fullJobsList = await createFullJobsList(); - const jobsMap = {}; + const jobsMap: { [id: string]: string[] } = {}; const jobs = fullJobsList.map(job => { jobsMap[job.job_id] = job.groups || []; const hasDatafeed = typeof job.datafeed_config === 'object' && Object.keys(job.datafeed_config).length > 0; - const timeRange = {}; + const timeRange: { to?: number; from?: number } = {}; const dataCounts = job.data_counts; if (dataCounts !== undefined) { timeRange.to = getLatestDataOrBucketTimestamp( - dataCounts.latest_record_timestamp, - dataCounts.latest_bucket_timestamp + dataCounts.latest_record_timestamp as number, + dataCounts.latest_bucket_timestamp as number ); timeRange.from = dataCounts.earliest_record_timestamp; } @@ -195,56 +225,65 @@ export function jobsProvider(callWithRequest) { return { jobs, jobsMap }; } - async function createFullJobsList(jobIds = []) { - const [JOBS, JOB_STATS, DATAFEEDS, DATAFEED_STATS, CALENDARS, BUCKET_TIMESTAMPS] = [ - 0, - 1, - 2, - 3, - 4, - 5, - ]; - - const jobs = []; - const groups = {}; - const datafeeds = {}; - const calendarsByJobId = {}; - const requests = + async function createFullJobsList(jobIds: string[] = []) { + const jobs: CombinedJobWithStats[] = []; + const groups: { [jobId: string]: string[] } = {}; + const datafeeds: { [id: string]: DatafeedWithStats } = {}; + const calendarsByJobId: { [jobId: string]: string[] } = {}; + const requests: [ + Promise, + Promise, + Promise, + Promise, + Promise, + Promise<{ [id: string]: number | undefined }> + ] = [ + jobIds.length > 0 + ? callAsCurrentUser('ml.jobs', { jobId: jobIds }) // move length check in side call + : callAsCurrentUser('ml.jobs'), jobIds.length > 0 - ? [ - callWithRequest('ml.jobs', { jobId: jobIds }), - callWithRequest('ml.jobStats', { jobId: jobIds }), - ] - : [callWithRequest('ml.jobs'), callWithRequest('ml.jobStats')]; - requests.push( - callWithRequest('ml.datafeeds'), - callWithRequest('ml.datafeedStats'), + ? callAsCurrentUser('ml.jobStats', { jobId: jobIds }) + : callAsCurrentUser('ml.jobStats'), + callAsCurrentUser('ml.datafeeds'), + callAsCurrentUser('ml.datafeedStats'), calMngr.getAllCalendars(), - getLatestBucketTimestampByJob() - ); - - const results = await Promise.all(requests); + getLatestBucketTimestampByJob(), + ]; - if (results[DATAFEEDS] && results[DATAFEEDS].datafeeds) { - results[DATAFEEDS].datafeeds.forEach(datafeed => { - if (results[DATAFEED_STATS] && results[DATAFEED_STATS].datafeeds) { - const datafeedStats = results[DATAFEED_STATS].datafeeds.find( + const [ + jobResults, + jobStatsResults, + datafeedResults, + datafeedStatsResults, + calendarResults, + latestBucketTimestampByJob, + ] = await Promise.all< + MlJobsResponse, + MlJobsStatsResponse, + MlDatafeedsResponse, + MlDatafeedsStatsResponse, + Calendar[], + { [id: string]: number | undefined } + >(requests); + + if (datafeedResults && datafeedResults.datafeeds) { + datafeedResults.datafeeds.forEach(datafeed => { + if (datafeedStatsResults && datafeedStatsResults.datafeeds) { + const datafeedStats = datafeedStatsResults.datafeeds.find( ds => ds.datafeed_id === datafeed.datafeed_id ); if (datafeedStats) { - datafeed.state = datafeedStats.state; - datafeed.timing_stats = datafeedStats.timing_stats; + datafeeds[datafeed.job_id] = { ...datafeed, ...datafeedStats }; } } - datafeeds[datafeed.job_id] = datafeed; }); } // create list of jobs per group. // used for assigning calendars to jobs when a calendar has // only been attached to a group - if (results[JOBS] && results[JOBS].jobs) { - results[JOBS].jobs.forEach(job => { + if (jobResults && jobResults.jobs) { + jobResults.jobs.forEach(job => { calendarsByJobId[job.job_id] = []; if (job.groups !== undefined) { @@ -259,8 +298,8 @@ export function jobsProvider(callWithRequest) { } // assign calendars to jobs - if (results[CALENDARS]) { - results[CALENDARS].forEach(cal => { + if (calendarResults) { + calendarResults.forEach(cal => { cal.job_ids.forEach(id => { if (groups[id]) { groups[id].forEach(jId => { @@ -285,42 +324,42 @@ export function jobsProvider(callWithRequest) { } // create jobs objects containing job stats, datafeeds, datafeed stats and calendars - if (results[JOBS] && results[JOBS].jobs) { - results[JOBS].jobs.forEach(job => { - job.data_counts = {}; - job.model_size_stats = {}; - job.datafeed_config = {}; - - if (calendarsByJobId[job.job_id].length) { - job.calendars = calendarsByJobId[job.job_id]; + if (jobResults && jobResults.jobs) { + jobResults.jobs.forEach(job => { + const tempJob = job as CombinedJobWithStats; + + if (calendarsByJobId[tempJob.job_id].length) { + tempJob.calendars = calendarsByJobId[tempJob.job_id]; } - if (results[JOB_STATS] && results[JOB_STATS].jobs) { - const jobStats = results[JOB_STATS].jobs.find(js => js.job_id === job.job_id); + if (jobStatsResults && jobStatsResults.jobs) { + const jobStats = jobStatsResults.jobs.find(js => js.job_id === tempJob.job_id); if (jobStats !== undefined) { - job.state = jobStats.state; - job.data_counts = jobStats.data_counts; - job.model_size_stats = jobStats.model_size_stats; + tempJob.state = jobStats.state; + tempJob.data_counts = jobStats.data_counts; + tempJob.model_size_stats = jobStats.model_size_stats; if (jobStats.node) { - job.node = jobStats.node; + tempJob.node = jobStats.node; } if (jobStats.open_time) { - job.open_time = jobStats.open_time; + tempJob.open_time = jobStats.open_time; } // Add in the timestamp of the last bucket processed for each job if available. - if (results[BUCKET_TIMESTAMPS] && results[BUCKET_TIMESTAMPS][job.job_id]) { - job.data_counts.latest_bucket_timestamp = results[BUCKET_TIMESTAMPS][job.job_id]; + const latestBucketTimestamp = + latestBucketTimestampByJob && latestBucketTimestampByJob[tempJob.job_id]; + if (latestBucketTimestamp) { + tempJob.data_counts.latest_bucket_timestamp = latestBucketTimestamp; } } } - const datafeed = datafeeds[job.job_id]; + const datafeed = datafeeds[tempJob.job_id]; if (datafeed !== undefined) { - job.datafeed_config = datafeed; + tempJob.datafeed_config = datafeed; } - jobs.push(job); + jobs.push(tempJob); }); } return jobs; @@ -331,7 +370,7 @@ export function jobsProvider(callWithRequest) { const detailed = true; const jobIds = []; try { - const tasksList = await callWithRequest('tasks.list', { actions, detailed }); + const tasksList = await callAsCurrentUser('tasks.list', { actions, detailed }); Object.keys(tasksList.nodes).forEach(nodeId => { const tasks = tasksList.nodes[nodeId].tasks; Object.keys(tasks).forEach(taskId => { @@ -341,7 +380,7 @@ export function jobsProvider(callWithRequest) { } catch (e) { // if the user doesn't have permission to load the task list, // use the jobs list to get the ids of deleting jobs - const { jobs } = await callWithRequest('ml.jobs'); + const { jobs } = await callAsCurrentUser('ml.jobs'); jobIds.push(...jobs.filter(j => j.deleting === true).map(j => j.job_id)); } return { jobIds }; @@ -350,11 +389,13 @@ export function jobsProvider(callWithRequest) { // Checks if each of the jobs in the specified list of IDs exist. // Job IDs in supplied array may contain wildcard '*' characters // e.g. *_low_request_rate_ecs - async function jobsExist(jobIds = []) { + async function jobsExist(jobIds: string[] = []) { // Get the list of job IDs. - const jobsInfo = await callWithRequest('ml.jobs', { jobId: jobIds }); + const jobsInfo = await callAsCurrentUser('ml.jobs', { + jobId: jobIds, + }); - const results = {}; + const results: { [id: string]: boolean } = {}; if (jobsInfo.count > 0) { const allJobIds = jobsInfo.jobs.map(job => job.job_id); @@ -375,8 +416,8 @@ export function jobsProvider(callWithRequest) { } async function getAllJobAndGroupIds() { - const { getAllGroups } = groupsProvider(callWithRequest); - const jobs = await callWithRequest('ml.jobs'); + const { getAllGroups } = groupsProvider(callAsCurrentUser); + const jobs = await callAsCurrentUser('ml.jobs'); const jobIds = jobs.jobs.map(job => job.job_id); const groups = await getAllGroups(); const groupIds = groups.map(group => group.id); @@ -387,10 +428,10 @@ export function jobsProvider(callWithRequest) { }; } - async function getLookBackProgress(jobId, start, end) { + async function getLookBackProgress(jobId: string, start: number, end: number) { const datafeedId = `datafeed-${jobId}`; const [jobStats, isRunning] = await Promise.all([ - callWithRequest('ml.jobStats', { jobId: [jobId] }), + callAsCurrentUser('ml.jobStats', { jobId: [jobId] }), isDatafeedRunning(datafeedId), ]); @@ -408,8 +449,10 @@ export function jobsProvider(callWithRequest) { return { progress: 0, isRunning: false, isJobClosed: true }; } - async function isDatafeedRunning(datafeedId) { - const stats = await callWithRequest('ml.datafeedStats', { datafeedId: [datafeedId] }); + async function isDatafeedRunning(datafeedId: string) { + const stats = await callAsCurrentUser('ml.datafeedStats', { + datafeedId: [datafeedId], + }); if (stats.datafeeds.length) { const state = stats.datafeeds[0].state; return ( diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts index d3930ecf44c8d5..ada2a1222281db 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_cardinality.d.ts @@ -5,16 +5,6 @@ */ import { APICaller } from 'src/core/server'; -import { - Job, - Datafeed, -} from '../../../../../legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs'; +import { CombinedJob } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; -interface ValidateCardinalityConfig extends Job { - datafeed_config?: Datafeed; -} - -export function validateCardinality( - callAsCurrentUser: APICaller, - job: ValidateCardinalityConfig -): any[]; +export function validateCardinality(callAsCurrentUser: APICaller, job: CombinedJob): any[]; diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts index 551b5ab9173a41..e2f6e0dca1a6f4 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_time_range.ts @@ -7,7 +7,7 @@ import { APICaller } from 'src/core/server'; import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/server'; import { parseInterval } from '../../../../../legacy/plugins/ml/common/util/parse_interval'; -import { CombinedJob } from '../../../../../legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs'; +import { CombinedJob } from '../../../../../legacy/plugins/ml/common/types/anomaly_detection_jobs'; // @ts-ignore import { validateJobObject } from './validate_job_object'; diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index 9ad2f80a1e66b4..bb4530bfb1c6c5 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -20,7 +20,7 @@ import { topCategoriesSchema, updateGroupsSchema, } from './schemas/job_service_schema'; -// @ts-ignore no declaration module + import { jobServiceProvider } from '../models/job_service'; import { categorizationExamplesProvider } from '../models/job_service/new_job'; @@ -209,8 +209,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { mlLicense.fullLicenseAPIGuard(async (context, request, response) => { try { const { jobsWithTimerange } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); - const { dateFormatTz } = request.body; - const resp = await jobsWithTimerange(dateFormatTz); + const resp = await jobsWithTimerange(); return response.ok({ body: resp, @@ -420,10 +419,7 @@ export function jobServiceRoutes({ router, mlLicense }: RouteInitialization) { splitFieldValue, } = request.body; - const { newJobLineChart } = jobServiceProvider( - context.ml!.mlClient.callAsCurrentUser, - request - ); + const { newJobLineChart } = jobServiceProvider(context.ml!.mlClient.callAsCurrentUser); const resp = await newJobLineChart( indexPatternTitle, timeField, diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts index 8a1ef5f196eba0..47c69d3f6d7ade 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/anomaly_explorer.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; import { Job, Datafeed, -} from '../../../../..//legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs'; +} from '../../../../..//legacy/plugins/ml/common/types/anomaly_detection_jobs'; const JOB_CONFIG: Job = { job_id: `fq_multi_1_ae`, diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts index 407e002f11f99e..f2d12b7d515cda 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_viewer.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; import { Job, Datafeed, -} from '../../../../..//legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs'; +} from '../../../../..//legacy/plugins/ml/common/types/anomaly_detection_jobs'; const JOB_CONFIG: Job = { job_id: `fq_single_1_smv`, diff --git a/x-pack/test/functional/services/machine_learning/api.ts b/x-pack/test/functional/services/machine_learning/api.ts index 7330a7b9812d58..976eb51318915b 100644 --- a/x-pack/test/functional/services/machine_learning/api.ts +++ b/x-pack/test/functional/services/machine_learning/api.ts @@ -10,8 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { JOB_STATE, DATAFEED_STATE } from '../../../../legacy/plugins/ml/common/constants/states'; import { DATA_FRAME_TASK_STATE } from '../../../../legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/common'; -import { Job } from '../../../..//legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/job'; -import { Datafeed } from '../../../..//legacy/plugins/ml/public/application/jobs/new_job/common/job_creator/configs/datafeed'; +import { Job, Datafeed } from '../../../..//legacy/plugins/ml/common/types/anomaly_detection_jobs'; export type MlApi = ProvidedType;