UNPKG

ca-apm-probe

Version:

CA APM Node.js Agent monitors real-time health and performance of Node.js applications

132 lines (111 loc) 3.74 kB
/** * Copyright (c) 2015 CA. All rights reserved. * * This software and all information contained therein is confidential and proprietary and * shall not be duplicated, used, disclosed or disseminated in any way except as authorized * by the applicable license agreement, without the express written permission of CA. All * authorized reproductions must be marked with this language. * * EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE EXTENT * PERMITTED BY APPLICABLE LAW, CA PROVIDES THIS SOFTWARE WITHOUT WARRANTY * OF ANY KIND, INCLUDING WITHOUT LIMITATION, ANY IMPLIED WARRANTIES OF * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL CA BE * LIABLE TO THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR * INDIRECT, FROM THE USE OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, LOST * PROFITS, BUSINESS INTERRUPTION, GOODWILL, OR LOST DATA, EVEN IF CA IS * EXPRESSLY ADVISED OF SUCH LOSS OR DAMAGE. */ var path = require('path'); var agent = require('../agent'); var proxy = require('../proxy'); var logger = require("../logger.js"); var config = require('../configdata').getConfigData(); var showGraphQLQuery = config.graphql.showGraphQLQuery; var targetModule = new Object; module.exports = function (graphql) { targetModule.graphql = graphql; targetModule.Execution = findExecution(targetModule.graphql, require); targetModule.methodMap = getMethodsWithProbes(); var methodMap = targetModule.methodMap; if (methodMap[0] == "skip_instrument") { return; } logger.info('Loading graphql probe'); proxy.before(targetModule.Execution, 'execute', queryHook); }; function queryHook(obj, args, storage) { var req = args[0]; if(!req.document){ return; } var operationDefinition = null req.document.definitions.forEach(element => { if(element.kind == "OperationDefinition"){ operationDefinition = element; } }); var operation = operationDefinition.operation; var query = null; operationDefinition.selectionSet.selections.forEach(element => { if(!query){ query = element.name.value; } else { query += ',' + element.name.value; } }); var ctx = storage.get('ctx') || req.__CA_ctx; var queryString = query; if(ctx != null && showGraphQLQuery){ queryString = storage.get('gqlQuery'); queryString = JSON.stringify(queryString).replace(/\\n/g, ''); } if(ctx != null){ if(!agent.graphQLUrl){ agent.graphQLUrl = ctx.args.url; } ctx.args.url = ctx.args.url + "/" + operation + "/" + query; ctx.args.hdrs[0]="GraphQL"; } var evtName = 'graphql.execute'; var gqlCtx = agent.asynchEventStart(ctx, evtName, { operation: operation, query: queryString, tracePreviousCtx: true }); if(ctx != null){ ctx.gqlCtx = gqlCtx; gqlCtx.asyncCall = true; gqlCtx.fragmentEntryPoint = ctx.args.url; } storage.set('ctx', gqlCtx); } function findExecution(parent, require) { var cache = require.cache; for (var key in cache) { var candidate = cache[key]; if (candidate.exports !== parent) { continue; } var dirname = path.dirname(candidate.filename); var filename = path.join(dirname, 'execution', 'execute.js'); try { return require(filename); } catch (e) { return null; } } return null; } function getMethodsWithProbes() { if (!targetModule.methodMap) { var mt = new Object; mt[0] = 'graphql#execute'; targetModule.methodMap = mt; } return targetModule.methodMap; } function instrument(methodMap) { targetModule.methodMap = methodMap; } module.exports.getMethodsWithProbes = getMethodsWithProbes; module.exports.instrument = instrument.bind(module);