appdynamics
Version:
Performance Profiler and Monitor
108 lines (95 loc) • 4.01 kB
JavaScript
;
var url = require('url');
const CONNECTION_ATTRIBUTES = Symbol('appdynamics.connection_attributes');
function RabbitMQExitProbe(agent) {
this.agent = agent;
}
exports.RabbitMQExitProbe = RabbitMQExitProbe;
RabbitMQExitProbe.prototype.init = function () {
};
RabbitMQExitProbe.prototype.attach = function (obj, moduleName) {
var self = this;
if(moduleName == 'amqplib/lib/connect') {
self.wrapConnect(obj);
} else if(moduleName == 'amqplib/lib/callback_model') {
self.wrapPublish(obj);
} else if(moduleName == 'amqplib/lib/channel_model') {
self.wrapPublish(obj);
}
};
RabbitMQExitProbe.prototype.wrapConnect = function(obj) {
var self = this;
self.agent.proxy.after(obj, 'connect', function(obj, args) {
if (!args || args.length < 1 || !args[0]) return;
var urlParam = args[0];
var connectionAttributes = {};
var urlParsed = urlParam;
if (typeof(urlParam) != 'object') {
urlParsed = url.parse(urlParam);
}
connectionAttributes['host'] = urlParsed.host || urlParsed.hostname || 'localhost';
connectionAttributes['port'] = urlParsed.port || (urlParsed.protocol && (urlParsed.protocol == 'amqp:') ? 5672 : 5671);
self.agent.proxy.callback(args, -1, function(obj, retArgs) {
if (!retArgs || retArgs.length < 2 || !retArgs[1]) return;
var conn = retArgs[1];
Object.defineProperty(conn, CONNECTION_ATTRIBUTES, {
value: connectionAttributes,
enumerable: false,
});
});
}, false, false, self.agent.thread.current());
};
RabbitMQExitProbe.prototype.getCorrelationHeader = function(exitCall) {
var self = this;
var correlationHeaderValue = self.agent.backendConnector.getCorrelationHeader(exitCall);
if (correlationHeaderValue) {
const noTxDetectHeader = self.agent.correlation.DISABLE_TRANSACTION_DETECTION + '=true';
const doNotResolveSubHeader = self.agent.correlation.DONOTRESOLVE + '=true';
correlationHeaderValue = correlationHeaderValue != noTxDetectHeader ? correlationHeaderValue + '*' +
doNotResolveSubHeader : correlationHeaderValue;
}
return correlationHeaderValue;
};
RabbitMQExitProbe.prototype.wrapPublish = function(obj) {
var self = this;
var proxy = self.agent.proxy;
var profiler = self.agent.profiler;
proxy.around(obj.Channel.prototype, 'publish', function(channel, args, locals) {
var argsArray = Array.prototype.slice.call(args);
locals.time = profiler.time();
locals.exitCall = createExitCall(self.agent, channel, locals.time, args);
if (locals.exitCall) {
var correlationHeaderValue = self.getCorrelationHeader(locals.exitCall);
if (correlationHeaderValue) {
self.agent.logger.debug(`RabbitMq Correlation Header is ${correlationHeaderValue}`);
var options = args[3] || {};
options.headers = options.headers ? options.headers : {};
options.headers[self.agent.correlation.HEADER_NAME] = correlationHeaderValue;
argsArray[3] = options;
}
return argsArray;
}
}, function(obj, args, ret, locals) {
var errorObject = {};
if (!ret) {
errorObject = { message: "RabbitMQError", name: "RabbitMQ pubish to queue failed" };
profiler.addExitCall(locals.time, locals.exitCall, errorObject);
} else {
profiler.addExitCall(locals.time, locals.exitCall);
}
}, false, self.agent.thread.current());
};
function createExitCall(agent, channel, time, args) {
var props = {
'HOST': channel.connection[CONNECTION_ATTRIBUTES] && channel.connection[CONNECTION_ATTRIBUTES].host || 'amqp://localhost',
'PORT': channel.connection[CONNECTION_ATTRIBUTES] && channel.connection[CONNECTION_ATTRIBUTES].port || 5672,
'EXCHANGE': args[0] || '<default>',
'ROUTING_KEY': args[1] || '<default>'
};
var ec = agent.profiler.createExitCall(time, {
exitType: 'RABBITMQ',
supportedProperties: props,
stackTrace: agent.profiler.stackTrace(),
});
return ec;
}