From f21b8d0e7fbcebbac06a2fcbd026b97388d71c1c Mon Sep 17 00:00:00 2001 From: Maciej Barelkowski Date: Thu, 26 Sep 2019 11:14:38 +0200 Subject: [PATCH] feat(deploy): display readable error message in log Closes #1426 --- .../src/plugins/deployment-tool/CamundaAPI.js | 73 ++----------------- .../deployment-tool/DeploymentDetailsModal.js | 2 +- .../plugins/deployment-tool/DeploymentTool.js | 2 + .../ConnectionError.js} | 35 +++++++++ .../deployment-tool/errors/DeploymentError.js | 70 ++++++++++++++++++ .../plugins/deployment-tool/errors/index.js | 18 +++++ 6 files changed, 134 insertions(+), 66 deletions(-) rename client/src/plugins/deployment-tool/{ErrorMessages.js => errors/ConnectionError.js} (55%) create mode 100644 client/src/plugins/deployment-tool/errors/DeploymentError.js create mode 100644 client/src/plugins/deployment-tool/errors/index.js diff --git a/client/src/plugins/deployment-tool/CamundaAPI.js b/client/src/plugins/deployment-tool/CamundaAPI.js index 8a8f47d23..3d838057c 100644 --- a/client/src/plugins/deployment-tool/CamundaAPI.js +++ b/client/src/plugins/deployment-tool/CamundaAPI.js @@ -8,7 +8,10 @@ * except in compliance with the MIT License. */ -import { ConnectionErrorMessages } from './ErrorMessages'; +import { + ConnectionError, + DeploymentError +} from './errors'; const FETCH_TIMEOUT = 5000; @@ -63,9 +66,9 @@ export default class CamundaAPI { }; } - const json = await this.safelyParse(response); + const body = await this.safelyParse(response); - throw responseError('Deployment failed', response, json); + throw new DeploymentError(response, body); } async checkConnection(details = {}) { @@ -79,7 +82,7 @@ export default class CamundaAPI { return; } - throw connectionError(response); + throw new ConnectionError(response); } getHeaders(auth) { @@ -118,7 +121,7 @@ export default class CamundaAPI { response = { url, json: () => { - return { message: 'Fetch failed' }; + return {}; } }; } @@ -146,63 +149,3 @@ export default class CamundaAPI { } } } - - - -// helpers ////////////// - -const parseError = 'ENGINE-09005 Could not parse BPMN process. Errors: \n*'; - -function responseError(message, response, details) { - const error = new Error(message); - - error.details = details; - error.response = response; - - // fix engine not exposing details - if (details && details.message && details.message.startsWith(parseError)) { - details.problems = details.message.substring(parseError.length).split(/\s?\n\*\s?/g); - details.message = 'ENGINE-09005 Could not parse BPMN process'; - } - - return error; -} - -function connectionError(response) { - const error = new Error(); - - const errorMessageFromStatus = getStatusCodeErrorMessage(response); - - if (errorMessageFromStatus) { - error.message = errorMessageFromStatus; - - return error; - } - - error.message = getNetworkErrorMessage(response); - - return error; -} - -function getStatusCodeErrorMessage(response) { - switch (response.status) { - case 401: - return ConnectionErrorMessages.unauthorized; - case 403: - return ConnectionErrorMessages.forbidden; - case 404: - return ConnectionErrorMessages.notFound; - case 500: - return ConnectionErrorMessages.internalServerError; - case 503: - return ConnectionErrorMessages.unavailable; - } -} - -function getNetworkErrorMessage(response) { - if (!/^https?:\/\/localhost/.test(response.url) && !window.navigator.onLine) { - return ConnectionErrorMessages.noInternetConnection; - } - - return ConnectionErrorMessages.unableToConnect; -} diff --git a/client/src/plugins/deployment-tool/DeploymentDetailsModal.js b/client/src/plugins/deployment-tool/DeploymentDetailsModal.js index 67562917b..0359be40c 100644 --- a/client/src/plugins/deployment-tool/DeploymentDetailsModal.js +++ b/client/src/plugins/deployment-tool/DeploymentDetailsModal.js @@ -30,7 +30,7 @@ import { Field } from 'formik'; -import { ConnectionErrorMessages } from './ErrorMessages'; +import { ConnectionErrorMessages } from './errors'; const initialFormValues = { diff --git a/client/src/plugins/deployment-tool/DeploymentTool.js b/client/src/plugins/deployment-tool/DeploymentTool.js index 53f3a2d6d..6ec8d0f0f 100644 --- a/client/src/plugins/deployment-tool/DeploymentTool.js +++ b/client/src/plugins/deployment-tool/DeploymentTool.js @@ -100,6 +100,7 @@ export default class DeploymentTool extends PureComponent { // (3) Trigger deployment // (3.1) Show deployment result (success or error) const { + log, displayNotification } = this.props; @@ -118,6 +119,7 @@ export default class DeploymentTool extends PureComponent { content: 'See the log for further details.', duration: 10000 }); + log({ category: 'deploy-error', message: error.problems || error.message }); } } diff --git a/client/src/plugins/deployment-tool/ErrorMessages.js b/client/src/plugins/deployment-tool/errors/ConnectionError.js similarity index 55% rename from client/src/plugins/deployment-tool/ErrorMessages.js rename to client/src/plugins/deployment-tool/errors/ConnectionError.js index 7a385a943..623e581d4 100644 --- a/client/src/plugins/deployment-tool/ErrorMessages.js +++ b/client/src/plugins/deployment-tool/errors/ConnectionError.js @@ -17,3 +17,38 @@ export const ConnectionErrorMessages = { internalServerError: 'Camunda is reporting an error. Please check the server status.', unreachable: 'Camunda is reporting an error. Please check the server status.' }; + + +export default class ConnectionError extends Error { + constructor(response) { + super(); + + this.message = ( + this.getStatusCodeErrorMessage(response) || + this.getNetworkErrorMessage(response) + ); + } + + getStatusCodeErrorMessage(response) { + switch (response.status) { + case 401: + return ConnectionErrorMessages.unauthorized; + case 403: + return ConnectionErrorMessages.forbidden; + case 404: + return ConnectionErrorMessages.notFound; + case 500: + return ConnectionErrorMessages.internalServerError; + case 503: + return ConnectionErrorMessages.unavailable; + } + } + + getNetworkErrorMessage(response) { + if (!/^https?:\/\/localhost/.test(response.url) && !window.navigator.onLine) { + return ConnectionErrorMessages.noInternetConnection; + } + + return ConnectionErrorMessages.unableToConnect; + } +} diff --git a/client/src/plugins/deployment-tool/errors/DeploymentError.js b/client/src/plugins/deployment-tool/errors/DeploymentError.js new file mode 100644 index 000000000..a4d22ed9c --- /dev/null +++ b/client/src/plugins/deployment-tool/errors/DeploymentError.js @@ -0,0 +1,70 @@ +/** + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. + * + * Camunda licenses this file to you under the MIT; you may not use this file + * except in compliance with the MIT License. + */ + +const DeploymentErrorMessages = { + noInternetConnection: 'Could not establish a network connection. Most likely your machine is not online right now.', + unableToConnect: 'Could not connect to the server. Did you run the engine?', + bpmnParsingError: 'Server could not parse the diagram. Please check log for errors.', + unauthorized: 'The deployment was unauthorized. Please use valid credentials.', + forbidden: 'The deployment was not permitted for your credentials. Please check your credentials.', + notFound: 'Could not connect to Camunda. Please check the endpoint URL.', + internalServerError: 'Camunda reported an unknown error. Please check the server status.', + serverUnavailable: 'Camunda is currently unavailable. Please try again later.' +}; + +const PARSE_ERROR = 'ENGINE-09005 Could not parse BPMN process. Errors:'; + + +export default class DeploymentError extends Error { + constructor(response, body) { + super(); + + this.message = ( + this.getCamundaBpmErrorMessage(body) || + this.getStatusCodeErrorMessage(response) || + this.getNetworkErrorMessage(response) + ); + + this.problems = this.getProblems(body); + } + + getCamundaBpmErrorMessage(body) { + if (body && body.message && body.message.startsWith(PARSE_ERROR)) { + return DeploymentErrorMessages.bpmnParsingError; + } + } + + getStatusCodeErrorMessage(response) { + switch (response.status) { + case 401: + return DeploymentErrorMessages.unauthorized; + case 403: + return DeploymentErrorMessages.forbidden; + case 404: + return DeploymentErrorMessages.notFound; + case 500: + return DeploymentErrorMessages.internalServerError; + case 503: + return DeploymentErrorMessages.serverUnavailable; + } + } + + getNetworkErrorMessage(response) { + if (!/^https?:\/\/localhost/.test(response.url) && !window.navigator.onLine) { + return DeploymentErrorMessages.noInternetConnection; + } + + return DeploymentErrorMessages.unableToConnect; + } + + getProblems(body) { + return body.message; + } +} diff --git a/client/src/plugins/deployment-tool/errors/index.js b/client/src/plugins/deployment-tool/errors/index.js new file mode 100644 index 000000000..d1ba7d0a0 --- /dev/null +++ b/client/src/plugins/deployment-tool/errors/index.js @@ -0,0 +1,18 @@ +/** + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. + * + * Camunda licenses this file to you under the MIT; you may not use this file + * except in compliance with the MIT License. + */ + +import ConnectionError, { ConnectionErrorMessages } from './ConnectionError'; +import DeploymentError from './DeploymentError'; + +export { + ConnectionError, + ConnectionErrorMessages, + DeploymentError +};