diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
index b463322ea55d..3508d69ee221 100644
--- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js
@@ -48,6 +48,8 @@ export class EditJobFlyoutUI extends Component {
jobDescription: '',
jobGroups: [],
jobModelMemoryLimit: '',
+ jobModelSnapshotRetentionDays: 10,
+ jobDailyModelSnapshotRetentionAfterDays: 10,
jobDetectors: [],
jobDetectorDescriptions: [],
jobCustomUrls: [],
@@ -96,6 +98,8 @@ export class EditJobFlyoutUI extends Component {
'jobDescription',
'jobGroups',
'jobModelMemoryLimit',
+ 'jobModelSnapshotRetentionDays',
+ 'jobDailyModelSnapshotRetentionAfterDays',
'jobCustomUrls',
'jobDetectors',
'jobDetectorDescriptions',
@@ -128,6 +132,15 @@ export class EditJobFlyoutUI extends Component {
job.analysis_limits && job.analysis_limits.model_memory_limit
? job.analysis_limits.model_memory_limit
: '';
+
+ const modelSnapshotRetentionDays =
+ job.model_snapshot_retention_days !== undefined ? job.model_snapshot_retention_days : 10;
+
+ const dailyModelSnapshotRetentionAfterDays =
+ job.daily_model_snapshot_retention_after_days !== undefined
+ ? job.daily_model_snapshot_retention_after_days
+ : modelSnapshotRetentionDays;
+
const detectors =
job.analysis_config && job.analysis_config.detectors
? [...job.analysis_config.detectors]
@@ -146,6 +159,8 @@ export class EditJobFlyoutUI extends Component {
jobDescription: job.description,
jobGroups: job.groups !== undefined ? job.groups : [],
jobModelMemoryLimit: mml,
+ jobModelSnapshotRetentionDays: modelSnapshotRetentionDays,
+ jobDailyModelSnapshotRetentionAfterDays: dailyModelSnapshotRetentionAfterDays,
jobDetectors: detectors,
jobDetectorDescriptions: detectors.map((d) => d.detector_description),
jobBucketSpan: bucketSpan,
@@ -229,6 +244,8 @@ export class EditJobFlyoutUI extends Component {
description: this.state.jobDescription,
groups: this.state.jobGroups,
mml: this.state.jobModelMemoryLimit,
+ modelSnapshotRetentionDays: this.state.jobModelSnapshotRetentionDays,
+ dailyModelSnapshotRetentionAfterDays: this.state.jobDailyModelSnapshotRetentionAfterDays,
detectorDescriptions: this.state.jobDetectorDescriptions,
datafeedQuery: collapseLiteralStrings(this.state.datafeedQuery),
datafeedQueryDelay: this.state.datafeedQueryDelay,
@@ -275,6 +292,8 @@ export class EditJobFlyoutUI extends Component {
jobDescription,
jobGroups,
jobModelMemoryLimit,
+ jobModelSnapshotRetentionDays,
+ jobDailyModelSnapshotRetentionAfterDays,
jobDetectors,
jobDetectorDescriptions,
jobBucketSpan,
@@ -302,6 +321,8 @@ export class EditJobFlyoutUI extends Component {
jobDescription={jobDescription}
jobGroups={jobGroups}
jobModelMemoryLimit={jobModelMemoryLimit}
+ jobModelSnapshotRetentionDays={jobModelSnapshotRetentionDays}
+ jobDailyModelSnapshotRetentionAfterDays={jobDailyModelSnapshotRetentionAfterDays}
setJobDetails={this.setJobDetails}
jobGroupsValidationError={jobGroupsValidationError}
jobModelMemoryLimitValidationError={jobModelMemoryLimitValidationError}
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js
index fcd2c09f7276..5030c48a4e36 100644
--- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_utils.js
@@ -16,6 +16,8 @@ export function saveJob(job, newJobData, finish) {
...extractDescription(job, newJobData),
...extractGroups(job, newJobData),
...extractMML(job, newJobData),
+ ...extractModelSnapshotRetentionDays(job, newJobData),
+ ...extractDailyModelSnapshotRetentionAfterDays(job, newJobData),
...extractDetectorDescriptions(job, newJobData),
...extractCustomSettings(job, newJobData),
};
@@ -175,6 +177,22 @@ function extractMML(job, newJobData) {
return mmlData;
}
+function extractModelSnapshotRetentionDays(job, newJobData) {
+ const modelSnapshotRetentionDays = newJobData.modelSnapshotRetentionDays;
+ if (modelSnapshotRetentionDays !== job.model_snapshot_retention_days) {
+ return { model_snapshot_retention_days: modelSnapshotRetentionDays };
+ }
+ return {};
+}
+
+function extractDailyModelSnapshotRetentionAfterDays(job, newJobData) {
+ const dailyModelSnapshotRetentionAfterDays = newJobData.dailyModelSnapshotRetentionAfterDays;
+ if (dailyModelSnapshotRetentionAfterDays !== job.daily_model_snapshot_retention_after_days) {
+ return { daily_model_snapshot_retention_after_days: dailyModelSnapshotRetentionAfterDays };
+ }
+ return {};
+}
+
function extractDetectorDescriptions(job, newJobData) {
const detectors = [];
const descriptions = newJobData.detectorDescriptions.map((d, i) => ({
diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/job_details.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/job_details.js
index 974afafc08b6..ec5ef6fce26b 100644
--- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/job_details.js
+++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/job_details.js
@@ -7,7 +7,14 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
-import { EuiFieldText, EuiForm, EuiFormRow, EuiSpacer, EuiComboBox } from '@elastic/eui';
+import {
+ EuiFieldText,
+ EuiForm,
+ EuiFormRow,
+ EuiSpacer,
+ EuiComboBox,
+ EuiFieldNumber,
+} from '@elastic/eui';
import { ml } from '../../../../../services/ml_api_service';
import { i18n } from '@kbn/i18n';
@@ -24,6 +31,8 @@ export class JobDetails extends Component {
mml: '',
mmlValidationError: '',
groupsValidationError: '',
+ modelSnapshotRetentionDays: 1,
+ dailyModelSnapshotRetentionAfterDays: 1,
};
this.setJobDetails = props.setJobDetails;
@@ -52,6 +61,8 @@ export class JobDetails extends Component {
mml: props.jobModelMemoryLimit,
mmlValidationError: props.jobModelMemoryLimitValidationError,
groupsValidationError: props.jobGroupsValidationError,
+ modelSnapshotRetentionDays: props.jobModelSnapshotRetentionDays,
+ dailyModelSnapshotRetentionAfterDays: props.jobDailyModelSnapshotRetentionAfterDays,
};
}
@@ -63,6 +74,24 @@ export class JobDetails extends Component {
this.setJobDetails({ jobModelMemoryLimit: e.target.value });
};
+ onModelSnapshotRetentionDaysChange = (e) => {
+ const jobModelSnapshotRetentionDays = Math.floor(+e.target.value);
+
+ this.setJobDetails({
+ jobModelSnapshotRetentionDays,
+ ...(this.state.dailyModelSnapshotRetentionAfterDays > jobModelSnapshotRetentionDays
+ ? { jobDailyModelSnapshotRetentionAfterDays: jobModelSnapshotRetentionDays }
+ : {}),
+ });
+ };
+
+ onDailyModelSnapshotRetentionAfterDaysChange = (e) => {
+ const jobDailyModelSnapshotRetentionAfterDays = Math.floor(+e.target.value);
+ if (jobDailyModelSnapshotRetentionAfterDays <= this.state.modelSnapshotRetentionDays) {
+ this.setJobDetails({ jobDailyModelSnapshotRetentionAfterDays });
+ }
+ };
+
onGroupsChange = (selectedGroups) => {
this.setJobDetails({ jobGroups: selectedGroups.map((g) => g.label) });
};
@@ -104,6 +133,8 @@ export class JobDetails extends Component {
groups,
mmlValidationError,
groupsValidationError,
+ modelSnapshotRetentionDays,
+ dailyModelSnapshotRetentionAfterDays,
} = this.state;
const { datafeedRunning } = this.props;
return (
@@ -172,6 +203,35 @@ export class JobDetails extends Component {
disabled={datafeedRunning}
/>
+
+ }
+ >
+
+
+
+ }
+ >
+
+
);
diff --git a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts
index de393e002c55..3a01a616a4f7 100644
--- a/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts
+++ b/x-pack/plugins/ml/server/routes/schemas/anomaly_detectors_schema.ts
@@ -69,6 +69,7 @@ export const anomalyDetectionUpdateJobSchema = schema.object({
})
),
groups: schema.maybe(schema.arrayOf(schema.maybe(schema.string()))),
+ model_snapshot_retention_days: schema.maybe(schema.number()),
});
export const analysisConfigSchema = schema.object({