@instana/core
Advanced tools
Comparing version 2.8.1 to 2.9.0
@@ -6,2 +6,10 @@ # Change Log | ||
# [2.9.0](https://github.com/instana/nodejs/compare/v2.8.1...v2.9.0) (2022-09-26) | ||
**Note:** Version bump only for package @instana/core | ||
## [2.8.1](https://github.com/instana/nodejs/compare/v2.8.0...v2.8.1) (2022-09-21) | ||
@@ -8,0 +16,0 @@ |
{ | ||
"name": "@instana/core", | ||
"version": "2.8.1", | ||
"version": "2.9.0", | ||
"description": "Core library for Instana's Node.js packages", | ||
@@ -139,3 +139,3 @@ "main": "src/index.js", | ||
}, | ||
"gitHead": "92addcc851d5f26d53d4a15e89fd353033957319" | ||
"gitHead": "9cd0ca71bb85162399a1e322b08b9ab2fe498db9" | ||
} |
@@ -43,9 +43,12 @@ /* | ||
} | ||
const redisClientProto = redis.RedisClient.prototype; | ||
commands.list.forEach(name => { | ||
// Some commands are not added or are renamed. Ignore them. | ||
// NOTE: Some commands are not added or are renamed. Ignore them. | ||
// Do not use & connector, because if the fn multi is defined, | ||
/// we still don't want to handle it here. Needs to be a OR condition | ||
if ( | ||
!redisClientProto[name] && | ||
!redisClientProto[name] || | ||
// Multi commands are handled differently. | ||
name !== 'multi' | ||
name === 'multi' | ||
) { | ||
@@ -60,21 +63,32 @@ return; | ||
// Batch === Individual commands fail and the whole batch executation will NOT fail | ||
// Multi === Individual commands fail and the whole multi executation will fail | ||
// Different version of redis (in particular ancient ones like 0.10.x) have rather different APIs for the multi | ||
// operations. Shimming them conditionally is not really necessary (shimmer checks for itself) but supresses a log | ||
// statement from shimmer. | ||
// 0.x => multi (https://github.com/redis/node-redis/blob/v0.12.1/index.js#L1105) exec | ||
// 0.x => no batch | ||
// 3.x => multi(https://github.com/redis/node-redis/blob/v3.1.2/lib/individualCommands.js#L24) exec = exec_transaction | ||
// 3.x => batch(https://github.com/redis/node-redis/blob/v3.1.2/lib/individualCommands.js#L31) exec = exec_batch | ||
if (redis.Multi) { | ||
// Different version of redis (in particular ancient ones like 0.10.x) have rather different APIs for the multi | ||
// operations. Shimming them conditionally is not really necessary (shimmer checks for itself) but supresses a log | ||
// statement from shimmer. | ||
const instrumentedAsMulti = instrumentMultiExec.bind(null, true); | ||
const instrumentedAsBatch = instrumentMultiExec.bind(null, false); | ||
if (typeof redis.Multi.prototype.exec_transaction === 'function') { | ||
shimmer.wrap(redis.Multi.prototype, 'exec_transaction', instrumentMultiExec.bind(null, true)); | ||
shimmer.wrap(redis.Multi.prototype, 'exec_transaction', instrumentedAsMulti); | ||
} | ||
const instrumentedBatch = instrumentMultiExec.bind(null, false); | ||
if (typeof redis.Multi.prototype.exec_batch === 'function') { | ||
// Old versions of redis also do not have exec_batch. See above (exec_transaction). | ||
shimmer.wrap(redis.Multi.prototype, 'exec_batch', instrumentedBatch); | ||
shimmer.wrap(redis.Multi.prototype, 'exec_batch', instrumentedAsBatch); | ||
} | ||
if (typeof redis.Multi.prototype.EXEC === 'function') { | ||
shimmer.wrap(redis.Multi.prototype, 'EXEC', instrumentedBatch); | ||
shimmer.wrap(redis.Multi.prototype, 'EXEC', instrumentedAsBatch); | ||
} | ||
// 0.x multi and 3.x batch use `exec` but we need to differeniate if batch or multi | ||
if (typeof redis.Multi.prototype.exec === 'function') { | ||
shimmer.wrap(redis.Multi.prototype, 'exec', instrumentedBatch); | ||
if (typeof redis.Multi.prototype.exec_transaction !== 'function') { | ||
shimmer.wrap(redis.Multi.prototype, 'exec', instrumentedAsMulti); | ||
} else { | ||
shimmer.wrap(redis.Multi.prototype, 'exec', instrumentedAsBatch); | ||
} | ||
} | ||
@@ -100,3 +114,2 @@ } | ||
const callback = cls.ns.bind(onResult); | ||
const args = []; | ||
@@ -107,2 +120,7 @@ for (let i = 0; i < arguments.length; i++) { | ||
// CASE: no callback provided | ||
// e.g. client.set('key', 'value') is valid without callback | ||
// e.g. client.get('key') is valid without callback | ||
// NOTE: multi & batch is not handled via instrumentCommand | ||
const callback = cls.ns.bind(onResult); | ||
let userProvidedCallback = args[args.length - 1]; | ||
@@ -144,19 +162,10 @@ if (typeof userProvidedCallback !== 'function') { | ||
// CASE: multi = multiple executions | ||
// These executations are combined in one batch (see test). | ||
// And all of them need to same parent. | ||
// This parent has to be the incoming http server span. | ||
// If parentSpan.n is "redis", we need to use the original entry span instead. (http server) | ||
// because `cls.getCurrentSpan()` is the previous redis execution of the multi executions. | ||
let parentSpan = cls.getCurrentSpan(); | ||
if (parentSpan.n === 'redis') { | ||
parentSpan = cls.getCurrentEntrySpan(); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan(exports.spanName, constants.EXIT, parentSpan.t, parentSpan.s); | ||
span.stack = tracingUtil.getStackTrace(instrumentedMultiExec); | ||
span.data.redis = { | ||
connection: multi._client != null ? multi._client.address : undefined, | ||
// pipeline = batch | ||
command: isAtomic ? 'multi' : 'pipeline' | ||
@@ -182,2 +191,3 @@ }; | ||
let legacyMultiMarkerHasBeenSeen = false; | ||
for (let i = 0; i < len; i++) { | ||
@@ -188,4 +198,9 @@ let subCommand; | ||
subCommands[i] = subCommand.command; | ||
subCommand.callback = buildSubCommandCallback(span, subCommand.callback); | ||
// CASE: a batch can succeed although an individual command failed | ||
if (!isAtomic) { | ||
subCommand.callback = buildSubCommandCallback(span, subCommand.callback); | ||
} | ||
} else { | ||
// NOTE: Remove in 3.x | ||
// Branch for ancient versions of redis (like 0.12.1): | ||
@@ -204,2 +219,3 @@ subCommand = multi.queue[i]; | ||
} | ||
// must not send batch size 0 | ||
@@ -215,7 +231,20 @@ if (subCommands.length > 0) { | ||
function onResult(error) { | ||
function onResult(err) { | ||
span.d = Date.now() - span.ts; | ||
if (error && isAtomic) { | ||
span.ec = span.data.redis.subCommands.length; | ||
if (err && isAtomic) { | ||
span.ec = 1; | ||
if (err.message) { | ||
span.data.redis.error = err.message; | ||
} else if (err instanceof Array && err.length) { | ||
span.data.redis.error = err[0].message; | ||
} else { | ||
span.data.redis.error = 'Unknown error'; | ||
} | ||
// NOTE: sub errors are not supported in 0.12 | ||
if (err.errors && err.errors.length) { | ||
span.data.redis.error = err.errors.map(subErr => subErr.message).join('\n'); | ||
} | ||
} | ||
@@ -233,2 +262,5 @@ | ||
// NOTE: We only need this function to capture errors in a batch command | ||
// 3.x offers the ability to read the errors as sub errors (sub error = sub command) | ||
// and 0.x has no batch functionality | ||
function buildSubCommandCallback(span, userProvidedCallback) { | ||
@@ -235,0 +267,0 @@ return function subCommandCallback(err) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
641295
17495