-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[APM] Add anomaly detection API tests + fixes #73120
[APM] Add anomaly detection API tests + fixes #73120
Conversation
sorenlouv
commented
Jul 23, 2020
•
edited by ogupte
Loading
edited by ogupte
- Add anomaly detection API tests (read/write/no access users)
- Remove error codes (not needed, since we can just set correct error messages)
- use Boom errors where appropriate
- only fetches anomaly detection jobs when available to user (Anomaly detection link)
- requires correct ML read/write privileges to access get/create routes
Pinging @elastic/apm-ui (Team:apm) |
indices: [ | ||
{ names: ['observability-annotations'], privileges: ['read', 'view_index_metadata'] }, | ||
], | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These privileges are now part of the apm_user
role.
text: MLErrorMessages[res.errorCode], | ||
}); | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got rid of the errorCode
in the response. Now the server side will throw the error and the client should simply read the error message (error.message
).
x-pack/plugins/apm/public/components/shared/Links/apm/AnomalyDetectionSetupLink.tsx
Show resolved
Hide resolved
de82143
to
a32d817
Compare
</EuiButtonEmpty> | ||
|
||
{canGetJobs && hasValidLicense ? ( | ||
<MissingJobsAlert environment={environment} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should only show ML warnings if the user can act on them. Which means: the user should have read privileges to ML and a valid license
@@ -29,16 +29,12 @@ export async function createAnomalyDetectionJobs( | |||
const { ml, indices } = setup; | |||
|
|||
if (!ml) { | |||
throw new AnomalyDetectionError(ErrorCode.ML_NOT_AVAILABLE); | |||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use Boom errors over the custom AnomalyDetectionError
(which I removed everywhere)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if a 503 is appropriate here. 503 implies that it is a temporary error, and should be retried. Maybe a 500 makes more sense?
@@ -12,7 +15,12 @@ export async function hasLegacyJobs(setup: Setup) { | |||
const { ml } = setup; | |||
|
|||
if (!ml) { | |||
return false; | |||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing early instead of returning a default value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other comment, we could consider a 500 instead of a 503.
|
||
// get ML anomaly detection jobs for each environment | ||
export const anomalyDetectionJobsRoute = createRoute(() => ({ | ||
method: 'GET', | ||
path: '/api/apm/settings/anomaly-detection', | ||
options: { | ||
tags: ['access:apm', 'access:ml:canGetJobs'], | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Require ML read privileges to access route
@@ -65,7 +52,7 @@ export const createAnomalyDetectionJobsRoute = createRoute(() => ({ | |||
method: 'POST', | |||
path: '/api/apm/settings/anomaly-detection/jobs', | |||
options: { | |||
tags: ['access:apm', 'access:apm_write'], | |||
tags: ['access:apm', 'access:apm_write', 'access:ml:canCreateJob'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require ML write privileges to access route
d16f3e8
to
d7735c4
Compare
}); | ||
|
||
expect(toolTipAnchor).not.toBeInTheDocument(); | ||
expect(toolTipText).toBe(undefined); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the tests became very clean and easy to read. It did come at the cost of making renderTooltipAnchor
slightly more complex. All in all I think it's worth it. LMK what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good compromise. It's unfortunate that we can't encapsulate all this logic into the original showAlert
function, since that was simple to use & test. But then we'd be making extra API calls that might not be necessary, so this works well.
d7735c4
to
ba7fac4
Compare
ba7fac4
to
744373f
Compare
it('should return true when there are no jobs', () => { | ||
const result = showAlert(dataWithoutJobs, undefined); | ||
expect(result).toBe(true); | ||
it('when no jobs exists for the selected environment - it should show warning', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use describe('when no jobs exists for the selected environment', () => { it('shows a warning', () => >..
@sqren I've got some feedback pending, give me a couple hours tomorrow before merging |
await createJobs(['production', 'staging']); | ||
|
||
const { body } = await getJobs(); | ||
expect(body.hasLegacyJobs).to.be(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since we don't have any legacy jobs in the test data, we can't test that part of the response here. But i think it's ok to do this in a unit test since it's only testing for a particular pattern in the a job id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll submit the feedback that I have for now - I'm waiting on ML to work on the obs test clusters to complete my review.
@@ -29,16 +29,12 @@ export async function createAnomalyDetectionJobs( | |||
const { ml, indices } = setup; | |||
|
|||
if (!ml) { | |||
throw new AnomalyDetectionError(ErrorCode.ML_NOT_AVAILABLE); | |||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if a 503 is appropriate here. 503 implies that it is a temporary error, and should be retried. Maybe a 500 makes more sense?
if (!ml) { | ||
return []; | ||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other comment, we could consider a 500 instead of a 503.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 501 is probably better than 500 or 503. From the RFC:
10.5.1 500 Internal Server Error
The server encountered an unexpected condition which prevented it from fulfilling the request.10.5.2 501 Not Implemented
The server does not support the functionality required to fulfill the request. This is the appropriate response when the server does not recognize the request method and is not capable of supporting it for any resource.
@@ -12,7 +15,12 @@ export async function hasLegacyJobs(setup: Setup) { | |||
const { ml } = setup; | |||
|
|||
if (!ml) { | |||
return false; | |||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See other comment, we could consider a 500 instead of a 503.
x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts
Show resolved
Hide resolved
@@ -31,29 +35,14 @@ export async function getServiceAnomalies({ | |||
const { ml, start, end } = setup; | |||
|
|||
if (!ml) { | |||
logger.warn('Anomaly detection plugin is not available.'); | |||
return DEFAULT_ANOMALIES; | |||
throw Boom.serverUnavailable(ML_ERRORS.ML_NOT_AVAILABLE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we perhaps handle this in the route, and use a helper function that will either throw these errors or refine { ml?: ... }
to { ml: ... }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea but I'm going to leave these as-is to avoid too many changes this late. If you really think they're needed mark this PR with changes requested and I can get them in.
x-pack/test/apm_api_integration/basic/tests/settings/anomaly_detection/write_user.ts
Show resolved
Hide resolved
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think that this test might be enough? i.e., if this fails I think it's safe to assume that other users (read, no access) won't have access either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right but I think I'll just leave these for now and err on the side of having too many tests.
return { | ||
errorCode: mlErrorCode, | ||
}; | ||
throw e; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need the log before this line if the route handler will throw anyway?
context.logger.warn( | ||
`Error while retrieving ML jobs: "${e.name}:${e.message}"` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we log if the route throws?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what you're saying here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the comment below I think you mean let's remove the try/catch and logging since we'll get the error anyway if it fails.
x-pack/plugins/apm/public/components/shared/Links/apm/AnomalyDetectionSetupLink.tsx
Outdated
Show resolved
Hide resolved
x-pack/plugins/apm/public/components/shared/Links/apm/AnomalyDetectionSetupLink.tsx
Show resolved
Hide resolved
💚 Build SucceededBuild metricsasync chunks size
History
To update your PR or re-run it, just comment with: |
Co-authored-by: Nathan L Smith <[email protected]>
💔 Backport was not successfulThe PR was attempted backported to the following branches:
|
Co-authored-by: Nathan L Smith <[email protected]> # Conflicts: # x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/jobs_list.tsx
Co-authored-by: Nathan L Smith <[email protected]> Co-authored-by: Søren Louv-Jansen <[email protected]>