apminsight
Version:
monitor nodejs applications
321 lines (301 loc) • 10.1 kB
JavaScript
var metricstore = require("./../metrics/metricstore");
var constants = require("./../constants");
var webTxn = require("./../metrics/webtxn");
var logger = require("./../util/logger");
var utils = require("./../util/utils");
var tracker = require("./../metrics/tracker");
var nvmStats = require("./../metrics/nodevm");
function getTxnMetric() {
var metricArray = [];
var insDbMetric = {};
var insApdexRTMetric = new webTxn({});
processTxnMetric(
metricstore.getWebTxnMetric(),
constants.webTxnPrefix,
constants.apdex,
metricArray,
insDbMetric,
insApdexRTMetric
);
if (metricArray.length > 0) {
appendTxnApdexRtMetric(
insApdexRTMetric,
"",
constants.apdex,
metricArray
);
checkAndAppendDbMetric(insDbMetric, "", metricArray);
}
processTxnMetric(
metricstore.getBgTxnmetric(),
constants.bgTxnPrefix,
constants.bckgrnd,
metricArray,
insDbMetric
);
processAppMetric(metricArray);
logger.info("total metric collected " + metricArray.length);
return metricArray;
}
function processTxnMetric(
txnMetric,
nsPrefix,
name,
metricArray,
insDbMetric,
insApdexRTMetric
) {
var allUniqueTxn = Object.keys(txnMetric);
allUniqueTxn.forEach(function (txnName) {
var txn = txnMetric[txnName];
if (!txn) {
logger.critical("empty txn present in data store");
return;
}
var ns = nsPrefix + txn.getUrl();
appendTxnApdexRtMetric(txn, ns, name, metricArray, insApdexRTMetric);
aggregateAndAppendDbMetric(txn, ns, metricArray, insDbMetric);
});
}
function appendTxnApdexRtMetric(txn, ns, name, metricArray, insApdexRTMetric) {
var info = { ns: ns, name: name };
var txnData = txn.getFormattedRtData();
var metric = [info, txnData];
metricArray.push(metric);
if (insApdexRTMetric) {
insApdexRTMetric.aggregate(txn);
}
}
function aggregateAndAppendDbMetric(txn, ns, metricArray, insDbMetric) {
var dbMetric = {};
txn.getDbCalls().forEach(function (dbTracker) {
var info = dbTracker.extractOperationInfo();
if (utils.isEmpty(info.opn) || utils.isEmpty(info.object)) {
return;
}
var dbOpn = "db/" + info.opn + "/" + info.object + "/dummy-db";
var matchedDbOpn = dbMetric[dbOpn] || new tracker.DbTracker({});
matchedDbOpn.aggregate(dbTracker);
dbMetric[dbOpn] = matchedDbOpn;
});
checkAndAppendDbMetric(dbMetric, ns, metricArray, insDbMetric);
}
function checkAndAppendDbMetric(dbMetric, ns, metricArray, insDbMetric) {
Object.keys(dbMetric).forEach(function (eachUniqueDbOpn) {
var eachDbMetric = dbMetric[eachUniqueDbOpn];
var info = eachDbMetric.extractOperationInfo();
if (utils.isEmpty(info.opn) || utils.isEmpty(info.object)) {
return;
}
var metric = getDbMetric(eachDbMetric, ns, eachUniqueDbOpn);
if (insDbMetric) {
var opnName = "db/" + info.opn + "/all/dummy-db";
aggregateDbByOpnWise(insDbMetric, opnName, eachDbMetric);
aggregateDbByOpnWise(
insDbMetric,
constants.dbOpnOverAll,
eachDbMetric
);
}
metricArray.push(metric);
});
}
function aggregateDbByOpnWise(insDbMetric, dbOpn, eachDbMetric) {
var matchedDbOpn = insDbMetric[dbOpn] || new tracker.DbTracker({});
matchedDbOpn.aggregate(eachDbMetric);
insDbMetric[dbOpn] = matchedDbOpn;
}
function getDbMetric(dbTracker, ns, name) {
var info = { ns: ns, name: name };
var rtData = [
dbTracker.getTime(),
dbTracker.getMinRt(),
dbTracker.getMaxRt(),
dbTracker.getCount(),
dbTracker.getErrorCount()
];
return [info, rtData];
}
function processAppMetric(metricArray) {
formatAppMetricSum(metricArray);
formatAppMetricAvg(metricArray);
}
function formatAppMetricSum(metricArray) {
var appMetricSum = metricstore.getAppMetricSum();
var allAppMetrics = Object.keys(appMetricSum);
if (allAppMetrics.length <= 0) {
return;
}
var info = { ns: constants.appParam, name: constants.sumStr };
var data = [[appMetricSum]];
metricArray.push([info, data]);
}
function formatAppMetricAvg(metricArray) {
var appMetricAvg = metricstore.getAppMetricAvg();
var allAppMetrics = Object.keys(appMetricAvg);
if (allAppMetrics.length <= 0) {
return;
}
var formattedAppMetricAvg = {};
allAppMetrics.forEach(function (eachAppMetric) {
var metricInfo = appMetricAvg[eachAppMetric];
var data = [
metricInfo.total,
metricInfo.min,
metricInfo.max,
metricInfo.count,
0
];
formattedAppMetricAvg[eachAppMetric] = data;
});
var info = { ns: constants.appParam, name: constants.avgStr };
var data = [[formattedAppMetricAvg]];
metricArray.push([info, data]);
}
function getFormattedTraceData() {
var allTraceData = [];
var ignoreCount = 0;
var traceList = metricstore.getTraceMetric();
logger.info("number of trace collected::" + traceList.length);
traceList.forEach(function (txn) {
var traceInfo = txn.getTraceInfo();
var traceData = getTraceData(txn, traceInfo);
allTraceData.push([traceInfo, traceData]);
});
logger.info("number of trace ignored:: " + ignoreCount);
return allTraceData;
}
function getTraceData(txn, traceInfo) {
var allTrackerData = [];
var childTrackersData = [];
var rootTrackersData = [];
var rootTracker = txn.getRootTracker();
var allChildTrackers = rootTracker.getChildTrackers();
for (var index = 0; index < allChildTrackers.length; index++) {
var curChildTracker = allChildTrackers[index];
traverseTracker(txn, curChildTracker, traceInfo, childTrackersData);
}
appendSummaryTrackerInfo(allTrackerData, txn, traceInfo);
appendRootTrackerInfo(rootTrackersData, rootTracker);
rootTrackersData.push(childTrackersData);
allTrackerData.push([rootTrackersData]);
return allTrackerData;
}
function appendSummaryTrackerInfo(allTrackerData, txn, traceInfo) {
const rootTracker = txn.getRootTracker();
allTrackerData.push(rootTracker.getStartTime());
let totalMethodsCount = traceInfo.method_count - traceInfo.sql_trackers_count - traceInfo.loginfo.length;
let summary = `Total Call(s): ${totalMethodsCount} Method Call(s) `;
if(traceInfo.sql_trackers_count > 0){
summary += `+ ${traceInfo.sql_trackers_count} SQL(s)`;
}
if(traceInfo.loginfo.length > 0){
summary += `+ ${traceInfo.loginfo.length} Other exception(s)`;
}
allTrackerData.push(summary);
allTrackerData.push("SUMMARY");
allTrackerData.push(traceInfo.r_time);
allTrackerData.push(0);
allTrackerData.push(null);
}
function appendRootTrackerInfo(rootTrackersData, rootTracker) {
rootTrackersData.push(rootTracker.getStartTime());
rootTrackersData.push(rootTracker.getTrackerNameForTrace());
rootTrackersData.push(rootTracker.getComponent());
rootTrackersData.push(rootTracker.getTime() + rootTracker.getChildOverhead());
rootTrackersData.push(rootTracker.getTime());
rootTrackersData.push(null);
}
function traverseTracker(
txn,
baseTracker,
traceInfo,
childTrackersData,
curTrackerInfo
) {
if (!baseTracker || traceInfo.method_count > constants.maxTrackers) {
return;
}
curTrackerInfo = checkAndIncludeTracker(
txn,
baseTracker,
traceInfo,
childTrackersData,
curTrackerInfo
);
var allChildTrackers = baseTracker.getChildTrackers();
for (var index = 0; index < allChildTrackers.length; index++) {
var curChildTracker = allChildTrackers[index];
traverseTracker(
txn,
curChildTracker,
traceInfo,
childTrackersData,
curTrackerInfo
);
}
}
function checkAndIncludeTracker(
txn,
tracker,
traceInfo,
trackerData,
curTrackerInfo
) {
if (tracker.isAllowedInTrace(txn)) {
var tempTrackerInfo = getTrackerInfo(txn, tracker, traceInfo);
if (curTrackerInfo) {
curTrackerInfo[6].push(tempTrackerInfo);
} else {
trackerData.push(tempTrackerInfo);
}
if (tracker.isDistributedTrace()) {
traceInfo.dt_count++;
}
traceInfo.method_count++;
return tempTrackerInfo;
}
return curTrackerInfo;
}
function getTrackerInfo(txn, tracker, traceInfo) {
var trackerInfo = [
tracker.getStartTime(),
tracker.getTrackerNameForTrace(),
tracker.getComponent(),
tracker.getTime(),
tracker.getTime(),
tracker.getAdditionalInfo(txn),
[]
];
if (tracker.isDbTracker) {
var info = tracker.extractOperationInfo();
if (info.opn && info.object) {
var opnInfo = info.opn + "/" + info.object;
if (traceInfo.db_opn.indexOf(opnInfo) < 0) {
traceInfo.db_opn.push(opnInfo);
}
}
}
if (
tracker.isError() &&
traceInfo.loginfo.length < constants.maxExcPerTrace
) {
var errorInfo = tracker.getErrorInfo();
var eachLogInfo = {};
eachLogInfo.time = errorInfo.getTime();
eachLogInfo.level = errorInfo.getLevel();
eachLogInfo.str = errorInfo.getMessage();
eachLogInfo.err_clz = errorInfo.getType();
eachLogInfo.st = errorInfo.getErrorStackFrames();
traceInfo.loginfo.push(eachLogInfo);
}
return trackerInfo;
}
function getNVMMetrics() {
return nvmStats.getNodeVMStats();
}
module.exports = {
getTxnMetric: getTxnMetric,
getFormattedTraceData: getFormattedTraceData,
getNodeVMMetrics: getNVMMetrics
};