Current File : //lib/node_modules/pm2/node_modules/@pm2/io/build/main/src/features/notifyInspector.js |
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const async_1 = require("async");
const json_1 = require("../utils/json");
const serviceManager_1 = require("../serviceManager");
class NotifyInspector {
constructor() {
this.inspectorService = serviceManager_1.ServiceManager.get('inspector');
this.exceptionsTrapped = [];
}
init() {
this.inspectorService.createSession();
this.inspectorService.connect();
this.catchAllDebugger();
}
destroy() {
this.inspectorService.disconnect();
}
trapException(listener) {
return (error) => {
// log it
if (listener === 'unhandledRejection') {
console.log('You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:');
}
console.error(error);
// create object to be send
const context = this.exceptionsTrapped.find((exception) => {
return !!exception.error.description.match(error.message);
});
error = json_1.default.jsonize(error);
// inject async stackframe
if (context && context.asyncStackTrace) {
const fetchFrames = (entry) => {
return entry.parent ? entry.callFrames.concat(fetchFrames(entry.parent)) : entry.callFrames;
};
const asyncStack = fetchFrames(context.asyncStackTrace)
.filter(frame => frame.url.indexOf('internal') === -1)
.map(frame => {
return ` at ${frame.functionName || '<anonymous>'} (${frame.url}:${frame.lineNumber}:${frame.columnNumber})`;
});
asyncStack.unshift('');
error.stack = error.stack.concat(asyncStack.join('\n'));
}
error.frame = context ? context.frame : undefined;
// send it
serviceManager_1.ServiceManager.get('transport').send('process:exception', error);
// at this point the process should exit
process.exit(1);
};
}
isObjectInteresting(entry) {
if (!entry.value)
return false;
if (!entry.value.objectId)
return false;
if (entry.value.type !== 'object')
return false;
switch (entry.value.description) {
case 'IncomingMessage': {
return true;
}
}
switch (entry.name) {
case 'headers': {
return true;
}
case 'user': {
return true;
}
case 'token': {
return true;
}
case 'body': {
return true;
}
case 'params': {
return true;
}
case 'query': {
return true;
}
}
return false;
}
isPropertyIntesting(entry, parent) {
if (!entry.value)
return false;
if (entry.value.type === 'object' && entry.properties)
return true;
if (parent && parent.name === 'headers')
return true;
if (parent && parent.name === 'body')
return true;
if (parent && parent.name === 'params')
return true;
if (parent && parent.name === 'query')
return true;
if (entry.name === '__proto__')
return false;
switch (entry.name) {
case 'url': {
return true;
}
case 'user': {
return true;
}
case 'token': {
return true;
}
case 'method': {
return true;
}
case 'ip': {
return true;
}
case 'query': {
return true;
}
case 'path': {
return true;
}
case 'body': {
return true;
}
case 'params': {
return true;
}
}
return false;
}
formatProperty(property) {
const value = property.value && property.value.value ? property.value.value : null;
const description = property.value && property.value.description ? property.value.description : null;
return {
name: property.name,
value: value || description || property.value,
properties: property.properties
};
}
fetchObjectProperties(session, object, cb) {
session.post('Runtime.getProperties', {
objectId: object,
ownProperties: true
}, (err, data) => {
if (err)
return cb(err, undefined);
async_1.default.map(data.result, (entry, next) => {
if (entry.value && entry.value.objectId && this.isObjectInteresting(entry)) {
return this.fetchObjectProperties(session, entry.value.objectId, (err, properties) => {
if (err)
return next(err);
// if some properties has been dumped, attach them
if (properties) {
entry.properties = properties
.filter(property => {
return this.isPropertyIntesting(property, entry);
})
.map(this.formatProperty);
}
return next(undefined, this.formatProperty(entry));
});
}
else {
return next(undefined, this.formatProperty(entry));
}
}, cb);
});
}
catchAllDebugger() {
const session = this.inspectorService.createSession();
this.inspectorService.connect();
// trap exception so we can re-use them with the debugger
process.on('uncaughtException', this.trapException('uncaughtException'));
process.on('unhandledRejection', this.trapException('unhandledRejection'));
// enable all the debugger options
session.post('Debugger.enable');
const maxDepth = parseInt(process.env.PM2_APM_ASYNC_STACK_DEPTH || '', 10);
if (!isNaN(maxDepth)) {
session.post('Debugger.setAsyncCallStackDepth', { maxDepth });
}
session.post('Debugger.setPauseOnExceptions', { state: 'uncaught' });
// register handler for paused event
session.on('Debugger.paused', ({ params }) => {
// should not happen but anyway
if (params.reason !== 'exception' && params.reason !== 'promiseRejection') {
return session.post('Debugger.resume');
}
if (!params.data)
return session.post('Debugger.resume');
const error = params.data;
// get only the current frame
const frame = params.callFrames[0];
// on each frame, dump all scopes
async_1.default.map(frame.scopeChain, (scope, nextScope) => {
if (scope.type === 'global')
return nextScope();
if (!scope.object.objectId)
return nextScope();
// get context of the scope
return this.fetchObjectProperties(session, scope.object.objectId, (error, context) => {
return nextScope(error, Object.assign(scope, {
context,
object: undefined
}));
});
}, (err, scopes) => {
if (err) {
console.error(err);
return session.post('Debugger.resume');
}
// we can remove some scope so we want to remove null entry
scopes = scopes.filter(scope => !!scope);
// inspect each scope to retrieve his context
this.exceptionsTrapped.push({
error,
asyncStackTrace: params.asyncStackTrace,
frame: Object.assign(frame, {
scopeChain: scopes
})
});
// continue execution
return session.post('Debugger.resume');
});
});
}
}
exports.default = NotifyInspector;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZ5SW5zcGVjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2ZlYXR1cmVzL25vdGlmeUluc3BlY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUF5QjtBQUV6Qix3Q0FBcUM7QUFDckMsc0RBQWtEO0FBd0NsRDtJQUtFO1FBQ0UsSUFBSSxDQUFDLGdCQUFnQixHQUFHLCtCQUFjLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQ3ZELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxFQUFFLENBQUE7SUFDN0IsQ0FBQztJQUVELElBQUk7UUFDRixJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDckMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQy9CLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO0lBQ3pCLENBQUM7SUFFRCxPQUFPO1FBQ0wsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQ3BDLENBQUM7SUFFRCxhQUFhLENBQUUsUUFBZ0I7UUFDN0IsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2YsU0FBUztZQUNULElBQUksUUFBUSxLQUFLLG9CQUFvQixFQUFFO2dCQUNyQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdHQUFnRyxDQUFDLENBQUE7YUFDOUc7WUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3BCLDJCQUEyQjtZQUMzQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBMkIsRUFBRSxFQUFFO2dCQUMxRSxPQUFPLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQzNELENBQUMsQ0FBQyxDQUFBO1lBQ0YsS0FBSyxHQUFHLGNB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