in lib/errors.js [159:294]
function createAPMError(args, cb) {
let numAsyncStepsRemaining = 0; // finish() will call cb() only when this is 0.
const error = {
id: args.id,
timestamp: args.timestampUs,
};
if (args.traceContext) {
error.parent_id = args.traceContext.traceparent.id;
error.trace_id = args.traceContext.traceparent.traceId;
}
if (args.trans) {
error.transaction_id = args.trans.id;
error.transaction = {
name: args.trans.name,
type: args.trans.type,
sampled: args.trans.sampled,
};
}
if (args.errorContext) {
error.context = args.errorContext;
}
if (args.exception) {
// Handle an exception, i.e. `captureError(<an Error instance>, ...)`.
const err = args.exception;
const errMsg = String(err.message);
error.exception = {
message: errMsg,
type: args.exceptionType || String(err.name),
handled: args.handled,
};
if ('code' in err) {
error.exception.code = String(err.code);
} else {
// To provide better grouping of mysql errors that happens after the async
// boundery, we modify to exception type to include the custom mysql error
// type (e.g. ER_PARSE_ERROR)
var match = errMsg.match(MYSQL_ERROR_MSG_RE);
if (match) {
error.exception.code = match[1];
}
}
// Optional add an alternative error message as well as the exception message.
if (args.message && typeof args.message === 'string') {
error.log = { message: args.message };
}
if (args.shouldCaptureAttributes) {
const attrs = attributesFromErr(err);
if (attrs) {
error.exception.attributes = attrs;
}
}
numAsyncStepsRemaining++;
gatherStackTrace(
args.log,
args.exception,
args.sourceLinesAppFrames,
args.sourceLinesLibraryFrames,
null, // filterCallSite
function (_err, stacktrace) {
// _err from gatherStackTrace is always null.
const culprit = culpritFromStacktrace(stacktrace);
if (culprit) {
error.culprit = culprit;
}
const moduleName = _moduleNameFromFrames(stacktrace);
if (moduleName) {
// TODO: consider if we should include this as it's not originally what module was intended for
error.exception.module = moduleName;
}
error.exception.stacktrace = stacktrace;
finish();
},
);
} else {
// Handle a logMessage, i.e. `captureError(<not an Error instance>, ...)`.
error.log = {};
const msg = args.logMessage;
if (typeof msg === 'string') {
error.log.message = msg;
} else if (typeof msg === 'object' && msg !== null) {
if (msg.message) {
error.log.message = util.format.apply(
this,
[msg.message].concat(msg.params),
);
error.log.param_message = msg.message;
} else {
error.log.message = util.inspect(msg);
}
} else {
error.log.message = String(msg);
}
}
if (args.callSiteLoc) {
numAsyncStepsRemaining++;
gatherStackTrace(
args.log,
args.callSiteLoc,
args.sourceLinesAppFrames,
args.sourceLinesLibraryFrames,
null, // filterCallSite
function (_err, stacktrace) {
// _err from gatherStackTrace is always null.
if (stacktrace) {
// In case there isn't any log object, we'll make a dummy message
// as the APM Server requires a message to be present if a
// stacktrace also present
if (!error.log) {
error.log = { message: error.exception.message };
}
error.log.stacktrace = stacktrace;
finish();
}
},
);
} else {
numAsyncStepsRemaining++;
setImmediate(finish);
}
function finish() {
numAsyncStepsRemaining--;
if (numAsyncStepsRemaining === 0) {
cb(null, error);
}
}
}