diff --git a/x-pack/plugins/ml/common/util/job_utils.js b/x-pack/plugins/ml/common/util/job_utils.js
index 59e9273b236a8..85a1bfc6d9042 100644
--- a/x-pack/plugins/ml/common/util/job_utils.js
+++ b/x-pack/plugins/ml/common/util/job_utils.js
@@ -350,7 +350,10 @@ export function basicJobValidation(job, fields, limits) {
messages.push({ id: 'bucket_span_invalid' });
valid = false;
} else {
- messages.push({ id: 'bucket_span_valid' });
+ messages.push({
+ id: 'bucket_span_valid',
+ bucketSpan: job.analysis_config.bucket_span
+ });
}
}
diff --git a/x-pack/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap b/x-pack/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap
index 485d4a5530342..50ea6c2fc67e5 100644
--- a/x-pack/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap
+++ b/x-pack/plugins/ml/public/components/validate_job/__snapshots__/validate_job_view.test.js.snap
@@ -31,6 +31,25 @@ exports[`ValidateJob renders button and modal with a message 1`] = `
}
}
/>
+
+ Job validation performs certain checks against job configurations and underlying source data and provides specific advice on how to adjust settings that are more likely to produce insightful results.
+
+
+ For more information, see
+
+ Machine Learning Job Tips
+
+ .
+
`;
@@ -71,6 +90,26 @@ exports[`ValidateJob renders the button and modal with a success message 1`] = `
+ >
+
+ Job validation performs certain checks against job configurations and underlying source data and provides specific advice on how to adjust settings that are more likely to produce insightful results.
+
+
+ For more information, see
+
+ Machine Learning Job Tips
+
+ .
+
+
`;
diff --git a/x-pack/plugins/ml/public/components/validate_job/validate_job_view.js b/x-pack/plugins/ml/public/components/validate_job/validate_job_view.js
index ddd37a5246b72..adfd66bdd7722 100644
--- a/x-pack/plugins/ml/public/components/validate_job/validate_job_view.js
+++ b/x-pack/plugins/ml/public/components/validate_job/validate_job_view.js
@@ -23,9 +23,14 @@ import {
EuiModalHeader,
EuiModalHeaderTitle,
EuiOverlayMask,
- EuiSpacer
+ EuiSpacer,
+ EuiText
} from '@elastic/eui';
+import { metadata } from 'ui/metadata';
+// metadata.branch corresponds to the version used in documentation links.
+const jobTipsUrl = `https://www.elastic.co/guide/en/kibana/${metadata.branch}/job-tips.html`;
+
// don't use something like plugins/ml/../common
// because it won't work with the jest tests
import { VALIDATION_STATUS } from '../../../common/constants/validation';
@@ -101,9 +106,11 @@ const Callout = ({ message }) => (
}
+ title={message.heading || }
iconType={statusToEuiIconType(message.status)}
- />
+ >
+ {message.heading && }
+
);
@@ -212,7 +219,6 @@ class ValidateJob extends Component {
const isCurrentJobConfig = (this.props.isCurrentJobConfig !== true) ? false : true;
const isDisabled = (this.props.isDisabled !== true) ? false : true;
-
return (
)}
+
+ Job validation performs certain checks against job configurations and underlying source data
+ and provides specific advice on how to adjust settings that are more likely to produce insightful results.
+
+
+ For more information, see Machine Learning Job Tips.
+
}
diff --git a/x-pack/plugins/ml/server/models/job_validation/job_validation.js b/x-pack/plugins/ml/server/models/job_validation/job_validation.js
index c148ffb81ffae..524370b65c711 100644
--- a/x-pack/plugins/ml/server/models/job_validation/job_validation.js
+++ b/x-pack/plugins/ml/server/models/job_validation/job_validation.js
@@ -104,6 +104,9 @@ export async function validateJob(callWithRequest, payload, kbnVersion = 'curren
return uniqWithIsEqual(validationMessages).map(message => {
if (typeof messages[message.id] !== 'undefined') {
// render the message template with the provided metadata
+ if (typeof messages[message.id].heading !== 'undefined') {
+ message.heading = renderTemplate(messages[message.id].heading, message);
+ }
message.text = renderTemplate(messages[message.id].text, message);
// check if the error message provides a link with further information
// if so, add it to the message to be returned with it
diff --git a/x-pack/plugins/ml/server/models/job_validation/messages.json b/x-pack/plugins/ml/server/models/job_validation/messages.json
index 7f3fec66ffcc0..dfb33592c84ba 100644
--- a/x-pack/plugins/ml/server/models/job_validation/messages.json
+++ b/x-pack/plugins/ml/server/models/job_validation/messages.json
@@ -35,7 +35,8 @@
},
"categorization_filters_valid": {
"status": "SUCCESS",
- "text": "Categorization filters"
+ "text": "Categorization filters checks passed.",
+ "url": "https://www.elastic.co/guide/en/x-pack/{{version}}/ml-configuring-categories.html#ml-configuring-categories"
},
"categorization_filters_invalid": {
"status": "ERROR",
@@ -43,41 +44,53 @@
},
"bucket_span_empty": {
"status": "ERROR",
- "text": "The bucket span field must be specified."
+ "text": "The bucket span field must be specified.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-analysisconfig"
},
"bucket_span_estimation_mismatch": {
"status": "INFO",
+ "heading": "Bucket span",
"text": "Current bucket span is \"{{currentBucketSpan}}\", but bucket span estimation returned \"{{estimateBucketSpan}}\".",
"url": "https://www.elastic.co/guide/en/kibana/{{version}}/job-tips.html#bucket-span"
},
"bucket_span_high": {
"status": "INFO",
+ "heading": "Bucket span",
"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/kibana/{{version}}/job-tips.html#bucket-span"
},
"bucket_span_valid": {
"status": "SUCCESS",
- "text": "Bucket span format"
+ "heading": "Bucket span",
+ "text": "Format of \"{{bucketSpan}}\" is valid.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-analysisconfig"
},
"bucket_span_invalid": {
"status": "ERROR",
- "text": "The specified bucket span is not a valid time interval format e.g. 10m, 1h. It also needs to be higher than zero."
+ "heading": "Bucket span",
+ "text": "The specified bucket span is not a valid time interval format e.g. 10m, 1h. It also needs to be higher than zero.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-analysisconfig"
},
"detectors_duplicates": {
"status": "ERROR",
- "text": "Duplicate detectors were found. Detectors having the same combined configuration for 'function', 'field_name', 'by_field_name', 'over_field_name' and 'partition_field_name' are not allowed within the same job."
+ "text": "Duplicate detectors were found. Detectors having the same combined configuration for 'function', 'field_name', 'by_field_name', 'over_field_name' and 'partition_field_name' are not allowed within the same job.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-detectorconfig"
},
"detectors_empty": {
"status": "ERROR",
- "text": "No detectors were found. At least one detector must be specified."
+ "text": "No detectors were found. At least one detector must be specified.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-detectorconfig"
},
"detectors_function_empty": {
"status": "ERROR",
- "text": "One of the detector functions is empty."
+ "text": "One of the detector functions is empty.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-detectorconfig"
},
"detectors_function_not_empty": {
"status": "SUCCESS",
- "text": "Detector functions format"
+ "heading": "Dectector functions",
+ "text": "Presence of detector functions validated in all detectors.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-detectorconfig"
},
"index_fields_invalid": {
"status": "ERROR",
@@ -85,7 +98,7 @@
},
"index_fields_valid": {
"status": "SUCCESS",
- "text": "Index fields"
+ "text": "Index fields are present in the datafeed."
},
"influencer_high": {
"status": "WARNING",
@@ -109,39 +122,51 @@
},
"job_id_empty": {
"status": "ERROR",
- "text": "The job name field must not be empty."
+ "text": "The job name field must not be empty.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-job-resource"
},
"job_id_invalid": {
"status": "ERROR",
- "text": "The job name 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."
+ "text": "The job name 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/{{version}}/ml-job-resource.html#ml-job-resource"
},
"job_id_valid": {
"status": "SUCCESS",
- "text": "Job id"
+ "heading": "Job id format is valid.",
+ "text": "Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-job-resource"
},
"job_group_id_invalid": {
"status": "ERROR",
- "text": "One of the job group names is invalid. They can contain lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores and must start and end with an alphanumeric character."
+ "text": "One of the job group names is invalid. They 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/{{version}}/ml-job-resource.html#ml-job-resource"
},
"job_group_id_valid": {
"status": "SUCCESS",
- "text": "Job group ids"
+ "heading": "Job group id formats are valid.",
+ "text": "Lowercase alphanumeric (a-z and 0-9) characters, hyphens or underscores, starts and ends with an alphanumeric character.",
+ "url": "https://www.elastic.co/guide/en/elasticsearch/reference/{{version}}/ml-job-resource.html#ml-job-resource"
},
"skipped_extended_tests": {
"status": "WARNING",
- "text": "Skipped some checks because the basic requirements of the job configuration were not met."
+ "text": "Skipped additional checks because the basic requirements of the job configuration were not met."
},
"success_cardinality": {
"status": "SUCCESS",
- "text": "Cardinality"
+ "heading": "Cardinality",
+ "text": "Cardinality of detector fields is within recommended bounds.",
+ "url": "https://www.elastic.co/guide/en/kibana/{{version}}/job-tips.html#cardinality"
},
"success_bucket_span": {
"status": "SUCCESS",
- "text": "Bucket span"
+ "heading": "Bucket span",
+ "text": "Format of \"{{bucketSpan}}\" is valid and passed validation checks.",
+ "url": "https://www.elastic.co/guide/en/kibana/{{version}}/job-tips.html#bucket-span"
},
"success_influencers": {
"status": "SUCCESS",
- "text": "Influencers"
+ "text": "Influencer configuration passed the validation checks.",
+ "url": "https://www.elastic.co/guide/en/kibana/{{version}}/job-tips.html#influencers"
},
"estimated_mml_greater_than_max_mml": {
"status": "WARNING",
@@ -161,11 +186,14 @@
},
"success_mml": {
"status": "SUCCESS",
- "text": "Model memory limit"
+ "heading": "Model memory limit",
+ "text": "Valid and within the estimated model memory limit.",
+ "url": "https://www.elastic.co/guide/en/x-pack/{{version}}/ml-gs-job1-manage.html#ml-gs-job1-manage"
},
"success_time_range": {
"status": "SUCCESS",
- "text": "Time range"
+ "heading": "Time range",
+ "text": "Valid and long enough to model patterns in the data."
},
"time_field_invalid": {
"status": "ERROR",
@@ -173,10 +201,12 @@
},
"time_range_short": {
"status": "WARNING",
+ "heading": "Time range",
"text": "The selected or available time range might be too short. The recommended minimum time range should be at least {{minTimeSpanReadable}} and {{bucketSpanCompareFactor}} times the bucket span."
},
"time_range_before_epoch": {
"status": "WARNING",
+ "heading": "Time range",
"text": "The selected or available time range contains data with timestamps before the UNIX epoch beginning. Timestamps before 01/01/1970 00:00:00 (UTC) are not supported for machine learning jobs."
}
}
diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js b/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js
index 8e74005d43fd4..fe7fdf991233a 100644
--- a/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js
+++ b/x-pack/plugins/ml/server/models/job_validation/validate_bucket_span.js
@@ -72,7 +72,10 @@ export async function validateBucketSpan(callWithRequest, job, duration) {
if (SKIP_BUCKET_SPAN_ESTIMATION) {
if (messages.length === 0) {
- messages.push({ id: 'success_bucket_span' });
+ messages.push({
+ id: 'success_bucket_span',
+ bucketSpan: job.analysis_config.bucket_span
+ });
}
return messages;
}
@@ -151,7 +154,10 @@ export async function validateBucketSpan(callWithRequest, job, duration) {
}
if (messages.length === 0) {
- messages.push({ id: 'success_bucket_span' });
+ messages.push({
+ id: 'success_bucket_span',
+ bucketSpan: job.analysis_config.bucket_span
+ });
}
return messages;