Skip to content

Commit

Permalink
[ML] Anomaly Detection: Migrate validation messages links to use docL…
Browse files Browse the repository at this point in the history
…inks. (#94568) (#94778)

- To make use of the docsLinks service which is only usable in client side code, Anomaly Detection's validation messages are not fully returned from the server anymore. Instead just the message ID and necessary metadata to parse the message template gets returned.
- getMessages() no longer uses inline hard coded documentation links but picks links from the docsLinks service.
- The code that rendered the messages originally on the server has been move to a function parseMessages() which can now be used on the client side and accepts the docsLinks services to get URLs to documentation from it.
- This means we no longer need to get the current version/branch information for the server side code.
- Tests have been updated to reflect the changes: API integration tests only check for the now reduced messages containing only message IDs and metadata. The expected results of the API integration tests are used as mocks for the client side function parseMessages(), this allows use to cover the same code and messages as previously.

Co-authored-by: Walter Rafelsberger <walter@elastic.co>
  • Loading branch information
kibanamachine and walterra authored Mar 17, 2021
1 parent 7eb713a commit 4d2c8e6
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 276 deletions.
9 changes: 9 additions & 0 deletions src/core/public/doc_links/doc_links_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,16 @@ export class DocLinksService {
aggregations: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-configuring-aggregation.html`,
anomalyDetection: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/xpack-ml.html`,
anomalyDetectionJobs: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-jobs.html`,
anomalyDetectionConfiguringCategories: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-configuring-categories.html`,
anomalyDetectionBucketSpan: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html#bucket-span`,
anomalyDetectionCardinality: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html#cardinality`,
anomalyDetectionCreateJobs: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html`,
anomalyDetectionDetectors: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html#detectors`,
anomalyDetectionInfluencers: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-influencers.html`,
anomalyDetectionJobResource: `${ELASTICSEARCH_DOCS}ml-put-job.html#ml-put-job-path-parms`,
anomalyDetectionJobResourceAnalysisConfig: `${ELASTICSEARCH_DOCS}ml-put-job.html#put-analysisconfig`,
anomalyDetectionJobTips: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html#job-tips`,
anomalyDetectionModelMemoryLimits: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/create-jobs.html#model-memory-limits`,
calendars: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-calendars.html`,
classificationEvaluation: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfanalytics-evaluate.html#ml-dfanalytics-classification`,
customRules: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-rules.html`,
Expand Down
81 changes: 81 additions & 0 deletions x-pack/plugins/ml/common/constants/messages.test.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

/* To keep tests in sync, these mocks should be used in API intregation tests
* as expected values to check against, and in the client side jest tests to be
* the values used as function arguments for `parseMessages()` to retrieve the
* messages populated with translations and documentation links.
*/

export const basicValidJobMessages = [
{
id: 'job_id_valid',
},
{
id: 'detectors_function_not_empty',
},
{
id: 'success_bucket_span',
bucketSpan: '15m',
},
{
id: 'success_time_range',
},
{
id: 'success_mml',
},
];

export const basicInvalidJobMessages = [
{
id: 'job_id_invalid',
},
{
id: 'detectors_function_not_empty',
},
{
id: 'bucket_span_valid',
bucketSpan: '15m',
},
{
id: 'skipped_extended_tests',
},
];

export const nonBasicIssuesMessages = [
{
id: 'job_id_valid',
},
{
id: 'detectors_function_not_empty',
},
{
id: 'cardinality_model_plot_high',
},
{
id: 'cardinality_partition_field',
fieldName: 'order_id',
},
{
id: 'bucket_span_high',
},
{
bucketSpanCompareFactor: 25,
id: 'time_range_short',
minTimeSpanReadable: '2 hours',
},
{
id: 'success_influencers',
},
{
id: 'half_estimated_mml_greater_than_mml',
mml: '1MB',
},
{
id: 'missing_summary_count_field_name',
},
];
178 changes: 178 additions & 0 deletions x-pack/plugins/ml/common/constants/messages.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { docLinksServiceMock } from 'src/core/public/mocks';

import { parseMessages } from './messages';

import {
basicValidJobMessages,
basicInvalidJobMessages,
nonBasicIssuesMessages,
} from './messages.test.mock';

describe('Constants: Messages parseMessages()', () => {
const docLinksService = docLinksServiceMock.createStartContract();

it('should parse valid job configuration messages', () => {
expect(parseMessages(basicValidJobMessages, docLinksService)).toStrictEqual([
{
heading: 'Job ID format is valid',
id: 'job_id_valid',
status: 'success',
text:
'Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character, and is no more than 64 characters long.',
url:
'https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/ml-put-job.html#ml-put-job-path-parms',
},
{
heading: 'Detector functions',
id: 'detectors_function_not_empty',
status: 'success',
text: 'Presence of detector functions validated in all detectors.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
},
{
bucketSpan: '15m',
heading: 'Bucket span',
id: 'success_bucket_span',
status: 'success',
text: 'Format of "15m" is valid and passed validation checks.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#bucket-span',
},
{
heading: 'Time range',
id: 'success_time_range',
status: 'success',
text: 'Valid and long enough to model patterns in the data.',
},
{
heading: 'Model memory limit',
id: 'success_mml',
status: 'success',
text: 'Valid and within the estimated model memory limit.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#model-memory-limits',
},
]);
});

it('should parse basic invalid job configuration messages', () => {
expect(parseMessages(basicInvalidJobMessages, docLinksService)).toStrictEqual([
{
id: 'job_id_invalid',
status: 'error',
text:
'Job ID is invalid. It can contain lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores and must start and end with an alphanumeric character.',
url:
'https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/ml-put-job.html#ml-put-job-path-parms',
},
{
heading: 'Detector functions',
id: 'detectors_function_not_empty',
status: 'success',
text: 'Presence of detector functions validated in all detectors.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
},
{
bucketSpan: '15m',
heading: 'Bucket span',
id: 'bucket_span_valid',
status: 'success',
text: 'Format of "15m" is valid.',
url:
'https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/ml-put-job.html#put-analysisconfig',
},
{
id: 'skipped_extended_tests',
status: 'warning',
text:
'Skipped additional checks because the basic requirements of the job configuration were not met.',
},
]);
});

it('should parse non-basic issues messages', () => {
expect(parseMessages(nonBasicIssuesMessages, docLinksService)).toStrictEqual([
{
heading: 'Job ID format is valid',
id: 'job_id_valid',
status: 'success',
text:
'Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character, and is no more than 64 characters long.',
url:
'https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/ml-put-job.html#ml-put-job-path-parms',
},
{
heading: 'Detector functions',
id: 'detectors_function_not_empty',
status: 'success',
text: 'Presence of detector functions validated in all detectors.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#detectors',
},
{
id: 'cardinality_model_plot_high',
status: 'warning',
text:
'The estimated cardinality of undefined of fields relevant to creating model plots might result in resource intensive jobs.',
},
{
fieldName: 'order_id',
id: 'cardinality_partition_field',
status: 'warning',
text:
'Cardinality of partition_field "order_id" is above 1000 and might result in high memory usage.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#cardinality',
},
{
heading: 'Bucket span',
id: 'bucket_span_high',
status: 'info',
text:
'Bucket span is 1 day or more. Be aware that days are considered as UTC days, not local days.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#bucket-span',
},
{
bucketSpanCompareFactor: 25,
heading: 'Time range',
id: 'time_range_short',
minTimeSpanReadable: '2 hours',
status: 'warning',
text:
'The selected or available time range might be too short. The recommended minimum time range should be at least 2 hours and 25 times the bucket span.',
},
{
id: 'success_influencers',
status: 'success',
text: 'Influencer configuration passed the validation checks.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/ml-influencers.html',
},
{
id: 'half_estimated_mml_greater_than_mml',
mml: '1MB',
status: 'warning',
text:
'The specified model memory limit is less than half of the estimated model memory limit and will likely hit the hard limit.',
url:
'https://www.elastic.co/guide/en/machine-learning/mocked-test-branch/create-jobs.html#model-memory-limits',
},
{
id: 'missing_summary_count_field_name',
status: 'error',
text:
'A job configured with a datafeed with aggregations must set summary_count_field_name; use doc_count or suitable alternative.',
},
]);
});
});
Loading

0 comments on commit 4d2c8e6

Please sign in to comment.