UNPKG

appdynamics

Version:

Performance Profiler and Monitor

147 lines (121 loc) 4.51 kB
/* Copyright (c) AppDynamics, Inc., and its affiliates 2015 All Rights Reserved */ "use strict"; var utility = require("../utility"); var HttpCommon = require("./http-common"); const bodyParser = require('body-parser'); var getGraphQLParams; var parseRequestParams; function HttpEntryProbe(agent) { this.agent = agent; } exports.HttpEntryProbe = HttpEntryProbe; HttpEntryProbe.prototype.init = function () {}; HttpEntryProbe.prototype.enableGraphQL = function (egql) { getGraphQLParams = egql.getGraphQLParams; }; HttpEntryProbe.prototype.enableGraphQLHttp = function (obj) { parseRequestParams = obj.parseRequestParams; }; HttpEntryProbe.prototype.attach = function (obj, moduleName) { var self = this; self.agent.timers.startTimer(100, true, function () {}); if (self.agent.tracer) { self.ot_api = self.agent.TracerProvider.ot_api; self.tracer = self.agent.tracer; } self.isHTTPs = obj.Agent && (obj.Agent.prototype.defaultPort == 443); // server probe self.agent.proxy.before(obj.Server.prototype, ['on', 'addListener'], function (obj, args) { if (args[0] !== 'request') return; if (obj.__httpProbe__) return; obj.__httpProbe__ = true; var cbIndex = args.length - 1; args[cbIndex] = self.__createRequestHandler(args[cbIndex], moduleName === 'https'); }); }; function invokeOriginal(callback, self, args, ot_api, span, otCtx, req, res) { if (ot_api) { ot_api.context.with(ot_api.trace.setSpan(otCtx, span), () => { ot_api.context.bind(ot_api.context.active(), req); ot_api.context.bind(ot_api.context.active(), res); return callback.apply(self, args); }); } else { return callback.apply(self, args); } } HttpEntryProbe.prototype.__createRequestHandler = function (callback, isHTTPs) { var self = this; const handler = function (req, res) { if (getGraphQLParams) { getGraphQLParams(req).then(function (params) { if (params.query !== null) { req._body = true; req.body = params; req.graphqlop = params.operationName || "undefined"; } self.agent.context.run(requestHandler, req, res); }); } else if (parseRequestParams) { const jsonParser = bodyParser.json(); jsonParser(req, res, (err) => { if(err) { self.agent.context.run(requestHandler, req, res); } else { parseRequestParams(req).then(function(params) { if (params.query !== null) { const { operationName } = params; req.graphqlop = operationName || "undefined"; } self.agent.context.run(requestHandler, req, res); }).catch(function() { self.agent.context.run(requestHandler, req, res); }); } }); } else { if ( self.agent.opts.enableGraphQL && self.agent.libagentConnector.getBusinessTransactionQueryType( "NODEJS_WEB", utility.createBtNamingWrapper(req) ) == utility.constants.GRAPHQL_QUERY_TYPE ) { self.agent.context.run(callback, req, res); } else { self.agent.context.run(requestHandler, req, res); } } }; function requestHandler(req, res) { let profiler = self.agent.profiler; let time = profiler.time(true); self.agent.metricsManager.addMetric(self.agent.metricsManager.HTTP_INCOMING_COUNT, 1); let { transaction, span, otContext, serviceEndpoint } = HttpCommon.startTransactionHandler(req, res, self.agent, isHTTPs, self.tracer, self.ot_api); var threadId = transaction.threadId; self.agent.context.run(() => { var oldThreadId = self.agent.thread.current(); self.agent.thread.resume(threadId); try { let threadProxyWrappedCb = self.agent.proxy.wrapWithThreadProxyIfEnabled(callback); return invokeOriginal(threadProxyWrappedCb, this, arguments, self.ot_api, span, otContext, req, res); } catch (e) { HttpCommon.finalizeRequest(e, profiler, time, transaction, req, res, span, serviceEndpoint); serviceEndpoint = null; transaction = null; throw e; } finally { self.agent.thread.resume(oldThreadId); } }); } // Ensure any properties on callback are still accessible through handler. // This is needed as Express attaches a bunch of extra properties and // functionality, which may need to be accessed by other modules down stream. handler.__proto__ = callback; return handler; };