apminsight
Version:
monitor nodejs applications
132 lines (121 loc) • 4.16 kB
JavaScript
var mod = require("module");
var coreModules = require("./core-modules");
var logger = require("./../util/logger");
var supportedModulesInfo = require("./npm-modules");
var wrapper = require("./wrapper");
var actLoad = mod._load;
var modulesCacheInfo = {};
var supportedModules = Object.keys(supportedModulesInfo);
function start() {
instrumentCoreModules();
patchModuleLoad();
checkaddAsyncHooks();
}
function instrumentCoreModules() {
var modulesInfo = coreModules.MODULES_INFO;
Object.keys(modulesInfo).forEach(function (moduleName) {
logger.info("Instrumenting module::", moduleName);
try {
var actualModule =
moduleName === "global" ? global : require(moduleName);
} catch (err) {
logger.info("module ::" + moduleName + " is not available");
return;
}
modulesInfo[moduleName].forEach(function (eachFunction) {
wrapper.checkAndWrapFunction(
actualModule,
eachFunction,
moduleName,
eachFunction.functionName
);
});
});
}
/* eslint-disable no-unused-vars */
function patchModuleLoad() {
mod._load = function (request, parent, Main) {
var actualContent = actLoad.apply(this, arguments);
if (supportedModules.indexOf(request) < 0) {
return actualContent;
}
return checkAndInstrument(request, actualContent);
};
}
/* eslint-enable no-unused-vars */
function instrumentCustomModules(moduleName, moduleInfo) {
supportedModulesInfo[moduleName] = moduleInfo;
supportedModules.push(moduleName);
}
function checkAndInstrument(request, actualContent, moduleName) {
if (modulesCacheInfo[request] && modulesCacheInfo[request].wrapped) {
return modulesCacheInfo[request].wrapped;
}
logger.info("Instrumenting module::" + request);
var functionInfo;
if (moduleName) {
var modInfo = supportedModulesInfo[moduleName];
functionInfo = modInfo[request];
} else {
moduleName = request;
functionInfo = supportedModulesInfo[moduleName];
}
functionInfo.functions.forEach(function (eachFunction) {
wrapper.checkAndWrapFunction(
actualContent,
eachFunction,
moduleName,
eachFunction.functionName
);
});
modulesCacheInfo[request] = {};
modulesCacheInfo[request].wrapped = actualContent;
return actualContent;
}
/* eslint-disable no-unused-vars */
function checkaddAsyncHooks() {
try {
var asyncHooks = require("async_hooks");
var contextMapping = {};
asyncHooks
.createHook({
init: function initHook(id, type, triggerId, promiseWrap) {
var curTxn = apmInsightAgentInstance.getCurTxn();
if (!curTxn || type !== "PROMISE") {
return;
}
contextMapping[id] = {
txn: curTxn,
tracker: apmInsightAgentInstance.getCurTracker()
};
},
before: function (id) {
if (contextMapping[id]) {
var context = contextMapping[id];
apmInsightAgentInstance.setCurContext(
context.txn,
context.tracker
);
}
},
after: function (id) {
if (contextMapping[id]) {
apmInsightAgentInstance.clearCurContext();
}
},
destroy: function (id) {
if (contextMapping[id]) {
delete contextMapping[id];
}
}
})
.enable();
} catch (error) {
logger.info("Async hook module is not available");
}
}
/* eslint-enable no-unused-vars */
module.exports = {
start: start,
instrumentCustomModules: instrumentCustomModules
};