-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
closes #30
- Loading branch information
Showing
8 changed files
with
605 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
'use strict'; | ||
|
||
var shimmer = require('shimmer'); | ||
|
||
var requireHook = require('../../util/requireHook'); | ||
var transmission = require('../transmission'); | ||
var tracingUtil = require('../tracingUtil'); | ||
var cls = require('../cls'); | ||
|
||
var isActive = false; | ||
|
||
exports.activate = function() { | ||
isActive = true; | ||
}; | ||
|
||
exports.deactivate = function() { | ||
isActive = false; | ||
}; | ||
|
||
exports.init = function() { | ||
requireHook.on('ioredis', instrument); | ||
}; | ||
|
||
|
||
function instrument(ioredis) { | ||
shimmer.wrap(ioredis.prototype, 'sendCommand', instrumentIoredisSendCommand); | ||
} | ||
|
||
function instrumentIoredisSendCommand(original) { | ||
return function wrappedInternalSendCommand(command) { | ||
var client = this; | ||
|
||
if (command.promise == null || | ||
typeof command.name !== 'string' || | ||
!isActive || | ||
!cls.isTracing()) { | ||
return original.apply(this, arguments); | ||
} | ||
|
||
var callback; | ||
var parentSpan = cls.getCurrentSpan(); | ||
if (cls.isExitSpan(parentSpan)) { | ||
// multi commands could actually be recorded as multiple spans, but we only want to record one | ||
// batched span | ||
if (parentSpan.n === 'redis' && parentSpan.data.redis.command === 'multi') { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
var parentSpanSubCommands = parentSpan.data.redis.subCommands = parentSpan.data.redis.subCommands || []; | ||
parentSpanSubCommands.push(command.name); | ||
|
||
if (command.name.toLowerCase() === 'exec') { | ||
callback = cls.ns.bind(getMultiCommandEndCall(parentSpan)); | ||
command.promise.then( | ||
// make sure that the first parameter is never truthy | ||
callback.bind(null, null), | ||
callback); | ||
} | ||
} | ||
return original.apply(this, arguments); | ||
} | ||
|
||
var span = cls.startSpan('redis'); | ||
span.stack = tracingUtil.getStackTrace(wrappedInternalSendCommand); | ||
span.data = { | ||
redis: { | ||
connection: client.options.host + ':' + client.options.port, | ||
command: command.name.toLowerCase() | ||
} | ||
}; | ||
|
||
callback = cls.ns.bind(onResult); | ||
command.promise.then( | ||
// make sure that the first parameter is never truthy | ||
callback.bind(null, null), | ||
callback); | ||
return original.apply(this, arguments); | ||
|
||
function onResult(error) { | ||
// multi commands are ended by exec. Wait for the exec result | ||
if (command.name === 'pipeline') { | ||
This comment has been minimized.
Sorry, something went wrong. |
||
return; | ||
} | ||
|
||
span.d = Date.now() - span.ts; | ||
|
||
if (error) { | ||
span.error = true; | ||
span.ec = 1; | ||
span.data.redis.error = error.message; | ||
} | ||
|
||
transmission.addSpan(span); | ||
} | ||
}; | ||
} | ||
|
||
function getMultiCommandEndCall(span) { | ||
return function multiCommandEndCallback(error) { | ||
span.d = Date.now() - span.ts; | ||
|
||
var subCommands = span.data.redis.subCommands; | ||
var commandCount = subCommands ? subCommands.length : 1; | ||
|
||
span.b = { | ||
s: commandCount, | ||
u: false | ||
}; | ||
|
||
if (error) { | ||
span.error = true; | ||
span.ec = commandCount; | ||
span.data.redis.error = error.message; | ||
} | ||
|
||
transmission.addSpan(span); | ||
}; | ||
} |
Oops, something went wrong.
I think we need to support
pipeline
here also