diff --git a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/settings/anomaly_detection.cy.ts b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/settings/anomaly_detection.cy.ts index 5bbb7717ff94b..6712f869aef57 100644 --- a/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/settings/anomaly_detection.cy.ts +++ b/x-pack/solutions/observability/plugins/apm/ftr_e2e/cypress/e2e/settings/anomaly_detection.cy.ts @@ -75,6 +75,10 @@ const getAbleToModifyCase = () => { }); it('should show error if api call crashes when modifying settings', () => { + cy.intercept('POST', '/internal/apm/settings/anomaly-detection/jobs', { + statusCode: 500, + }); + const { rangeFrom, rangeTo } = timeRange; const TEST_ENV = 'Synthtrace: case scenario TEST-with-a-really-long-name ' + new Date().toISOString(); diff --git a/x-pack/solutions/observability/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts b/x-pack/solutions/observability/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts index 72277a6ed957a..393cfa42ccd88 100644 --- a/x-pack/solutions/observability/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts +++ b/x-pack/solutions/observability/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts @@ -23,6 +23,7 @@ import { APM_ML_JOB_GROUP, ML_MODULE_ID_APM_TRANSACTION } from './constants'; import { getAnomalyDetectionJobs } from './get_anomaly_detection_jobs'; const DEFAULT_TIMEOUT = '60s'; +const ENV_MAX_LENGTH = 40; export async function createAnomalyDetectionJobs({ mlClient, @@ -107,10 +108,11 @@ async function createAnomalyDetectionJob({ }) { return withApmSpan('create_anomaly_detection_job', async () => { const randomToken = uuidv4().substr(-4); + const sanitizedEnvironment = snakeCase(environment).slice(0, ENV_MAX_LENGTH); // limit env name due to ML job ID length constraints (up to 64 chars in total) const anomalyDetectionJob = mlClient.modules.setup({ moduleId: ML_MODULE_ID_APM_TRANSACTION, - prefix: `${APM_ML_JOB_GROUP}-${snakeCase(environment)}-${randomToken}-`, + prefix: `${APM_ML_JOB_GROUP}-${sanitizedEnvironment}-${randomToken}-`, groups: [APM_ML_JOB_GROUP], indexPatternName: apmMetricIndex, applyToAllSpaces: true, diff --git a/x-pack/solutions/observability/test/apm_api_integration/tests/settings/anomaly_detection/write_user.spec.ts b/x-pack/solutions/observability/test/apm_api_integration/tests/settings/anomaly_detection/write_user.spec.ts index 40e62b1ddc969..8a5f9125dda2c 100644 --- a/x-pack/solutions/observability/test/apm_api_integration/tests/settings/anomaly_detection/write_user.spec.ts +++ b/x-pack/solutions/observability/test/apm_api_integration/tests/settings/anomaly_detection/write_user.spec.ts @@ -58,6 +58,12 @@ export default function apiTest({ getService }: FtrProviderContext) { }); describe('when calling create endpoint', () => { + beforeEach(async () => { + const res = await getJobs({ user }); + const jobIds = res.body.jobs.map((job: any) => job.jobId); + await deleteJobs(jobIds); + }); + it('creates two jobs', async () => { await createJobs(['production', 'staging'], { user }); @@ -69,19 +75,22 @@ export default function apiTest({ getService }: FtrProviderContext) { }); }); - describe('with existing ML jobs', () => { - before(async () => { - await createJobs(['production', 'staging'], { user }); - }); - it('skips duplicate job creation', async () => { - await createJobs(['production', 'test'], { user }); + it('creates job with long environment name', async () => { + const longEnvironmentName = + 'Production: This Is A Deliberately Long Environment Name To Test Limits - 1234567890'; + const { status } = await createJobs([longEnvironmentName], { user }); + expect(status).to.be(200); + }); + + it('skips duplicate job creation', async () => { + await createJobs(['production', 'staging'], { user }); + await createJobs(['production', 'test'], { user }); - const { body } = await getJobs({ user }); - expect(countBy(body.jobs, 'environment')).to.eql({ - production: 1, - staging: 1, - test: 1, - }); + const { body } = await getJobs({ user }); + expect(countBy(body.jobs, 'environment')).to.eql({ + production: 1, + staging: 1, + test: 1, }); }); });