Skip to content

Commit

Permalink
GG-20249 Extract message from exception cause stack trace. (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
vsisko committed Jun 27, 2019
1 parent 525034b commit 90907b5
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,19 @@ class Paragraph {
};

this.setError = (err) => {
const parsedErr = errorParser.parse(err);

this.error.root = err;
this.error.message = errorParser.extractMessage(err);
this.error.message = parsedErr.message;

let cause = err;

while (nonNil(cause)) {
if (nonEmpty(cause.className) &&
_.includes(['SQLException', 'JdbcSQLException', 'QueryCancelledException'], JavaTypes.shortClassName(cause.className))) {
this.error.message = errorParser.extractMessage(cause.message || cause.className);
const parsedCause = errorParser.parse(cause.message || cause.className);

this.error.message = parsedCause.message;

break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
import isEmpty from 'lodash/isEmpty';
import {nonEmpty} from 'app/utils/lodashMixins';

const CAUSE_STR = 'Caused by: ';
const ERR_START_STR = ' err=';

export default class {
static $inject = ['JavaTypes'];

Expand All @@ -27,7 +30,7 @@ export default class {
this.JavaTypes = JavaTypes;
}

extractMessage(err, prefix) {
parse(err, prefix) {
prefix = prefix || '';

if (err) {
Expand All @@ -42,7 +45,7 @@ export default class {
if (traceIndex > 0)
msg = msg.substring(0, traceIndex);

const lastIdx = msg.lastIndexOf(' err=');
const lastIdx = msg.lastIndexOf(ERR_START_STR);
let msgEndIdx = msg.indexOf(']', lastIdx);

if (lastIdx > 0 && msgEndIdx > 0) {
Expand All @@ -58,20 +61,41 @@ export default class {
}
}

return prefix + (lastIdx >= 0 ? msg.substring(lastIdx + 5, msgEndIdx > 0 ? msgEndIdx : traceIndex) : msg);
const causes = [];

let causeIdx = err.message.indexOf(CAUSE_STR);

while (causeIdx >= 0) {
// Find next ": " in cause message to skip exception class name.
const msgStart = err.message.indexOf(': ', causeIdx + CAUSE_STR.length) + 2;
const causeEndLine = err.message.indexOf('\n', msgStart);
const msgEnd = err.message.indexOf('[', msgStart);
const cause = err.message.substring(msgStart, msgEnd >= 0 && msgEnd < causeEndLine ? msgEnd : causeEndLine);

causes.unshift(cause);

causeIdx = err.message.indexOf(CAUSE_STR, causeIdx + CAUSE_STR.length);
}

return new ErrorParseResult(
prefix + (lastIdx >= 0
? msg.substring(lastIdx + ERR_START_STR.length, msgEndIdx > 0 ? msgEndIdx : traceIndex)
: msg),
causes
);
}

if (nonEmpty(err.className)) {
if (isEmpty(prefix))
prefix = 'Internal cluster error: ';

return prefix + err.className;
return new ErrorParseResult(prefix + err.className);
}

return prefix + err;
return new ErrorParseResult(prefix + err);
}

return prefix + 'Internal error.';
return new ErrorParseResult(prefix + 'Internal error.');
}

extractFullMessage(err) {
Expand All @@ -86,3 +110,23 @@ export default class {
return clsName + (msg);
}
}

/**
* Information with error parsing result.
*/
export class ErrorParseResult {
/** String with parsed error message. */
message: String;

/** List of error causes in reverse order. */
causes: String[];

/**
* @param {String} message String with parsed error message.
* @param {Array.<String>} causes List of error causes in reverse order.
*/
constructor(message: String, causes = []) {
this.message = message;
this.causes = causes;
}
}
11 changes: 4 additions & 7 deletions modules/web-console/frontend/app/services/Messages.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ export default function factory($alert, errorParser) {
// Common instance of alert modal.
let msgModal;

const errorMessage = (prefix, err) => {
return errorParser.extractMessage(err, prefix);
};

const hideAlert = () => {
if (msgModal) {
msgModal.hide();
Expand All @@ -40,15 +36,16 @@ export default function factory($alert, errorParser) {
const _showMessage = (message, err, type, duration) => {
hideAlert();

const title = err ? errorMessage(message, err) : errorMessage(null, message);
const parsedErr = err ? errorParser.parse(err, message) : errorParser.parse(message, null);
const causes = parsedErr.causes;
const title = parsedErr.message + (causes.length ? '<ul><li>' + causes.join('</li><li>') + '</li></ul>See node logs for more details.' : '');

msgModal = $alert({type, title, duration});
msgModal = $alert({type, title, duration: duration + causes.length * 5});

msgModal.$scope.icon = `icon-${type}`;
};

return {
errorMessage,
hideAlert,
/**
* @param {string|CancellationError} message
Expand Down

0 comments on commit 90907b5

Please sign in to comment.