UNPKG

appdynamics

Version:

Performance Profiler and Monitor

184 lines (156 loc) 5.64 kB
/* Copyright (c) AppDynamics, Inc., and its affiliates 2015 All Rights Reserved */ 'use strict'; var HttpOTUtils = require('./http-ot-utils.js'); module.exports.getHttpStatusCodeConfig = getHttpStatusCodeConfig; module.exports.generateError = generateError; module.exports.getHttpExitCallError = getHttpExitCallError; module.exports.finalizeTransaction = finalizeTransaction; module.exports.finalizeRequest = finalizeRequest; module.exports.startTransactionHandler = startTransactionHandler; function getHttpStatusCodeConfig(statusCode, statusCodesConfig) { if (!statusCodesConfig) { return undefined; } for (var i = 0, length = statusCodesConfig.length; i < length; ++i) { var statusCodeConfig = statusCodesConfig[i]; if (statusCode >= statusCodeConfig.lowerBound && statusCode <= statusCodeConfig.upperBound) { return statusCodeConfig; } } return undefined; } function generateError(exception, statusCode, statusCodesConfig) { var errorObject; if (exception) { if (exception instanceof Error) { errorObject = { name: "JS " + exception.name, message: exception.message, stack: exception.stack }; } } else { var statusCodeConfig = getHttpStatusCodeConfig(statusCode, statusCodesConfig); if (statusCodeConfig) { if (statusCodeConfig.enabled) { errorObject= { message: statusCodeConfig.description.toString(), name: "Error" }; } } else if ((statusCode < 200) || (statusCode >= 400)) { var error, errorMsg; if (statusCode >= 400 && statusCode <= 505) { error = "HTTP response code " + statusCode; } else { error = "HTTP response code other"; } errorMsg = "HTTP response code " + statusCode; errorObject = { message: errorMsg, name: error }; } } return errorObject; } function getHttpExitCallError(statusCode, stack, locals) { var error = {message: "Error code " + statusCode + " for URL " + locals.opts.hostname + ":" + locals.opts.port + locals.opts.path, name: "Error", stack: stack}; return error; } function finalizeRequest(err, profiler, time, transaction, req, res, span, sep) { if (!time.done()) return; finalizeTransaction(err, profiler, time, transaction, req, res, span); finalizeServiceEndpoint(err, profiler, time, sep, res); } function finalizeServiceEndpoint (err, profiler, time, sep, res) { if(!sep) return; sep.error = sep.error || res.error || err; sep.statusCode = sep.statusCode || (sep.error && sep.error.statusCode) || (res && res.statusCode) || 500; sep.stackTrace = sep.stackTrace || profiler.formatStackTrace(sep.error); var error = generateError(sep.error, sep.statusCode); if (error) { sep.error = error; } profiler.endServiceEndpoint(time, sep); } function finalizeTransaction (err, profiler, time, transaction, req, res, span) { transaction.error = transaction.error || res.error || err; transaction.statusCode = transaction.statusCode || (transaction.error && transaction.error.statusCode) || (res && res.statusCode) || 500; transaction.stackTrace = transaction.stackTrace || profiler.formatStackTrace(transaction.error); var error = generateError(transaction.error, transaction.statusCode); if (error) { transaction.error = error; } if (transaction.api && transaction.api.onResponseComplete) { transaction.api.onResponseComplete.apply(transaction.api, [req, res]); } if (span) { span.setAttributes(HttpOTUtils.getIncomingRequestAttributesOnResponse(res)); span.setStatus(HttpOTUtils.parseResponseStatus(res)); span.end(); } profiler.endTransaction(time, transaction); } function startTransactionHandler(req, res, agent, isHTTPs, tracer, ot_api) { var profiler = agent.profiler; var proxy = agent.proxy; var time = profiler.time(true); agent.metricsManager.addMetric( agent.metricsManager.HTTP_INCOMING_COUNT, 1 ); var span = undefined; var baggageCorrHeader = undefined; var otContext = undefined; if (tracer) { otContext = ot_api.propagation.extract(agent.TracerProvider.ot_api.ROOT_CONTEXT, req.headers); var baggage = ot_api.propagation.getBaggage(otContext); if (baggage && baggage.getEntry(agent.correlation.HEADER_NAME)) { baggageCorrHeader = baggage.getEntry(agent.correlation.HEADER_NAME).value; } } var transaction = profiler.startTransaction(time, req, "NODEJS_WEB", baggageCorrHeader); if (tracer) { ot_api.context.with(otContext, () => { span = tracer.startSpan(transaction.name, { kind: ot_api.SpanKind.SERVER, attributes: HttpOTUtils.getIncomingRequestAttributes(req) }); }); } agent.context.set("threadId", transaction.threadId); req.__appdThreadId = transaction.threadId; transaction.url = req.url; transaction.method = req.method; transaction.requestHeaders = req.headers; var eumEnabled = transaction.eumEnabled && !transaction.skip; if (!transaction.corrHeader && eumEnabled) { proxy.before(res, "writeHead", function (obj) { if (!transaction.isFinished) { var eumCookie = agent.eum.newEumCookie( transaction, req, obj, isHTTPs ); eumCookie.build(); } }); } var serviceEndpoint = profiler.startServiceEndpoint(time, req, 'NODEJS_WEB'); proxy.after(res, "end", function () { finalizeRequest(null, profiler, time, transaction, req, res, span, serviceEndpoint); transaction = null; serviceEndpoint = null; }); return { transaction, span, otContext, serviceEndpoint }; }