You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
4.1 KiB

import unserialize from './unserialize';
import style from "./Components/TraceLine.css";
import {formatArgument} from "./Components/TraceLine";
window.unserialize = unserialize;
export class ExceptionParser {
isException (logMessage) {
return this.isNewStyleException(logMessage) || this.isOldStyleException(logMessage) || this.isBackgroundJobException(logMessage);
}
isNewStyleException (logMessage) {
return logMessage.Exception;
}
isOldStyleException (logMessage) {
return logMessage.substr && logMessage.substr(0, 12) === 'Exception: {';
}
isBackgroundJobException (logMessage) {
return logMessage.substr && logMessage.substr(0, 34) === 'Error while running background job' && logMessage.indexOf('{"Exception":') !== -1;
}
parse (logMessage) {
if (this.isNewStyleException(logMessage)) {
return logMessage;
}
let data;
if (this.isOldStyleException(logMessage)) {
try {
data = this.tryParseJSON(logMessage.substr(10));
} catch (e) {
console.log('Error while parsing exception:');
console.log(logMessage.substr(10));
console.error(e);
}
} else {
data = this.tryParseJSON(logMessage.substr(logMessage.indexOf('{"Exception":')));
const messageHead = logMessage.substr(0, logMessage.indexOf('{"Exception":'));
const jobDataString = messageHead.split('(', 2)[1];
const jobDataParts = jobDataString.split(',', 2).map(part => part.trim());
data.jobClass = jobDataParts[0].split(':', 2)[1].trim();
data.jobArguments = jobDataParts[1].substr(10).trim();
window.s = jobDataParts[1].substr(10).trim();
if (data.jobClass === 'OC\\Command\\CommandJob') {
try {
[data.jobClass, data.jobArguments] = this.parseCommandJob(data.jobArguments);
} catch (e) {
}
}
}
let traceLines = data.Trace.split('\n');
data.Trace = traceLines.map(this.parseTraceLine);
return data;
}
tryParseJSON (json) {
try {
return JSON.parse(json);
} catch (e) {
// fix unescaped newlines
json = json.replace(/\n/g, '\\n');
// fix unescaped namespace delimiters
json = json.replace(/([^\\])\\([A-Z{])/g, '$1\\\\$2');
try {
return JSON.parse(json);
} catch (e) {
console.log('Error while parsing exception:');
console.log(json);
console.error(e);
}
}
}
parseCommandJob (data) {
const parsed = unserialize(data);
return [parsed['class'], parsed.properties];
}
parseTraceLine (line) {
let parts = line.split(' ');
let number = parts.shift();
let traceData = parts.join(' ');
parts = traceData.split(':');
if (parts.length > 1) {
let file, lineNumber;
let fileAndLine = parts.shift();
let call = parts.join(' ');
if (fileAndLine[0] === '[') {
lineNumber = false;
file = fileAndLine;
} else {
let filePaths = fileAndLine.split('(', 2);
file = filePaths[0];
lineNumber = filePaths[1].substr(0, filePaths[1].length - 1);
}
return {
'function': call,
number: number,
file: file,
line: lineNumber
};
} else {
return {
'function': traceData,
number: number,
file: false,
line: false
};
}
}
format (logMessage) {
if (!this.isException(logMessage)) {
return logMessage;
}
const parsed = this.parse(logMessage);
const fileAndLine = (item) => {
if (item.file && item.line) {
return `${item.file} line ${item.line}`
} else {
return '<<closure>>';
}
};
if (parsed.Exception) {
const widestIndex = ('' + (parsed.Trace.length - 1)).length;
let message = `${parsed.Exception}: ${parsed.Message} at ${fileAndLine(parsed)}\n\n`;
message += parsed.Trace.map(
(trace, i) => {
const args = trace.args.map(arg => {
const baseFormatted = formatArgument(arg, 0).replace(/\n/g, '');;
const showInline = baseFormatted.length < 42;
return showInline ? baseFormatted : `${baseFormatted.substr(0, 16)} ... ${baseFormatted.substr(baseFormatted.length - 2, 2)}`;
});
return `${' '.repeat(widestIndex - ('' + i).length)}${i}. ${fileAndLine(trace)}\n` +
`${' '.repeat(widestIndex + 2)}${trace.class}${trace.type}${trace.function}(${args.join(', ')})`;
}
).join('\n');
return message;
} else {
return parsed;
}
}
}