UNPKG

appdynamics

Version:

Performance Profiler and Monitor

175 lines (146 loc) 5.08 kB
/* Copyright (c) AppDynamics, Inc., and its affiliates 2015 All Rights Reserved */ 'use strict'; var url = require("url"); function RedisProbe(agent) { this.agent = agent; this.packages = ['redis']; this.relativePackages = ['../commander']; } exports.RedisProbe = RedisProbe; function wrapExecutor(self, executor) { return async function proxyExecutor(command, args, name) { var profiler = self.agent.profiler; var proxy = self.agent.proxy; var locals = {}; locals.time = profiler.time(); locals.args = args; var urlParsed = new url.URL(this.options.url); var host = urlParsed.host; locals.exitCall = self.createExitCall(host, name, args); var val = executor.call(this, command, args, name); var currentCtxt = self.agent.thread.current(); return proxy.promise(val, function(obj, args, ret, locals) { self.agent.thread.resume(currentCtxt); if (!locals.exitCall) return; if (!locals.time.done()) return; var error = proxy.getErrorObject(ret.error); profiler.addExitCall(locals.time, locals.exitCall, error); }, this, args, locals); }; } function proxyAttachCommands(self, originalObject) { return function wrapperAttachCommands(argsObj) { argsObj.executor = wrapExecutor(self, argsObj.executor); return originalObject.attachCommands(argsObj); }; } RedisProbe.prototype.attachRelative = function(mod, args, obj) { var self = this; if(process.env.APPDYNAMICS_REDIS_PROBE_DISABLE == true || process.env.APPDYNAMICS_REDIS_PROBE_DISABLE == 'true') { return; } if (args[0] == '../commander') { var parentMod = mod.filename.split('@'); if (parentMod.length < 2 || parentMod[1] != "redis/client/dist/lib/client/index.js") { return; } if(obj.__appdynamicsProbeAttached__) return; obj.__appdynamicsProbeAttached__ = true; self.agent.on('destroy', function() { if(obj.__appdynamicsProbeAttached__) { delete obj.__appdynamicsProbeAttached__; } }); const originalObject = obj; const overriddenObject = {}; overriddenObject.attachCommands = proxyAttachCommands(self, originalObject); overriddenObject.__proto__ = originalObject; return overriddenObject; } }; RedisProbe.prototype.attach = function(obj) { var self = this; if(obj.__appdynamicsProbeAttached__) return; obj.__appdynamicsProbeAttached__ = true; self.agent.on('destroy', function() { if(obj.__appdynamicsProbeAttached__) { delete obj.__appdynamicsProbeAttached__; proxy.release(obj.createClient); } }); var proxy = self.agent.proxy; var profiler = self.agent.profiler; function proxyCommand(client) { var method = client.internal_send_command ? "internal_send_command" : "send_command"; proxy.around(client, method, before, after); function before(obj, args, locals) { locals.time = profiler.time(); var address = client.address || (client.host + ':' + client.port); var command, params; if (typeof(args[0]) == 'string') { command = args[0]; params = args[1]; } else { command = args[0].command; params = args[0].args; } locals.exitCall = self.createExitCall(address, command, params); if (typeof(args[0]) === 'object' && typeof(args[0].callback) === 'function') { locals.methodHasCb = true; proxy.before(args[0], 'callback', function(obj, args) { complete(args, locals); }, false, false, self.agent.thread.current()); } else if (typeof(args[2]) === 'function') { locals.methodHasCb = true; proxy.before(args, 2, function(obj, args) { complete(args, locals); }, false, false, self.agent.thread.current()); } else { locals.methodHasCb = proxy.callback(args[1], -1, function(obj, args) { complete(args, locals); }, undefined, self.agent.thread.current()); } } function after(obj, args, ret, locals) { if (locals.methodHasCb) return; if (!ret || !ret.__appdynamicsIsPromiseResult__) complete(null, locals); else if (ret.error) complete(ret.error, locals); else complete(null, locals); } function complete(err, locals) { if (!locals.exitCall) return; if (!locals.time.done()) return; var error = proxy.getErrorObject(err); profiler.addExitCall(locals.time, locals.exitCall, error); } } proxy.after(obj, 'createClient', function(obj, args, ret) { var client = ret; proxyCommand(client); }); }; RedisProbe.prototype.createExitCall = function(address, command, params) { var self = this; var profiler = self.agent.profiler; var supportedProperties = { 'SERVER POOL': address, 'VENDOR': 'REDIS' }; return profiler.createExitCall(profiler.time(), { exitType: 'EXIT_CACHE', supportedProperties: supportedProperties, command: command, commandArgs: profiler.sanitize(params), stackTrace: profiler.stackTrace() }); };