UNPKG

appdynamics

Version:

Performance Profiler and Monitor

194 lines (164 loc) 6.13 kB
/* Copyright (c) AppDynamics, Inc., and its affiliates 2015 All Rights Reserved */ 'use strict'; function SocketioProbe(agent) { this.agent = agent; this.packages = ['socket.io']; this.attached = false; } exports.SocketioProbe = SocketioProbe; SocketioProbe.prototype.attach = function(obj) { var self = this; var socketIOServer; if(process.env.APPDYNAMICS_SOCKETIO_PROBE_DISABLE == true || process.env.APPDYNAMICS_SOCKETIO_PROBE_DISABLE == 'true') { return; } if(obj.__appdynamicsProbeAttached__) return; obj.__appdynamicsProbeAttached__ = true; self.agent.on('destroy', function() { if(obj.__appdynamicsProbeAttached__) { delete obj.__appdynamicsProbeAttached__; var socketIoObj = obj.prototype || obj.Server.prototype; if(socketIoObj) { proxy.release(socketIoObj.listen); proxy.release(socketIoObj.attach); } if (socketIOServer) { var nsps = socketIOServer.nsps || socketIOServer._nsps; if(nsps instanceof Map) { nsps.forEach(function(value, key) { var namespace = nsps.get(key); delete namespace.__appdynamicsProbeAttached__; }); } else { Object.keys(nsps).forEach(function(nameSpace) { delete nsps[nameSpace].__appdynamicsProbeAttached__; }); } } } }); var proxy = self.agent.proxy; var connectCount; var totalConnectCount; var metricsManager = self.agent.metricsManager; metricsManager.addMetric(metricsManager.SOCKETIO_CONNECTIONS, function() { if(connectCount === undefined) { connectCount = 0; } return connectCount; }); metricsManager.addMetric(metricsManager.SOCKETIO_CONNECTIONS_TOTAL, function() { if(totalConnectCount === undefined) { totalConnectCount = 0; } return totalConnectCount; }); var sentCountMetric = metricsManager.createMetric(metricsManager.SOCKETIO_MESSAGES_SENT); var receivedCountMetric = metricsManager.createMetric(metricsManager.SOCKETIO_MESSAGES_RECEIVED); var sentSizeMetric = metricsManager.createMetric(metricsManager.SOCKETIO_SENT_MESSAGES_SIZE); var receivedSizeMetric = metricsManager.createMetric(metricsManager.SOCKETIO_RECEIVED_MESSAGES_SIZE); var socketIoObj = obj.prototype || obj.Server.prototype; proxy.after(socketIoObj, ['listen','attach'], function(obj, args, ret) { if(!ret.sockets) return; socketIOServer = ret; if(connectCount === undefined) { connectCount = totalConnectCount = 0; } proxy.after(ret, 'of', function(obj, args, ret) { if (ret.__appdynamicsProbeAttached__) return; attachProbeToNameSpace(ret); ret.__appdynamicsProbeAttached__ = true; }); var nsps = ret.nsps || ret._nsps; if(nsps instanceof Map) { ret._nsps.forEach(function(value, key) { var namespace = ret._nsps.get(key); if (namespace.__appdynamicsProbeAttached__) return; attachProbeToNameSpace(namespace); namespace.__appdynamicsProbeAttached__ = true; }); } else { Object.keys(ret.nsps).forEach(function(nameSpace) { if (ret.nsps[nameSpace].__appdynamicsProbeAttached__) return; attachProbeToNameSpace(ret.nsps[nameSpace]); ret.nsps[nameSpace].__appdynamicsProbeAttached__ = true; }); } function attachProbeToNameSpace(nameSpaceObj) { proxy.before(nameSpaceObj, ['on', 'addListener'], function(obj, args) { if(args[0] !== 'connection') return; proxy.callback(args, -1, function(obj, args) { if(!args[0]) return; var socket = args[0]; // conenctions connectCount++; totalConnectCount++; socket.on('disconnect', function() { connectCount--; }); // sent messages proxy.before(socket, ['emit', 'send'], function(obj, args) { // ignore internal events if(args[0] === 'newListener') return; try { sentCountMetric.addValue(1); if(args.length > 1) { sentSizeMetric.addValue(JSON.stringify(args.slice(1)).length); } } catch (e) { // ignored; unable to serialize socket.io message } }); proxy.getter(socket, ['broadcast'], function(obj, ret) { proxy.before(ret, ['emit', 'send'], function(obj, args) { // ignore internal events if(args[0] === 'newListener') return; try { sentCountMetric.addValue(1); if(args.length > 1) { sentSizeMetric.addValue(JSON.stringify(args.slice(1)).length); } } catch (e) { // ignored; unable to serialize socket.io message } }); }); proxy.after(socket, ['to', 'in', 'except'], function(obj, args, ret) { proxy.before(ret, ['emit', 'send'], function(obj, args) { // ignore internal events if(args[0] === 'newListener') return; try { sentCountMetric.addValue(1); if(args.length > 1) { sentSizeMetric.addValue(JSON.stringify(args.slice(1)).length); } } catch (e) { // ignored; unable to serialize socket.io message } }); }); // received messages proxy.before(socket, ['on', 'addListener'], function(obj, args) { // ignore internal events if(args[0] === 'disconnect') return; proxy.callback(args, -1, function(obj, args) { try { var msg = Array.from(args); receivedCountMetric.addValue(1); if(msg.length > 0) { receivedSizeMetric.addValue(JSON.stringify(msg).length); } } catch (e) { // ignored; unable to serialize socket.io message } }); }); }); }); } }); };