diff --git a/x-pack/legacy/plugins/ml/common/constants/detector_rule.js b/x-pack/legacy/plugins/ml/common/constants/detector_rule.ts similarity index 53% rename from x-pack/legacy/plugins/ml/common/constants/detector_rule.js rename to x-pack/legacy/plugins/ml/common/constants/detector_rule.ts index f07b82f4d2d3ec..81120d01318ab4 100644 --- a/x-pack/legacy/plugins/ml/common/constants/detector_rule.js +++ b/x-pack/legacy/plugins/ml/common/constants/detector_rule.ts @@ -8,28 +8,28 @@ * Contains values for ML job detector rules. */ -export const ACTION = { - SKIP_MODEL_UPDATE: 'skip_model_update', - SKIP_RESULT: 'skip_result', -}; +export enum ACTION { + SKIP_MODEL_UPDATE = 'skip_model_update', + SKIP_RESULT = 'skip_result', +} -export const FILTER_TYPE = { - EXCLUDE: 'exclude', - INCLUDE: 'include', -}; +export enum FILTER_TYPE { + EXCLUDE = 'exclude', + INCLUDE = 'include', +} -export const APPLIES_TO = { - ACTUAL: 'actual', - DIFF_FROM_TYPICAL: 'diff_from_typical', - TYPICAL: 'typical', -}; +export enum APPLIES_TO { + ACTUAL = 'actual', + DIFF_FROM_TYPICAL = 'diff_from_typical', + TYPICAL = 'typical', +} -export const OPERATOR = { - LESS_THAN: 'lt', - LESS_THAN_OR_EQUAL: 'lte', - GREATER_THAN: 'gt', - GREATER_THAN_OR_EQUAL: 'gte', -}; +export enum OPERATOR { + LESS_THAN = 'lt', + LESS_THAN_OR_EQUAL = 'lte', + GREATER_THAN = 'gt', + GREATER_THAN_OR_EQUAL = 'gte', +} // List of detector functions which don't support rules with numeric conditions. export const CONDITIONS_NOT_SUPPORTED_FUNCTIONS = ['freq_rare', 'lat_long', 'metric', 'rare']; diff --git a/x-pack/legacy/plugins/ml/common/types/detector_rules.ts b/x-pack/legacy/plugins/ml/common/types/detector_rules.ts new file mode 100644 index 00000000000000..c94e5d1327363f --- /dev/null +++ b/x-pack/legacy/plugins/ml/common/types/detector_rules.ts @@ -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 { ACTION, FILTER_TYPE, APPLIES_TO, OPERATOR } from '../constants/detector_rule'; + +export interface DetectorRuleScope { + [id: string]: { + filter_id: string; + filter_type: FILTER_TYPE; + }; +} + +export interface DetectorRuleCondition { + applies_to: APPLIES_TO; + operator: OPERATOR; + value: number; +} + +export interface DetectorRule { + actions: ACTION[]; + scope?: DetectorRuleScope; + conditions?: DetectorRuleCondition[]; +} diff --git a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js b/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts similarity index 57% rename from x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js rename to x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts index d644494c206066..f40663a5eb6b2d 100644 --- a/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.js +++ b/x-pack/legacy/plugins/ml/server/models/filter/filter_manager.ts @@ -5,22 +5,75 @@ */ import Boom from 'boom'; +import { IScopedClusterClient } from 'src/core/server'; + +import { DetectorRule, DetectorRuleScope } from '../../../common/types/detector_rules'; + +export interface Filter { + filter_id: string; + description?: string; + items: string[]; +} + +export interface FormFilter { + filterId: string; + description?: string; + addItems?: string[]; + removeItems?: string[]; +} + +export interface FilterRequest { + filter_id: string; + description?: string; + add_items?: string[]; + remove_items?: string[]; +} + +interface FilterUsage { + jobs: string[]; + detectors: string[]; +} + +interface FilterStats { + filter_id: string; + description?: string; + item_count: number; + used_by: FilterUsage; +} + +interface FiltersInUse { + [id: string]: FilterUsage; +} + +interface PartialDetector { + detector_description: string; + custom_rules: DetectorRule[]; +} + +interface PartialJob { + job_id: string; + analysis_config: { + detectors: PartialDetector[]; + }; +} export class FilterManager { - constructor(callWithRequest) { - this.callWithRequest = callWithRequest; + private _client: IScopedClusterClient['callAsCurrentUser']; + + constructor(client: IScopedClusterClient['callAsCurrentUser']) { + this._client = client; } - async getFilter(filterId) { + async getFilter(filterId: string) { try { const [JOBS, FILTERS] = [0, 1]; const results = await Promise.all([ - this.callWithRequest('ml.jobs'), - this.callWithRequest('ml.filters', { filterId }), + this._client('ml.jobs'), + this._client('ml.filters', { filterId }), ]); if (results[FILTERS] && results[FILTERS].filters.length) { - let filtersInUse = {}; + let filtersInUse: FiltersInUse = {}; if (results[JOBS] && results[JOBS].jobs) { filtersInUse = this.buildFiltersInUse(results[JOBS].jobs); } @@ -38,7 +91,7 @@ export class FilterManager { async getAllFilters() { try { - const filtersResp = await this.callWithRequest('ml.filters'); + const filtersResp = await this._client('ml.filters'); return filtersResp.filters; } catch (error) { throw Boom.badRequest(error); @@ -48,13 +101,10 @@ export class FilterManager { async getAllFilterStats() { try { const [JOBS, FILTERS] = [0, 1]; - const results = await Promise.all([ - this.callWithRequest('ml.jobs'), - this.callWithRequest('ml.filters'), - ]); + const results = await Promise.all([this._client('ml.jobs'), this._client('ml.filters')]); // Build a map of filter_ids against jobs and detectors using that filter. - let filtersInUse = {}; + let filtersInUse: FiltersInUse = {}; if (results[JOBS] && results[JOBS].jobs) { filtersInUse = this.buildFiltersInUse(results[JOBS].jobs); } @@ -64,10 +114,10 @@ export class FilterManager { // description // item_count // jobs using the filter - const filterStats = []; + const filterStats: FilterStats[] = []; if (results[FILTERS] && results[FILTERS].filters) { - results[FILTERS].filters.forEach(filter => { - const stats = { + results[FILTERS].filters.forEach((filter: Filter) => { + const stats: FilterStats = { filter_id: filter.filter_id, description: filter.description, item_count: filter.items.length, @@ -83,32 +133,32 @@ export class FilterManager { } } - async newFilter(filter) { + async newFilter(filter: FormFilter) { const filterId = filter.filterId; delete filter.filterId; try { // Returns the newly created filter. - return await this.callWithRequest('ml.addFilter', { filterId, body: filter }); + return await this._client('ml.addFilter', { filterId, body: filter }); } catch (error) { throw Boom.badRequest(error); } } - async updateFilter(filterId, description, addItems, removeItems) { + async updateFilter(filterId: string, filter: FormFilter) { try { - const body = {}; - if (description !== undefined) { - body.description = description; + const body: FilterRequest = { filter_id: filterId }; + if (filter.description !== undefined) { + body.description = filter.description; } - if (addItems !== undefined) { - body.add_items = addItems; + if (filter.addItems !== undefined) { + body.add_items = filter.addItems; } - if (removeItems !== undefined) { - body.remove_items = removeItems; + if (filter.removeItems !== undefined) { + body.remove_items = filter.removeItems; } // Returns the newly updated filter. - return await this.callWithRequest('ml.updateFilter', { + return await this._client('ml.updateFilter', { filterId, body, }); @@ -117,13 +167,13 @@ export class FilterManager { } } - async deleteFilter(filterId) { - return this.callWithRequest('ml.deleteFilter', { filterId }); + async deleteFilter(filterId: string) { + return this._client('ml.deleteFilter', { filterId }); } - buildFiltersInUse(jobsList) { + buildFiltersInUse(jobsList: PartialJob[]) { // Build a map of filter_ids against jobs and detectors using that filter. - const filtersInUse = {}; + const filtersInUse: FiltersInUse = {}; jobsList.forEach(job => { const detectors = job.analysis_config.detectors; detectors.forEach(detector => { @@ -131,9 +181,10 @@ export class FilterManager { const rules = detector.custom_rules; rules.forEach(rule => { if (rule.scope) { - const scopeFields = Object.keys(rule.scope); + const ruleScope: DetectorRuleScope = rule.scope; + const scopeFields = Object.keys(ruleScope); scopeFields.forEach(scopeField => { - const filter = rule.scope[scopeField]; + const filter = ruleScope[scopeField]; const filterId = filter.filter_id; if (filtersInUse[filterId] === undefined) { filtersInUse[filterId] = { jobs: [], detectors: [] }; diff --git a/x-pack/legacy/plugins/ml/server/models/filter/index.ts b/x-pack/legacy/plugins/ml/server/models/filter/index.ts new file mode 100644 index 00000000000000..ed4802f6d5ee69 --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/models/filter/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { FilterManager, Filter, FormFilter } from './filter_manager'; diff --git a/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts b/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts new file mode 100644 index 00000000000000..dffee56565c73a --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/new_platform/filters_schema.ts @@ -0,0 +1,19 @@ +/* + * 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 { schema } from '@kbn/config-schema'; + +export const createFilterSchema = { + filterId: schema.string(), + description: schema.maybe(schema.string()), + items: schema.arrayOf(schema.string()), +}; + +export const updateFilterSchema = { + description: schema.maybe(schema.string()), + addItems: schema.maybe(schema.arrayOf(schema.string())), + removeItems: schema.maybe(schema.arrayOf(schema.string())), +}; diff --git a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts b/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts index 68ab88744278ef..068bfc40f53e19 100644 --- a/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts +++ b/x-pack/legacy/plugins/ml/server/new_platform/plugin.ts @@ -48,7 +48,6 @@ import { dataVisualizerRoutes } from '../routes/data_visualizer'; import { calendars } from '../routes/calendars'; // @ts-ignore: could not find declaration file for module import { fieldsService } from '../routes/fields_service'; -// @ts-ignore: could not find declaration file for module import { filtersRoutes } from '../routes/filters'; // @ts-ignore: could not find declaration file for module import { resultsServiceRoutes } from '../routes/results_service'; diff --git a/x-pack/legacy/plugins/ml/server/routes/apidoc.json b/x-pack/legacy/plugins/ml/server/routes/apidoc.json index 3fac715fef85a0..be1554bf55f78e 100644 --- a/x-pack/legacy/plugins/ml/server/routes/apidoc.json +++ b/x-pack/legacy/plugins/ml/server/routes/apidoc.json @@ -57,7 +57,7 @@ "DeleteJobs", "CloseJobs", "JobsSummary", - "JobsWithTimerange", + "JobsWithTimeRange", "CreateFullJobsList", "GetAllGroups", "UpdateGroups", @@ -69,6 +69,13 @@ "GetAllJobAndGroupIds", "GetLookBackProgress", "ValidateCategoryExamples", - "TopCategories" + "TopCategories", + "Filters", + "GetFilters", + "GetFilterById", + "CreateFilter", + "UpdateFilter", + "DeleteFilter", + "GetFiltersStats" ] } diff --git a/x-pack/legacy/plugins/ml/server/routes/filters.js b/x-pack/legacy/plugins/ml/server/routes/filters.js deleted file mode 100644 index b09566c6adfbe8..00000000000000 --- a/x-pack/legacy/plugins/ml/server/routes/filters.js +++ /dev/null @@ -1,126 +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 { callWithRequestFactory } from '../client/call_with_request_factory'; -import { wrapError } from '../client/errors'; -import { FilterManager } from '../models/filter'; - -// TODO - add function for returning a list of just the filter IDs. -// TODO - add function for returning a list of filter IDs plus item count. -function getAllFilters(callWithRequest) { - const mgr = new FilterManager(callWithRequest); - return mgr.getAllFilters(); -} - -function getAllFilterStats(callWithRequest) { - const mgr = new FilterManager(callWithRequest); - return mgr.getAllFilterStats(); -} - -function getFilter(callWithRequest, filterId) { - const mgr = new FilterManager(callWithRequest); - return mgr.getFilter(filterId); -} - -function newFilter(callWithRequest, filter) { - const mgr = new FilterManager(callWithRequest); - return mgr.newFilter(filter); -} - -function updateFilter(callWithRequest, filterId, description, addItems, removeItems) { - const mgr = new FilterManager(callWithRequest); - return mgr.updateFilter(filterId, description, addItems, removeItems); -} - -function deleteFilter(callWithRequest, filterId) { - const mgr = new FilterManager(callWithRequest); - return mgr.deleteFilter(filterId); -} - -export function filtersRoutes({ commonRouteConfig, elasticsearchPlugin, route }) { - route({ - method: 'GET', - path: '/api/ml/filters', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - return getAllFilters(callWithRequest).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'GET', - path: '/api/ml/filters/_stats', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - return getAllFilterStats(callWithRequest).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'GET', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - return getFilter(callWithRequest, filterId).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'PUT', - path: '/api/ml/filters', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const body = request.payload; - return newFilter(callWithRequest, body).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'PUT', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - const payload = request.payload; - return updateFilter( - callWithRequest, - filterId, - payload.description, - payload.addItems, - payload.removeItems - ).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); - - route({ - method: 'DELETE', - path: '/api/ml/filters/{filterId}', - handler(request) { - const callWithRequest = callWithRequestFactory(elasticsearchPlugin, request); - const filterId = request.params.filterId; - return deleteFilter(callWithRequest, filterId).catch(resp => wrapError(resp)); - }, - config: { - ...commonRouteConfig, - }, - }); -} diff --git a/x-pack/legacy/plugins/ml/server/routes/filters.ts b/x-pack/legacy/plugins/ml/server/routes/filters.ts new file mode 100644 index 00000000000000..a06f8d4f8b727b --- /dev/null +++ b/x-pack/legacy/plugins/ml/server/routes/filters.ts @@ -0,0 +1,227 @@ +/* + * 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 { RequestHandlerContext } from 'src/core/server'; +import { schema } from '@kbn/config-schema'; +import { licensePreRoutingFactory } from '../new_platform/licence_check_pre_routing_factory'; +import { wrapError } from '../client/error_wrapper'; +import { RouteInitialization } from '../new_platform/plugin'; +import { createFilterSchema, updateFilterSchema } from '../new_platform/filters_schema'; +import { FilterManager, FormFilter } from '../models/filter'; + +// TODO - add function for returning a list of just the filter IDs. +// TODO - add function for returning a list of filter IDs plus item count. +function getAllFilters(context: RequestHandlerContext) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getAllFilters(); +} + +function getAllFilterStats(context: RequestHandlerContext) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getAllFilterStats(); +} + +function getFilter(context: RequestHandlerContext, filterId: string) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.getFilter(filterId); +} + +function newFilter(context: RequestHandlerContext, filter: FormFilter) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.newFilter(filter); +} + +function updateFilter(context: RequestHandlerContext, filterId: string, filter: FormFilter) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.updateFilter(filterId, filter); +} + +function deleteFilter(context: RequestHandlerContext, filterId: string) { + const mgr = new FilterManager(context.ml!.mlClient.callAsCurrentUser); + return mgr.deleteFilter(filterId); +} + +export function filtersRoutes({ xpackMainPlugin, router }: RouteInitialization) { + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters Gets filters + * @apiName GetFilters + * @apiDescription Retrieves the list of filters which are used for custom rules in anomaly detection. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object[]} filters list of filters + */ + router.get( + { + path: '/api/ml/filters', + validate: false, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getAllFilters(context); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters/:filterId Gets filter by ID + * @apiName GetFilterById + * @apiDescription Retrieves the filter with the specified ID. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter the filter with the specified ID + */ + router.get( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getFilter(context, request.params.filterId); + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {put} /api/ml/filters Creates a filter + * @apiName CreateFilter + * @apiDescription Instantiates a filter, for use by custom rules in anomaly detection. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter created filter + */ + router.put( + { + path: '/api/ml/filters', + validate: { + body: schema.object(createFilterSchema), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const body = request.body; + const resp = await newFilter(context, body); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {put} /api/ml/filters/:filterId Updates a filter + * @apiName UpdateFilter + * @apiDescription Updates the description of a filter, adds items or removes items. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object} filter updated filter + */ + router.put( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + body: schema.object(updateFilterSchema), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { filterId } = request.params; + const body = request.body; + const resp = await updateFilter(context, filterId, body); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {delete} /api/ml/filters/:filterId Delete filter + * @apiName DeleteFilter + * @apiDescription Deletes the filter with the specified ID. + * + * @apiParam {String} filterId the ID of the filter to delete + */ + router.delete( + { + path: '/api/ml/filters/{filterId}', + validate: { + params: schema.object({ filterId: schema.string() }), + }, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const { filterId } = request.params; + const resp = await deleteFilter(context, filterId); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup Filters + * + * @api {get} /api/ml/filters/_stats Gets filters stats + * @apiName GetFiltersStats + * @apiDescription Retrieves the list of filters which are used for custom rules in anomaly detection, + * with stats on the list of jobs and detectors which are using each filter. + * + * @apiSuccess {Boolean} success + * @apiSuccess {Object[]} filters list of filters with stats on usage + */ + router.get( + { + path: '/api/ml/filters/_stats', + validate: false, + }, + licensePreRoutingFactory(xpackMainPlugin, async (context, request, response) => { + try { + const resp = await getAllFilterStats(context); + + return response.ok({ + body: resp, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); +} diff --git a/x-pack/legacy/plugins/ml/server/routes/job_service.ts b/x-pack/legacy/plugins/ml/server/routes/job_service.ts index 3af651c92353b2..9aa3960e59e4c8 100644 --- a/x-pack/legacy/plugins/ml/server/routes/job_service.ts +++ b/x-pack/legacy/plugins/ml/server/routes/job_service.ts @@ -29,7 +29,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/force_start_datafeeds + * @api {post} /api/ml/jobs/force_start_datafeeds Start datafeeds * @apiName ForceStartDatafeeds * @apiDescription Starts one or more datafeeds */ @@ -58,7 +58,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/stop_datafeeds + * @api {post} /api/ml/jobs/stop_datafeeds Stop datafeeds * @apiName StopDatafeeds * @apiDescription Stops one or more datafeeds */ @@ -87,7 +87,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/delete_jobs + * @api {post} /api/ml/jobs/delete_jobs Delete jobs * @apiName DeleteJobs * @apiDescription Deletes an existing anomaly detection job */ @@ -116,7 +116,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/close_jobs + * @api {post} /api/ml/jobs/close_jobs Close jobs * @apiName CloseJobs * @apiDescription Closes one or more anomaly detection jobs */ @@ -145,7 +145,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_summary + * @api {post} /api/ml/jobs/jobs_summary Jobs summary * @apiName JobsSummary * @apiDescription Creates a summary jobs list. Jobs include job stats, datafeed stats, and calendars. */ @@ -174,9 +174,9 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_with_time_range - * @apiName JobsWithTimerange - * @apiDescription Creates a list of jobs with data about the job's timerange + * @api {post} /api/ml/jobs/jobs_with_time_range Jobs with time range + * @apiName JobsWithTimeRange + * @apiDescription Creates a list of jobs with data about the job's time range */ router.post( { @@ -203,7 +203,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs + * @api {post} /api/ml/jobs/jobs Create jobs list * @apiName CreateFullJobsList * @apiDescription Creates a list of jobs */ @@ -232,7 +232,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/groups + * @api {get} /api/ml/jobs/groups Get job groups * @apiName GetAllGroups * @apiDescription Returns array of group objects with job ids listed for each group */ @@ -258,7 +258,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/update_groups + * @api {post} /api/ml/jobs/update_groups Update job groups * @apiName UpdateGroups * @apiDescription Updates 'groups' property of an anomaly detection job */ @@ -287,7 +287,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/deleting_jobs_tasks + * @api {get} /api/ml/jobs/deleting_jobs_tasks Get deleting job tasks * @apiName DeletingJobTasks * @apiDescription Gets the ids of deleting anomaly detection jobs */ @@ -313,7 +313,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/jobs_exist + * @api {post} /api/ml/jobs/jobs_exist Check if jobs exist * @apiName JobsExist * @apiDescription Checks if each of the jobs in the specified list of IDs exist */ @@ -342,7 +342,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/new_job_caps/:indexPattern + * @api {get} /api/ml/jobs/new_job_caps/:indexPattern Get new job capabilities * @apiName NewJobCaps * @apiDescription Retrieve the capabilities of fields for indices */ @@ -374,7 +374,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/new_job_line_chart + * @api {post} /api/ml/jobs/new_job_line_chart Get job line chart data * @apiName NewJobLineChart * @apiDescription Returns line chart data for anomaly detection job */ @@ -427,7 +427,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/new_job_population_chart + * @api {post} /api/ml/jobs/new_job_population_chart Get population job chart data * @apiName NewJobPopulationChart * @apiDescription Returns population job chart data */ @@ -477,7 +477,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {get} /api/ml/jobs/all_jobs_and_group_ids + * @api {get} /api/ml/jobs/all_jobs_and_group_ids Get all job and group IDs * @apiName GetAllJobAndGroupIds * @apiDescription Returns a list of all job IDs and all group IDs */ @@ -503,7 +503,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/look_back_progress + * @api {post} /api/ml/jobs/look_back_progress Get lookback progress * @apiName GetLookBackProgress * @apiDescription Returns current progress of anomaly detection job */ @@ -532,7 +532,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/categorization_field_examples + * @api {post} /api/ml/jobs/categorization_field_examples Get categorization field examples * @apiName ValidateCategoryExamples * @apiDescription Validates category examples */ @@ -582,7 +582,7 @@ export function jobServiceRoutes({ xpackMainPlugin, router }: RouteInitializatio /** * @apiGroup JobService * - * @api {post} /api/ml/jobs/top_categories + * @api {post} /api/ml/jobs/top_categories Get top categories * @apiName TopCategories * @apiDescription Returns list of top categories */