UNPKG

apminsight

Version:

monitor nodejs applications

328 lines (294 loc) 9.92 kB
var transaction = require("./transaction"); var libUtil = require("util"); var utils = require("./../util/utils"); var metricstore = require("./metricstore"); var constants = require("./../constants"); function WebTxn(reqInfo, req) { transaction.call(this, reqInfo); this._url = reqInfo.uri; this._exactUrl = reqInfo.uri; this._method = req ? req.method : ""; this._queryParam = reqInfo.queryParam; this._inputParam = reqInfo.inputParam; this._httpHeaders = reqInfo.httpHeaders; (this._apdex = 0), (this._satisfied = 0); (this._errorCodeDetails = {}), (this._tolerated = 0); (this._frustrated = 0), (this._resCode = 0); this._bytesInInfo = getBytesIn(req); this._bytesOutInfo = {}; this._syntheticKey = ""; } libUtil.inherits(WebTxn, transaction); WebTxn.prototype.endTransaction = function (res) { if (this.isTxnIgnored(res.statusCode)) { return; } var allChildTrackers = this.getRootTracker().getChildTrackers(); for (var index = 0; index < allChildTrackers.length; index++) { var curChildTracker = allChildTrackers[index]; traverseChildTrackers(curChildTracker, this); } this.updateRtMetric(); this.updateApdexMetric(); this.updateReqCount(res.statusCode); this.markCompleted(); this.updateInDataStore(); }; function traverseChildTrackers(baseChildTracker, txnObj) { if (!baseChildTracker) { return; } if (!baseChildTracker.isCompleted()) { apmInsightAgentInstance.endTracker(baseChildTracker, txnObj); } var allChilds = baseChildTracker.getChildTrackers(); for (var index = 0; index < allChilds.length; index++) { var currChild = allChilds[index]; traverseChildTrackers(currChild, txnObj); } } WebTxn.prototype.endApiTxn = function (err) { if (this.isCreatedByApi() && !this.isTxnIgnored(this._resCode)) { this.updateRtMetric(); this.updateApdexMetric(); this.updateReqCountByErr(err); this.markCompleted(); this.updateInDataStore(); } }; WebTxn.prototype.updateApdexMetric = function () { var threshold = utils.getGenericThreshold(this.getUrl()); if (this._responseTime <= threshold.getApdexTh() * 1000) { this._satisfied = 1; } else if (this._responseTime <= threshold.getApdexTh() * 4 * 1000) { this._tolerating = 1; } else { this._frustrated = 1; } }; WebTxn.prototype.updateReqCount = function (statusCode) { this._resCode = statusCode; if (utils.isPositiveNumber(statusCode) && statusCode >= 400) { this._errorCount = 1; this._errorCodeDetails[statusCode] = 1; } else { this._count = 1; } }; WebTxn.prototype.aggregate = function (txn) { this._url = txn.getUrl(); this._resCode = txn.getResCode(); this.checkAndAggregateBytes(txn); if (txn.isErrorTxn()) { this._errorCount += txn.getErrorCount(); this._errorRt += txn.getRt(); this.aggregateErrorCode(txn.getErrorCodeDetails()); } this.aggregateTxnSubResources(txn); if (txn.getCount() > 0) { this.aggregateNonErrorTxn(txn); this._satisfied += txn.getSatisfied(); this._tolerated += txn.getTolerated(); this._frustrated += txn.getFrustrated(); } }; WebTxn.prototype.checkAndAggregateBytes = function (txn) { aggregateBytes(this._bytesInInfo, txn.getBytesInInfo()); aggregateBytes(this._bytesOutInfo, txn.getBytesOutInfo()); }; WebTxn.prototype.aggregateErrorCode = function (aggregatedErrorCodes) { var allErrorCode = Object.keys(aggregatedErrorCodes); var curTxn = this; allErrorCode.forEach(function (eachErrorCode) { if (curTxn._errorCodeDetails[eachErrorCode]) { curTxn._errorCodeDetails[eachErrorCode] += aggregatedErrorCodes[eachErrorCode]; return; } curTxn._errorCodeDetails[eachErrorCode] = aggregatedErrorCodes[eachErrorCode]; }); }; WebTxn.prototype.updateInDataStore = function () { var txnMetric = metricstore.getWebTxnMetric(); var samplingFac = utils .getGenericThreshold(this.getUrl()) .getWebTxnSamplingFactor(); var metricLimit = utils .getGenericThreshold(this.getUrl()) .getApdexMetricSize(); this.checkAndupdateInDataStore(txnMetric, WebTxn, samplingFac, metricLimit); }; WebTxn.prototype.getFormattedRtData = function () { var apdexScore = 0; if (this.getCount() > 0) { apdexScore = (this.getSatisfied() + this.getTolerated() / 2) / this.getCount(); } var apdexRtData = [ this.getRt(), this.getMinRt(), this.getMaxRt(), this.getCount(), apdexScore, this.getSatisfied(), this.getTolerated(), this.getFrustrated(), this.getErrorCount() ]; var additinalMetric = { httpcode: this.getErrorCodeDetails(), components: this.getComponentDetails(), logmetric: this.getErrorDetails(), error_rt: this.getErrorRt(), bytes_in: [0, 0, 0, 0], bytes_out: [0, 0, 0, 0] }; if (this.getBytesInInfo().bytes) { var bytesInInfo = this.getBytesInInfo(); additinalMetric.bytes_in = [ bytesInInfo.bytes, bytesInInfo.min, bytesInInfo.max, bytesInInfo.count ]; } if (this.getBytesOutInfo().bytes) { var bytesOutInfo = this.getBytesOutInfo(); additinalMetric.bytes_out = [ bytesOutInfo.bytes, bytesOutInfo.min, bytesOutInfo.max, bytesOutInfo.count ]; } return [apdexRtData, additinalMetric]; }; WebTxn.prototype.getTraceInfo = function () { var traceInfo = {}; traceInfo.t_name = constants.webTxnPrefix + this.getUrl(); traceInfo.exact_url = this.getExactUrl(); traceInfo.http_method_name = this.getMethod(); traceInfo.s_time = this.getStartTime(); traceInfo.r_time = this.getRt(); traceInfo.http_query_str = this.getQueryParam(); traceInfo.http_input_params = this.getInputParam(); traceInfo.http_headers = this.getHttpHeaders(); traceInfo.trace_reason = 4; traceInfo.db_opn = []; traceInfo.loginfo = []; traceInfo.method_count = 1; traceInfo.dt_count = 0; traceInfo.custom_params = this.getCustomParamsAsStr(); Object.assign(traceInfo, this.getTrackerCountInfo()); traceInfo.drop_threshold = utils .getGenericThreshold(this.getUrl()) .getTxnTrackerDropThreshold(); this.appendCompInfoInTrace(traceInfo); if (this.getBytesInInfo().bytes) { traceInfo.hbytesin = this.getBytesInInfo().bytes; } if (this.getBytesOutInfo().bytes) { traceInfo.hbytes = this.getBytesOutInfo().bytes; } if (this.getResCode() > 0) { traceInfo.httpcode = this.getResCode(); } if (this.getRumTraceId()) { traceInfo.trace_id = this.getRumTraceId(); } if (this.getSyntheticKey()) { traceInfo[constants.syntheticMonitoringKey] = this.getSyntheticKey(); } if (!utils.isEmpty(this.getError())) { traceInfo.err_st = this.getError().getErrorStackFrames(); } return traceInfo; }; WebTxn.prototype.getExactUrl = function () { return this._exactUrl; }; WebTxn.prototype.getErrorCodeDetails = function () { return this._errorCodeDetails; }; WebTxn.prototype.getMethod = function () { return this._method; }; WebTxn.prototype.getResCode = function () { return this._resCode; }; WebTxn.prototype.getSatisfied = function () { return this._satisfied; }; WebTxn.prototype.getTolerated = function () { return this._tolerated; }; WebTxn.prototype.getFrustrated = function () { return this._frustrated; }; WebTxn.prototype.getQueryParam = function () { return this._queryParam; }; WebTxn.prototype.getInputParam = function () { return this._inputParam; }; WebTxn.prototype.getHttpHeaders = function () { return this._httpHeaders; }; WebTxn.prototype.getBytesInInfo = function () { return this._bytesInInfo; }; WebTxn.prototype.setBytesIn = function (bytes) { this._bytesInInfo = { bytes: bytes }; }; WebTxn.prototype.getBytesOutInfo = function () { return this._bytesOutInfo; }; WebTxn.prototype.setBytesOut = function (bytes) { this._bytesOutInfo = { bytes: bytes }; }; WebTxn.prototype.getSyntheticKey = function () { return this._syntheticKey; }; WebTxn.prototype.setSyntheticKey = function (key) { this._syntheticKey = key; }; WebTxn.prototype.getTxnType = function () { return "webtxn"; }; function getNormalisedUri(uri) { return uri ? uri.replace(constants.txnNormalizationRegex, "/*") : ""; } function getBytesIn(req) { var bytesInfo = {}; if (!req) { return bytesInfo; } if (req && req.headers) { var bytesIn = parseInt(req.headers[constants.contentLengthHeader]); return utils.isPositiveNumber(bytesIn) ? { bytes: bytesIn } : bytesInfo; } return bytesInfo; } function aggregateBytes(curTxnBytesInfo, txnBytesInfo) { if (txnBytesInfo.bytes) { if (curTxnBytesInfo.bytes) { curTxnBytesInfo.bytes += txnBytesInfo.bytes; curTxnBytesInfo.min = curTxnBytesInfo.min < txnBytesInfo.bytes ? curTxnBytesInfo.min : txnBytesInfo.bytes; curTxnBytesInfo.max = curTxnBytesInfo.max > txnBytesInfo.bytes ? curTxnBytesInfo.max : txnBytesInfo.bytes; curTxnBytesInfo.count++; } else { curTxnBytesInfo.bytes = txnBytesInfo.bytes; curTxnBytesInfo.min = txnBytesInfo.bytes; curTxnBytesInfo.max = txnBytesInfo.bytes; curTxnBytesInfo.count = 1; } } } module.exports = WebTxn;