@instana/core
Advanced tools
Comparing version 2.6.0 to 2.6.1
@@ -6,2 +6,10 @@ # Change Log | ||
## [2.6.1](https://github.com/instana/nodejs/compare/v2.6.0...v2.6.1) (2022-08-09) | ||
**Note:** Version bump only for package @instana/core | ||
# [2.6.0](https://github.com/instana/nodejs/compare/v2.5.0...v2.6.0) (2022-06-28) | ||
@@ -8,0 +16,0 @@ |
{ | ||
"name": "@instana/core", | ||
"version": "2.6.0", | ||
"version": "2.6.1", | ||
"description": "Core library for Instana's Node.js packages", | ||
@@ -139,3 +139,3 @@ "main": "src/index.js", | ||
}, | ||
"gitHead": "f1ad73bc1502d90038190991943950057e8d1aca" | ||
"gitHead": "6910adcc568af60c1f648abc816daff8ff0bccdb" | ||
} |
@@ -10,3 +10,3 @@ /* | ||
const tracingUtil = require('./tracingUtil'); | ||
const { ENTRY, EXIT, INTERMEDIATE } = require('./constants'); | ||
const { ENTRY, EXIT, INTERMEDIATE, isExitSpan } = require('./constants'); | ||
const hooked = require('./clsHooked'); | ||
@@ -497,4 +497,59 @@ const tracingMetrics = require('./metrics'); | ||
} | ||
/** | ||
* This method should be used in all exit instrumentations. | ||
* It checks whether the tracing shoud be skipped or not. | ||
* | ||
* | options | description | ||
* -------------------------------------------------------------------------------------------- | ||
* | isActive | Whether the instrumentation is active or not. | ||
* | extendedResponse | By default the method returns a boolean. Sometimes it's helpful to | ||
* | | get the full response when you would like to determine why it was skipped. | ||
* | | For example because of suppression. | ||
* | skipParentSpanCheck | Some instrumentations have a very specific handling for checking the parent span. | ||
* | | With this flag you can skip the default parent span check. | ||
* | log | Logger instrumentations might not want to log because they run into recursive | ||
* | | problem raising `RangeError: Maximum call stack size exceeded`. | ||
* | skipIsTracing | Instrumentation wants to handle `cls.isTracing` on it's own (e.g db2) | ||
* | ||
* @param {Object.<string, *>} options | ||
*/ | ||
function skipExitTracing( | ||
options = { | ||
isActive: true, | ||
extendedResponse: false, | ||
skipParentSpanCheck: false, | ||
log: true, | ||
skipIsTracing: false | ||
} | ||
) { | ||
const parentSpan = getCurrentSpan(); | ||
const suppressed = tracingSuppressed(); | ||
const isExitSpanResult = isExitSpan(parentSpan); | ||
if (!options.skipParentSpanCheck && (!parentSpan || isExitSpanResult)) { | ||
if (options.log) { | ||
logger.warn( | ||
// eslint-disable-next-line max-len | ||
`Cannot start an exit span as this requires an active entry (or intermediate) span as parent. ${ | ||
parentSpan | ||
? `But the currently active span is itself an exit span: ${JSON.stringify(parentSpan)}` | ||
: 'Currently there is no span active at all' | ||
}` | ||
); | ||
} | ||
if (options.extendedResponse) return { skip: true, suppressed, isExitSpan: isExitSpanResult }; | ||
else return true; | ||
} | ||
const skipIsActive = options.isActive === false; | ||
const skipIsTracing = !options.skipIsTracing ? !isTracing() : false; | ||
const skip = skipIsActive || skipIsTracing || suppressed; | ||
if (options.extendedResponse) return { skip, suppressed, isExitSpan: isExitSpanResult }; | ||
else return skip; | ||
} | ||
module.exports = { | ||
skipExitTracing, | ||
currentEntrySpanKey, | ||
@@ -501,0 +556,0 @@ currentSpanKey, |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -32,5 +32,4 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
instrumentedMakeRequest(ctx, originalMakeRequest, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
// NOTE: `shimMakeRequest` in index.js is already checking the result of `isActive` | ||
if (cls.skipExitTracing()) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
@@ -37,0 +36,0 @@ } |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -47,6 +47,6 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
instrumentedMakeRequest(ctx, originalMakeRequest, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const self = this; | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
// NOTE: `shimMakeRequest` in index.js is already checking the result of `isActive` | ||
if (cls.skipExitTracing()) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
@@ -53,0 +53,0 @@ } |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -20,7 +20,60 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
class InstanaAWSLambda extends InstanaAWSProduct { | ||
propagateInstanaHeaders(originalArgs, span, suppressed = false) { | ||
/** @type {import('aws-sdk').Lambda.Types.InvocationRequest | import('aws-sdk').Lambda.Types.InvokeAsyncRequest} */ | ||
const params = originalArgs[1]; | ||
let clientContextContentBase64; | ||
let clientContextContentJSON; | ||
let isJSON = true; | ||
const instanaHeaders = { | ||
'x-instana-l': suppressed ? '0' : '1' | ||
}; | ||
if (span) { | ||
instanaHeaders['x-instana-s'] = span.s; | ||
instanaHeaders['x-instana-t'] = span.t; | ||
} | ||
// invokeAsync doesn't have the option ClientContext | ||
if (originalArgs[0] === 'invoke') { | ||
if (params.ClientContext != null) { | ||
clientContextContentBase64 = Buffer.from(params.ClientContext, 'base64').toString(); | ||
try { | ||
clientContextContentJSON = JSON.parse(clientContextContentBase64); | ||
if (typeof clientContextContentJSON.Custom === 'object') { | ||
Object.assign(clientContextContentJSON.Custom, instanaHeaders); | ||
} else { | ||
clientContextContentJSON.Custom = instanaHeaders; | ||
} | ||
} catch (err) { | ||
// ClientContext has a value that is not JSON, then we cannot add Instana headers | ||
isJSON = false; | ||
} | ||
} else { | ||
clientContextContentJSON = { | ||
Custom: instanaHeaders | ||
}; | ||
} | ||
if (isJSON) { | ||
clientContextContentBase64 = Buffer.from(JSON.stringify(clientContextContentJSON), 'utf8').toString('base64'); | ||
if (clientContextContentBase64.length <= MAX_CONTEXT_SIZE) { | ||
params.ClientContext = clientContextContentBase64; | ||
} | ||
} | ||
} | ||
} | ||
instrumentedMakeRequest(ctx, originalMakeRequest, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const self = this; | ||
const skipTracingResult = cls.skipExitTracing({ extendedResponse: true }); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
// NOTE: `shimMakeRequest` in index.js is already checking the result of `isActive` | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
this.propagateInstanaHeaders(originalArgs, null, skipTracingResult.suppressed); | ||
} | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
@@ -35,53 +88,4 @@ } | ||
// eslint-disable-next-line | ||
/** @type {import('aws-sdk').Lambda.Types.InvocationRequest | import('aws-sdk').Lambda.Types.InvokeAsyncRequest} */ | ||
const params = originalArgs[1]; | ||
let clientContextContentBase64; | ||
let clientContextContentJSON; | ||
let isJSON = true; | ||
this.propagateInstanaHeaders(originalArgs, span); | ||
const instanaCustomHeaders = { | ||
Custom: { | ||
'x-instana-l': cls.tracingSuppressed() ? '0' : '1', | ||
'x-instana-s': span.s, | ||
'x-instana-t': span.t | ||
} | ||
}; | ||
// invokeAsync doesn't have the option ClientContext | ||
if (originalArgs[0] === 'invoke') { | ||
if (params.ClientContext != null) { | ||
clientContextContentBase64 = Buffer.from(params.ClientContext, 'base64').toString(); | ||
try { | ||
clientContextContentJSON = JSON.parse(clientContextContentBase64); | ||
if (typeof clientContextContentJSON.Custom === 'object') { | ||
clientContextContentJSON.Custom['x-instana-l'] = cls.tracingSuppressed() ? '0' : '1'; | ||
clientContextContentJSON.Custom['x-instana-s'] = span.s; | ||
clientContextContentJSON.Custom['x-instana-t'] = span.t; | ||
} else { | ||
clientContextContentJSON.Custom = instanaCustomHeaders.Custom; | ||
} | ||
} catch (err) { | ||
// ClientContext has a value that is not JSON, then we cannot add Instana headers | ||
isJSON = false; | ||
} | ||
} else { | ||
clientContextContentJSON = instanaCustomHeaders; | ||
} | ||
if (isJSON) { | ||
clientContextContentBase64 = Buffer.from(JSON.stringify(clientContextContentJSON), 'utf8').toString('base64'); | ||
if (clientContextContentBase64.length <= MAX_CONTEXT_SIZE) { | ||
params.ClientContext = clientContextContentBase64; | ||
} | ||
} | ||
} | ||
if (cls.tracingSuppressed()) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
} | ||
if (typeof originalArgs[2] === 'function') { | ||
@@ -88,0 +92,0 @@ // callback case |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -57,18 +57,13 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
class InstanaAWSS3 extends InstanaAWSProduct { | ||
/** | ||
* Original args for ALL AWS SDK Requets: [method, params, callback] | ||
*/ | ||
instrumentedMakeRequest(ctx, originalMakeRequest, originalArgs) { | ||
const self = this; | ||
/** | ||
* Original args for ALL AWS SDK Requets: [method, params, callback] | ||
*/ | ||
if (cls.tracingSuppressed()) { | ||
// NOTE: `shimMakeRequest` in index.js is already checking the result of `isActive` | ||
if (cls.skipExitTracing()) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -75,0 +70,0 @@ const span = cls.startSpan(SPAN_NAME, EXIT); |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan, sqsAttributeNames } = require('../../../../constants'); | ||
const { EXIT, sqsAttributeNames } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -28,3 +28,2 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
instrumentedMakeRequest(ctx, originalMakeRequest, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const messageBody = originalArgs[1]; | ||
@@ -36,8 +35,8 @@ | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
} | ||
const skipTracingResult = cls.skipExitTracing({ isActive: true, extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
this.propagateSuppression(messageBody.MessageAttributes); | ||
} | ||
if (cls.tracingSuppressed()) { | ||
this.propagateSuppression(messageBody.MessageAttributes); | ||
return originalMakeRequest.apply(ctx, originalArgs); | ||
@@ -44,0 +43,0 @@ } |
@@ -16,3 +16,3 @@ /* | ||
} = require('../aws_utils'); | ||
const { ENTRY, EXIT, isExitSpan, sqsAttributeNames } = require('../../../../constants'); | ||
const { ENTRY, EXIT, sqsAttributeNames } = require('../../../../constants'); | ||
const requireHook = require('../../../../../util/requireHook'); | ||
@@ -71,12 +71,8 @@ const tracingUtil = require('../../../../tracingUtil'); | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < originalArgs.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedSendMessage(this, originalSendMessage, originalArgs); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < originalArgs.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalSendMessage.apply(this, arguments); | ||
return instrumentedSendMessage(this, originalSendMessage, originalArgs); | ||
}; | ||
@@ -121,16 +117,14 @@ } | ||
if (cls.tracingSuppressed()) { | ||
if (isBatch) { | ||
messageData.Entries.forEach(entry => { | ||
propagateSuppression(entry.MessageAttributes); | ||
}); | ||
} else { | ||
propagateSuppression(attributes); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
if (isBatch) { | ||
messageData.Entries.forEach(entry => { | ||
propagateSuppression(entry.MessageAttributes); | ||
}); | ||
} else { | ||
propagateSuppression(attributes); | ||
} | ||
} | ||
return originalSendMessage.apply(ctx, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalSendMessage.apply(ctx, originalArgs); | ||
@@ -137,0 +131,0 @@ } |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -32,9 +32,9 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
instrumentedSmithySend(ctx, originalSend, smithySendArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const command = smithySendArgs[0]; | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
// NOTE: `shimSmithySend` in index.js is already checking the result of `isActive` | ||
if (cls.skipExitTracing()) { | ||
return originalSend.apply(ctx, smithySendArgs); | ||
} | ||
const command = smithySendArgs[0]; | ||
return cls.ns.runAndReturn(() => { | ||
@@ -41,0 +41,0 @@ const self = this; |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../../../cls'); | ||
const { EXIT, isExitSpan } = require('../../../../constants'); | ||
const { EXIT } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -59,9 +59,9 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
instrumentedSmithySend(ctx, originalSend, smithySendArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const command = smithySendArgs[0]; | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
// NOTE: `shimSmithySend` in index.js is already checking the result of `isActive` | ||
if (cls.skipExitTracing()) { | ||
return originalSend.apply(ctx, smithySendArgs); | ||
} | ||
const command = smithySendArgs[0]; | ||
return cls.ns.runAndReturn(() => { | ||
@@ -68,0 +68,0 @@ const self = this; |
@@ -15,3 +15,3 @@ /* | ||
} = require('../aws_utils'); | ||
const { ENTRY, EXIT, isExitSpan, sqsAttributeNames } = require('../../../../constants'); | ||
const { ENTRY, EXIT, sqsAttributeNames } = require('../../../../constants'); | ||
const tracingUtil = require('../../../../tracingUtil'); | ||
@@ -87,16 +87,16 @@ const { InstanaAWSProduct } = require('./instana_aws_product'); | ||
if (cls.tracingSuppressed()) { | ||
if (isBatch) { | ||
sendMessageInput.Entries.forEach(entry => { | ||
this.propagateSuppression(entry.MessageAttributes); | ||
}); | ||
} else { | ||
this.propagateSuppression(attributes); | ||
// NOTE: `shimSmithySend` in index.js is already checking the result of `isActive` | ||
const skipTracingResult = cls.skipExitTracing({ extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
if (isBatch) { | ||
sendMessageInput.Entries.forEach(entry => { | ||
this.propagateSuppression(entry.MessageAttributes); | ||
}); | ||
} else { | ||
this.propagateSuppression(attributes); | ||
} | ||
} | ||
return originalSend.apply(ctx, smithySendArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalSend.apply(ctx, smithySendArgs); | ||
@@ -103,0 +103,0 @@ } |
@@ -16,4 +16,3 @@ /* | ||
ENTRY, | ||
EXIT, | ||
isExitSpan | ||
EXIT | ||
} = require('../../../constants'); | ||
@@ -68,10 +67,22 @@ const requireHook = require('../../../../util/requireHook'); | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
const message = originalArgs[0]; | ||
let attributes = message.attributes; | ||
if (!attributes) { | ||
attributes = message.attributes = {}; | ||
} | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
propagateSuppression(attributes); | ||
} | ||
return instrumentedPublishMessage(this, originalFunction, originalArgs); | ||
return originalFunction.apply(this, arguments); | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedPublishMessage(this, originalFunction, originalArgs); | ||
}; | ||
@@ -87,12 +98,2 @@ } | ||
if (cls.tracingSuppressed()) { | ||
propagateSuppression(attributes); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalPublishMessage.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -99,0 +100,0 @@ const span = cls.startSpan('gcps', EXIT); |
@@ -382,5 +382,6 @@ /* | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -395,7 +396,2 @@ for (let i = 0; i < arguments.length; i++) { | ||
function instrumentedOperation(operation, extractorPre, extractorPost, ctx, original, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return original.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -433,7 +429,2 @@ const span = cls.startSpan('gcs', constants.EXIT); | ||
function instrumentedCreateStream(operation, bindEvent, finalEvent, ctx, original, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return original.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -440,0 +431,0 @@ const span = cls.startSpan('gcs', constants.EXIT); |
@@ -53,5 +53,7 @@ /* | ||
function skipTracing(ignoreClsTracing = false) { | ||
// CASE: instrumentation is disabled | ||
// CASE: db call is disabled via suppress header | ||
return !isActive || cls.tracingSuppressed() || (ignoreClsTracing ? false : !cls.isTracing()); | ||
// CASES: instrumentation is disabled, db call is disabled via suppress header | ||
return ( | ||
cls.skipExitTracing({ isActive, skipIsTracing: true, skipParentSpanCheck: true }) || | ||
(ignoreClsTracing ? false : !cls.isTracing()) | ||
); | ||
} | ||
@@ -210,6 +212,6 @@ | ||
return originalFn.apply(this, arguments); | ||
} catch (catchedErr) { | ||
} catch (caughtErr) { | ||
span.ec = 1; | ||
span.data.db2.error = tracingUtil.getErrorDetails(catchedErr); | ||
throw catchedErr; | ||
span.data.db2.error = tracingUtil.getErrorDetails(caughtErr); | ||
throw caughtErr; | ||
} | ||
@@ -249,9 +251,2 @@ }; | ||
const parentSpan = cls.getCurrentSpan(); | ||
// CASE: There can be only one exit span, skip | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -326,3 +321,3 @@ const span = createSpan(stmt, instrumentQueryHelper); | ||
const canPrepareTracing = () => { | ||
const canTrace = () => { | ||
// cls.getCurrentSpan() : exists if prepare is called outside of the http context | ||
@@ -364,3 +359,3 @@ // prepareCallParentSpan : exists if prepare call is called inside of the http context | ||
return cls.ns.runAndReturn(() => { | ||
if (!canPrepareTracing()) { | ||
if (!canTrace()) { | ||
return originalExecuteNonQuerySync.apply(this, arguments); | ||
@@ -388,3 +383,3 @@ } | ||
return cls.ns.runAndReturn(() => { | ||
if (!canPrepareTracing()) { | ||
if (!canTrace()) { | ||
return originalExecuteSync.apply(this, arguments); | ||
@@ -406,3 +401,3 @@ } | ||
return cls.ns.runAndReturn(() => { | ||
if (!canPrepareTracing()) { | ||
if (!canTrace()) { | ||
return originalExecute.apply(this, arguments); | ||
@@ -446,9 +441,2 @@ } | ||
const parentSpan = cls.getCurrentSpan(); | ||
// CASE: There can be only one exit span, skip | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -455,0 +443,0 @@ const span = createSpan(stmt, instrumentQueryResultHelper); |
@@ -67,3 +67,3 @@ /* | ||
parent[actionPath[actionPath.length - 1]] = function instrumentedAction(params, cb) { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(this, arguments); | ||
@@ -70,0 +70,0 @@ } |
@@ -90,3 +90,3 @@ /* | ||
parent[actionPath[actionPath.length - 1]] = function instrumentedAction(params, options, originalCallback) { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(this, arguments); | ||
@@ -303,5 +303,6 @@ } | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return esReq.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -311,2 +312,3 @@ for (let i = 0; i < arguments.length; i++) { | ||
} | ||
return instrumentedRequest(this, esReq, originalArgs); | ||
@@ -317,7 +319,2 @@ }; | ||
function instrumentedRequest(ctx, origEsReq, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return origEsReq.apply(ctx, originalArgs); | ||
} | ||
// normalize arguments | ||
@@ -324,0 +321,0 @@ let params = originalArgs[0] || {}; |
@@ -41,10 +41,13 @@ /* | ||
const client = this; | ||
const parentSpan = cls.getCurrentSpan(); | ||
let callback; | ||
if (command.promise == null || typeof command.name !== 'string' || !isActive || !cls.isTracing()) { | ||
if ( | ||
command.promise == null || | ||
typeof command.name !== 'string' || | ||
cls.skipExitTracing({ isActive, skipParentSpanCheck: true }) | ||
) { | ||
return original.apply(this, arguments); | ||
} | ||
let callback; | ||
const parentSpan = cls.getCurrentSpan(); | ||
if ( | ||
@@ -115,12 +118,9 @@ parentSpan.n === exports.spanName && | ||
const client = this; | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!isActive || !cls.isTracing()) { | ||
// NOTE: multiple redis transaction can have a parent ioredis call | ||
if (cls.skipExitTracing({ isActive, skipParentSpanCheck: true }) || constants.isExitSpan(parentSpan)) { | ||
return original.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return original.apply(this, arguments); | ||
} | ||
// create a new cls context parent to track the multi/pipeline child calls | ||
@@ -127,0 +127,0 @@ const clsContextForMultiOrPipeline = cls.ns.createContext(); |
@@ -9,3 +9,3 @@ /* | ||
const cls = require('../../cls'); | ||
const { EXIT, isExitSpan } = require('../../constants'); | ||
const { EXIT } = require('../../constants'); | ||
const tracingUtil = require('../../tracingUtil'); | ||
@@ -60,8 +60,8 @@ | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = getFunctionArguments(arguments); | ||
return instrumentedCommand(this, originalCommand, originalArgs); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalCommand.apply(this, arguments); | ||
} | ||
return originalCommand.apply(this, arguments); | ||
const originalArgs = getFunctionArguments(arguments); | ||
return instrumentedCommand(this, originalCommand, originalArgs); | ||
}; | ||
@@ -71,8 +71,2 @@ } | ||
function instrumentedCommand(ctx, originalCommand, originaCommandArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || isExitSpan(parentSpan)) { | ||
return originalCommand.apply(ctx, originaCommandArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -79,0 +73,0 @@ const originalQuery = originaCommandArgs[0]; |
@@ -67,3 +67,3 @@ /* | ||
return function tmp() { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
@@ -83,3 +83,3 @@ } | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
@@ -105,3 +105,3 @@ } | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
@@ -121,3 +121,3 @@ } | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
@@ -136,7 +136,2 @@ } | ||
function instrumentedCmapQuery(ctx, originalQuery, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalQuery.apply(ctx, originalArgs); | ||
} | ||
const { originalCallback, callbackIndex } = findCallback(originalArgs); | ||
@@ -179,7 +174,2 @@ if (callbackIndex < 0) { | ||
function instrumentedCmapMethod(ctx, originalMethod, originalArgs, command) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalMethod.apply(ctx, originalArgs); | ||
} | ||
const { originalCallback, callbackIndex } = findCallback(originalArgs); | ||
@@ -220,7 +210,2 @@ if (callbackIndex < 0) { | ||
function instrumentedCmapGetMore(ctx, originalMethod, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalMethod.apply(ctx, originalArgs); | ||
} | ||
const { originalCallback, callbackIndex } = findCallback(originalArgs); | ||
@@ -261,5 +246,6 @@ if (callbackIndex < 0) { | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -269,2 +255,3 @@ for (let i = 0; i < arguments.length; i++) { | ||
} | ||
return instrumentedLegacyWrite(this, original, originalArgs); | ||
@@ -275,7 +262,2 @@ }; | ||
function instrumentedLegacyWrite(ctx, originalWrite, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalWrite.apply(ctx, originalArgs); | ||
} | ||
// pool.js#write throws a sync error if there is no callback, so we can safely assume there is one. If there was no | ||
@@ -282,0 +264,0 @@ // callback, we wouldn't be able to finish the span, so we won't start one. |
@@ -39,10 +39,11 @@ /* | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedFunction(this, originalFunction, originalArgs); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(this, arguments); | ||
} | ||
return originalFunction.apply(this, arguments); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedFunction(this, originalFunction, originalArgs); | ||
}; | ||
@@ -60,10 +61,5 @@ } | ||
function instrumentedMethod(ctx, originalFunction, originalArgs, stackTraceRef, commandProvider) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
} | ||
const connectionParameters = findConnectionParameters(ctx); | ||
const command = commandProvider(originalArgs); | ||
return cls.ns.runAndReturn(() => { | ||
@@ -119,15 +115,18 @@ const span = cls.startSpan(exports.spanName, constants.EXIT); | ||
// we explicitly do not check for cls.isTracing() here. | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (originalArgs.length >= 2 && typeof originalArgs[1] === 'function') { | ||
originalArgs[1] = cls.ns.bind(originalArgs[1]); | ||
} | ||
// Attach the statement to the PreparedStatement object so that we can add it to the span when execute is called. | ||
this.__instanaStatement = originalArgs[0]; | ||
return originalFunction.apply(this, originalArgs); | ||
// We do not want to use `cls.skipExitTracing` here because this is a db prepare call. | ||
// We do not want to check anything other than if the instrumentation is active. | ||
if (!isActive) { | ||
return originalFunction.apply(this, arguments); | ||
} | ||
return originalFunction.apply(this, arguments); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (originalArgs.length >= 2 && typeof originalArgs[1] === 'function') { | ||
originalArgs[1] = cls.ns.bind(originalArgs[1]); | ||
} | ||
// Attach the statement to the PreparedStatement object so that we can add it to the span when execute is called. | ||
this.__instanaStatement = originalArgs[0]; | ||
return originalFunction.apply(this, originalArgs); | ||
}; | ||
@@ -146,15 +145,16 @@ } | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (typeof originalArgs[1] === 'function') { | ||
originalArgs[1] = cls.ns.bind(originalArgs[1]); | ||
} else if (typeof originalArgs[0] === 'function') { | ||
originalArgs[0] = cls.ns.bind(originalArgs[0]); | ||
} | ||
return originalFunction.apply(this, originalArgs); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(this, arguments); | ||
} | ||
return originalFunction.apply(this, arguments); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (typeof originalArgs[1] === 'function') { | ||
originalArgs[1] = cls.ns.bind(originalArgs[1]); | ||
} else if (typeof originalArgs[0] === 'function') { | ||
originalArgs[0] = cls.ns.bind(originalArgs[0]); | ||
} | ||
return originalFunction.apply(this, originalArgs); | ||
}; | ||
@@ -161,0 +161,0 @@ } |
@@ -76,6 +76,7 @@ /* | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
return instrumentedAccessFunction(this, original, arguments[0], arguments[1], arguments[2]); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
return original.apply(this, arguments); | ||
return instrumentedAccessFunction(this, original, arguments[0], arguments[1], arguments[2]); | ||
}; | ||
@@ -86,6 +87,7 @@ } | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
return instrumentedAccessFunction(this, original, arguments[0], arguments[1], arguments[2]); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
return original.apply(this, arguments); | ||
return instrumentedAccessFunction(this, original, arguments[0], arguments[1], arguments[2]); | ||
}; | ||
@@ -96,6 +98,7 @@ } | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
return instrumentedAccessFunction(this, originalQuery, arguments[0], arguments[1], null, true); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalQuery.apply(this, arguments); | ||
} | ||
return originalQuery.apply(this, arguments); | ||
return instrumentedAccessFunction(this, originalQuery, arguments[0], arguments[1], null, true); | ||
}; | ||
@@ -106,6 +109,7 @@ } | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
return instrumentedAccessFunction(this, originalExecute, arguments[0], arguments[1], null, true); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalExecute.apply(this, arguments); | ||
} | ||
return originalExecute.apply(this, arguments); | ||
return instrumentedAccessFunction(this, originalExecute, arguments[0], arguments[1], null, true); | ||
}; | ||
@@ -127,7 +131,2 @@ } | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
} | ||
let host; | ||
@@ -134,0 +133,0 @@ let port; |
@@ -34,11 +34,12 @@ /* | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
// slightly more performant version of the usual Array.prototype.slice trick. | ||
const argsForOriginalQuery = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
argsForOriginalQuery[i] = arguments[i]; | ||
} | ||
return instrumentedQuery(this, original, argsForOriginalQuery); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
return original.apply(this, arguments); | ||
// slightly more performant version of the usual Array.prototype.slice trick. | ||
const argsForOriginalQuery = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
argsForOriginalQuery[i] = arguments[i]; | ||
} | ||
return instrumentedQuery(this, original, argsForOriginalQuery); | ||
}; | ||
@@ -48,8 +49,2 @@ } | ||
function instrumentedQuery(ctx, originalQuery, argsForOriginalQuery) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalQuery.apply(ctx, argsForOriginalQuery); | ||
} | ||
const host = ctx.connectionParameters.host; | ||
@@ -56,0 +51,0 @@ const port = ctx.connectionParameters.port; |
@@ -58,5 +58,6 @@ /* | ||
return function () { | ||
if (!isActive || !cls.isTracing() || typeof arguments[0] !== 'function') { | ||
if (cls.skipExitTracing({ isActive }) || typeof arguments[0] !== 'function') { | ||
return original.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -67,2 +68,3 @@ originalArgs[0] = cls.ns.bind(arguments[0]); | ||
} | ||
return original.apply(this, originalArgs); | ||
@@ -81,5 +83,6 @@ }; | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -89,2 +92,3 @@ for (let i = 0; i < arguments.length; i++) { | ||
} | ||
return instrumented(this, original, originalArgs); | ||
@@ -95,6 +99,2 @@ }; | ||
function instrumentedQuery(ctx, originalQuery, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalQuery.apply(ctx, originalArgs); | ||
} | ||
const statement = originalArgs[0]; | ||
@@ -106,6 +106,2 @@ const stackTraceRef = instrumentedQuery; | ||
function instrumentedExecute(ctx, originalExecute, originalArgs) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return originalExecute.apply(ctx, originalArgs); | ||
} | ||
const statement = preparedStatements.get(originalArgs[0]); | ||
@@ -118,3 +114,3 @@ const stackTraceRef = instrumentedExecute; | ||
return function () { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
@@ -130,3 +126,5 @@ } | ||
const resultAndSpan = startSpanBeforeSync(this, original, originalArgs, statement, shimQueryOrExecuteSync); | ||
finishSpan(resultAndSpan.error, resultAndSpan.span); | ||
if (resultAndSpan.error) { | ||
@@ -133,0 +131,0 @@ throw resultAndSpan.error; |
@@ -77,50 +77,45 @@ /* | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return original.apply(this, arguments); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan(exports.spanName, constants.EXIT); | ||
span.stack = tracingUtil.getStackTrace(wrappedCommand); | ||
span.data.redis = { | ||
connection: client.address, | ||
command | ||
}; | ||
const span = cls.startSpan(exports.spanName, constants.EXIT); | ||
// do not set the redis span as the current span | ||
cls.setCurrentSpan(parentSpan); | ||
span.stack = tracingUtil.getStackTrace(wrappedCommand); | ||
span.data.redis = { | ||
connection: client.address, | ||
command | ||
}; | ||
const callback = cls.ns.bind(onResult); | ||
const args = []; | ||
for (let i = 0; i < arguments.length; i++) { | ||
args[i] = arguments[i]; | ||
} | ||
const callback = cls.ns.bind(onResult); | ||
const args = []; | ||
for (let i = 0; i < arguments.length; i++) { | ||
args[i] = arguments[i]; | ||
} | ||
let userProvidedCallback = args[args.length - 1]; | ||
if (typeof userProvidedCallback !== 'function') { | ||
userProvidedCallback = null; | ||
args.push(callback); | ||
} else { | ||
args[args.length - 1] = callback; | ||
} | ||
let userProvidedCallback = args[args.length - 1]; | ||
if (typeof userProvidedCallback !== 'function') { | ||
userProvidedCallback = null; | ||
args.push(callback); | ||
} else { | ||
args[args.length - 1] = callback; | ||
} | ||
return original.apply(this, args); | ||
return original.apply(this, args); | ||
function onResult(error) { | ||
span.d = Date.now() - span.ts; | ||
function onResult(error) { | ||
span.d = Date.now() - span.ts; | ||
if (error) { | ||
span.ec = 1; | ||
span.data.redis.error = tracingUtil.getErrorDetails(error); | ||
} | ||
if (error) { | ||
span.ec = 1; | ||
span.data.redis.error = tracingUtil.getErrorDetails(error); | ||
} | ||
span.transmit(); | ||
span.transmit(); | ||
if (typeof userProvidedCallback === 'function') { | ||
return userProvidedCallback.apply(this, arguments); | ||
if (typeof userProvidedCallback === 'function') { | ||
return userProvidedCallback.apply(this, arguments); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
@@ -133,80 +128,87 @@ } | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return original.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (constants.isExitSpan(parentSpan)) { | ||
return original.apply(this, arguments); | ||
// 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 span = cls.startSpan(exports.spanName, constants.EXIT); | ||
// do not set the redis span as the current span | ||
cls.setCurrentSpan(parentSpan); | ||
span.stack = tracingUtil.getStackTrace(instrumentedMultiExec); | ||
span.data.redis = { | ||
connection: multi._client != null ? multi._client.address : undefined, | ||
command: isAtomic ? 'multi' : 'pipeline' | ||
}; | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan(exports.spanName, constants.EXIT, parentSpan.t, parentSpan.s); | ||
const callback = cls.ns.bind(onResult); | ||
const args = []; | ||
for (let i = 0; i < arguments.length; i++) { | ||
args[i] = arguments[i]; | ||
} | ||
span.stack = tracingUtil.getStackTrace(instrumentedMultiExec); | ||
span.data.redis = { | ||
connection: multi._client != null ? multi._client.address : undefined, | ||
command: isAtomic ? 'multi' : 'pipeline' | ||
}; | ||
let userProvidedCallback = args[args.length - 1]; | ||
if (typeof userProvidedCallback !== 'function') { | ||
userProvidedCallback = null; | ||
args.push(callback); | ||
} else { | ||
args[args.length - 1] = callback; | ||
} | ||
const callback = cls.ns.bind(onResult); | ||
const args = []; | ||
for (let i = 0; i < arguments.length; i++) { | ||
args[i] = arguments[i]; | ||
} | ||
const subCommands = (span.data.redis.subCommands = []); | ||
const len = multi.queue != null ? multi.queue.length : 0; | ||
let legacyMultiMarkerHasBeenSeen = false; | ||
for (let i = 0; i < len; i++) { | ||
let subCommand; | ||
if (typeof multi.queue.get === 'function') { | ||
subCommand = multi.queue.get(i); | ||
subCommands[i] = subCommand.command; | ||
subCommand.callback = buildSubCommandCallback(span, subCommand.callback); | ||
let userProvidedCallback = args[args.length - 1]; | ||
if (typeof userProvidedCallback !== 'function') { | ||
userProvidedCallback = null; | ||
args.push(callback); | ||
} else { | ||
// Branch for ancient versions of redis (like 0.12.1): | ||
subCommand = multi.queue[i]; | ||
if (!Array.isArray(subCommand) || subCommand.length === 0) { | ||
continue; | ||
args[args.length - 1] = callback; | ||
} | ||
const subCommands = (span.data.redis.subCommands = []); | ||
const len = multi.queue != null ? multi.queue.length : 0; | ||
let legacyMultiMarkerHasBeenSeen = false; | ||
for (let i = 0; i < len; i++) { | ||
let subCommand; | ||
if (typeof multi.queue.get === 'function') { | ||
subCommand = multi.queue.get(i); | ||
subCommands[i] = subCommand.command; | ||
subCommand.callback = buildSubCommandCallback(span, subCommand.callback); | ||
} else { | ||
// Branch for ancient versions of redis (like 0.12.1): | ||
subCommand = multi.queue[i]; | ||
if (!Array.isArray(subCommand) || subCommand.length === 0) { | ||
continue; | ||
} | ||
if (subCommand[0] === 'MULTI') { | ||
legacyMultiMarkerHasBeenSeen = true; | ||
continue; | ||
} | ||
const idx = legacyMultiMarkerHasBeenSeen && i >= 1 ? i - 1 : i; | ||
subCommands[idx] = subCommand[0]; | ||
} | ||
if (subCommand[0] === 'MULTI') { | ||
legacyMultiMarkerHasBeenSeen = true; | ||
continue; | ||
} | ||
const idx = legacyMultiMarkerHasBeenSeen && i >= 1 ? i - 1 : i; | ||
subCommands[idx] = subCommand[0]; | ||
} | ||
} | ||
// must not send batch size 0 | ||
if (subCommands.length > 0) { | ||
span.b = { | ||
s: subCommands.length | ||
}; | ||
} | ||
span.ec = 0; | ||
// must not send batch size 0 | ||
if (subCommands.length > 0) { | ||
span.b = { | ||
s: subCommands.length | ||
}; | ||
} | ||
span.ec = 0; | ||
return original.apply(this, args); | ||
return original.apply(this, args); | ||
function onResult(error) { | ||
span.d = Date.now() - span.ts; | ||
function onResult(error) { | ||
span.d = Date.now() - span.ts; | ||
if (error && isAtomic) { | ||
span.ec = span.data.redis.subCommands.length; | ||
} | ||
if (error && isAtomic) { | ||
span.ec = span.data.redis.subCommands.length; | ||
} | ||
span.transmit(); | ||
span.transmit(); | ||
if (typeof userProvidedCallback === 'function') { | ||
return userProvidedCallback.apply(this, arguments); | ||
if (typeof userProvidedCallback === 'function') { | ||
return userProvidedCallback.apply(this, arguments); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
@@ -213,0 +215,0 @@ } |
@@ -38,16 +38,12 @@ /* | ||
} | ||
if (isActive && cls.isTracing()) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (parentSpan && !constants.isExitSpan(parentSpan)) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
instrumentedLog(this, originalLog, originalArgs, markAsError); | ||
} else { | ||
return originalLog.apply(this, arguments); | ||
} | ||
} else { | ||
if (cls.skipExitTracing({ isActive, log: false })) { | ||
return originalLog.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
instrumentedLog(this, originalLog, originalArgs, markAsError); | ||
}; | ||
@@ -54,0 +50,0 @@ } |
@@ -32,19 +32,13 @@ /* | ||
if (isActive && cls.isTracing()) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (cls.skipExitTracing({ isActive, log: false })) { | ||
return originalLog.apply(this, arguments); | ||
} | ||
if (parentSpan && !constants.isExitSpan(parentSpan)) { | ||
const originalArgs = new Array(arguments.length); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
instrumentedLog(this, originalLog, originalArgs, options); | ||
} else { | ||
return originalLog.apply(this, arguments); | ||
} | ||
} else { | ||
return originalLog.apply(this, arguments); | ||
} | ||
instrumentedLog(this, originalLog, originalArgs, options); | ||
}; | ||
@@ -51,0 +45,0 @@ } |
@@ -37,11 +37,6 @@ /* | ||
return function (level) { | ||
if (!isActive || !cls.isTracing()) { | ||
if (cls.skipExitTracing({ isActive, log: false })) { | ||
return originalLog.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || constants.isExitSpan(parentSpan)) { | ||
return originalLog.apply(this, arguments); | ||
} | ||
const actualLevel = levels && levels.getLevel(level, levels.INFO); | ||
@@ -48,0 +43,0 @@ if (actualLevel == null || typeof actualLevel.level !== 'number' || actualLevel.level < 30000) { |
@@ -38,65 +38,59 @@ /* | ||
return function log(mergingObject, message) { | ||
if (isActive && cls.isTracing()) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (cls.skipExitTracing({ isActive, log: false })) { | ||
return originalLoggingFunction.apply(this, arguments); | ||
} | ||
if (parentSpan && !constants.isExitSpan(parentSpan)) { | ||
const originalArgs = new Array(arguments.length); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
const ctx = this; | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan('log.pino', constants.EXIT); | ||
span.stack = tracingUtil.getStackTrace(log); | ||
const ctx = this; | ||
return cls.ns.runAndReturn(() => { | ||
const span = cls.startSpan('log.pino', constants.EXIT); | ||
span.stack = tracingUtil.getStackTrace(log); | ||
if (typeof mergingObject === 'string') { | ||
// calls like logger.error('only a message') | ||
message = mergingObject; | ||
} else if (mergingObject && typeof mergingObject.message === 'string' && typeof message === 'string') { | ||
// calls like | ||
// logger.error({ message: 'a message in the merging object'}, 'an additional message as a string') | ||
message = `${mergingObject.message} -- ${message}`; | ||
} else if (mergingObject && typeof mergingObject.message === 'string') { | ||
// calls like | ||
// logger.error({ message: 'a message in the merging object'}) or | ||
// logger.error({ message: 'a message in the merging object: %s'}, /* non-string interpolation param */) | ||
message = mergingObject.message; | ||
} else if (typeof message === 'string') { | ||
// calls like | ||
// logger.error({ /* merging object without message attribute */ }, 'a string message) | ||
// Nothing to do, just use the given message (second argument) and ignore the first argument, which | ||
// apparently has no message attribute | ||
} else if (mergingObject != null) { | ||
// Fallback for calls with an unknown shape, like: | ||
// logger.error({ /* merging object without message attribute */ }) | ||
// Serialize the first argument, but only the first level, and also shorten it: | ||
message = inspect(mergingObject, { depth: 1 }).substring(0, 500); | ||
} else { | ||
// If it is neither of those call patterns, we give up and do not capture a message. | ||
message = 'Pino log call without message and mergingObject.'; | ||
} | ||
if (typeof mergingObject === 'string') { | ||
// calls like logger.error('only a message') | ||
message = mergingObject; | ||
} else if (mergingObject && typeof mergingObject.message === 'string' && typeof message === 'string') { | ||
// calls like | ||
// logger.error({ message: 'a message in the merging object'}, 'an additional message as a string') | ||
message = `${mergingObject.message} -- ${message}`; | ||
} else if (mergingObject && typeof mergingObject.message === 'string') { | ||
// calls like | ||
// logger.error({ message: 'a message in the merging object'}) or | ||
// logger.error({ message: 'a message in the merging object: %s'}, /* non-string interpolation param */) | ||
message = mergingObject.message; | ||
} else if (typeof message === 'string') { | ||
// calls like | ||
// logger.error({ /* merging object without message attribute */ }, 'a string message) | ||
// Nothing to do, just use the given message (second argument) and ignore the first argument, which | ||
// apparently has no message attribute | ||
} else if (mergingObject != null) { | ||
// Fallback for calls with an unknown shape, like: | ||
// logger.error({ /* merging object without message attribute */ }) | ||
// Serialize the first argument, but only the first level, and also shorten it: | ||
message = inspect(mergingObject, { depth: 1 }).substring(0, 500); | ||
} else { | ||
// If it is neither of those call patterns, we give up and do not capture a message. | ||
message = 'Pino log call without message and mergingObject.'; | ||
} | ||
span.data.log = { | ||
message | ||
}; | ||
span.data.log = { | ||
message | ||
}; | ||
if (level >= 50) { | ||
span.ec = 1; | ||
} | ||
if (level >= 50) { | ||
span.ec = 1; | ||
} | ||
try { | ||
return originalLoggingFunction.apply(ctx, originalArgs); | ||
} finally { | ||
span.d = Date.now() - span.ts; | ||
span.transmit(); | ||
} | ||
}); | ||
} else { | ||
return originalLoggingFunction.apply(this, arguments); | ||
try { | ||
return originalLoggingFunction.apply(ctx, originalArgs); | ||
} finally { | ||
span.d = Date.now() - span.ts; | ||
span.transmit(); | ||
} | ||
} else { | ||
return originalLoggingFunction.apply(this, arguments); | ||
} | ||
}); | ||
}; | ||
@@ -103,0 +97,0 @@ } |
@@ -71,34 +71,29 @@ /* | ||
return function (message) { | ||
if (isActive && cls.isTracing()) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (parentSpan && !constants.isExitSpan(parentSpan)) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (cls.skipExitTracing({ isActive, log: false })) { | ||
return originalMethod.apply(this, arguments); | ||
} | ||
if ( | ||
arguments.length === 1 && | ||
!!arguments[0] && | ||
typeof arguments[0] === 'object' && | ||
typeof arguments[0].message === 'string' | ||
) { | ||
// this is the case logger.$level({ message: '...'}) | ||
message = arguments[0].message; | ||
} else if (arguments.length >= 1) { | ||
for (let j = arguments.length - 1; j >= 1; j--) { | ||
if (!!arguments[j] && typeof arguments[j] === 'object' && typeof arguments[j].message === 'string') { | ||
message += arguments[j].message; | ||
} | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if ( | ||
arguments.length === 1 && | ||
!!arguments[0] && | ||
typeof arguments[0] === 'object' && | ||
typeof arguments[0].message === 'string' | ||
) { | ||
// this is the case logger.$level({ message: '...'}) | ||
message = arguments[0].message; | ||
} else if (arguments.length >= 1) { | ||
for (let j = arguments.length - 1; j >= 1; j--) { | ||
if (!!arguments[j] && typeof arguments[j] === 'object' && typeof arguments[j].message === 'string') { | ||
message += arguments[j].message; | ||
} | ||
const ctx = this; | ||
return createSpan(ctx, originalMethod, originalArgs, message, markAsError); | ||
} else { | ||
return originalMethod.apply(this, arguments); | ||
} | ||
} else { | ||
return originalMethod.apply(this, arguments); | ||
} | ||
const ctx = this; | ||
return createSpan(ctx, originalMethod, originalArgs, message, markAsError); | ||
}; | ||
@@ -143,17 +138,12 @@ } | ||
if (levelIsTraced(level) && isActive && cls.isTracing()) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (parentSpan && !constants.isExitSpan(parentSpan)) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let j = 0; j < arguments.length; j++) { | ||
originalArgs[j] = arguments[j]; | ||
} | ||
const ctx = this; | ||
return createSpan(ctx, originalMethod, originalArgs, message, levelIsError(level)); | ||
} else { | ||
return originalMethod.apply(this, arguments); | ||
} | ||
} else { | ||
if (cls.skipExitTracing({ isActive, log: false }) || !levelIsTraced(level)) { | ||
return originalMethod.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
for (let j = 0; j < arguments.length; j++) { | ||
originalArgs[j] = arguments[j]; | ||
} | ||
const ctx = this; | ||
return createSpan(ctx, originalMethod, originalArgs, message, levelIsError(level)); | ||
}; | ||
@@ -160,0 +150,0 @@ } |
@@ -45,10 +45,8 @@ /* | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedSendMessage(this, originalFunction, originalArgs); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedSendMessage(this, originalFunction, originalArgs); | ||
}; | ||
@@ -58,17 +56,22 @@ } | ||
function instrumentedSendMessage(ctx, originalSendMessage, originalArgs) { | ||
if (cls.tracingSuppressed()) { | ||
propagateSuppression(originalArgs[0]); | ||
propagateSuppression(originalArgs[1]); | ||
// We need to skip parentSpan condition because the parentSpan check is too specific in this fn | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true, skipParentSpanCheck: true }); | ||
const parentSpan = cls.getCurrentSpan(); | ||
const isExitSpan = skipTracingResult.isExitSpan; | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
propagateSuppression(originalArgs[0]); | ||
propagateSuppression(originalArgs[1]); | ||
} | ||
return originalSendMessage.apply(ctx, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if ( | ||
!parentSpan || // | ||
// allow rabbitmq parent exit spans, this is actually the span started in instrumentedChannelModelPublish | ||
(constants.isExitSpan(parentSpan) && parentSpan.n !== 'rabbitmq') | ||
) { | ||
// allow rabbitmq parent exit spans, this is actually the span started in instrumentedChannelModelPublish | ||
if (!parentSpan || (isExitSpan && parentSpan.n !== 'rabbitmq')) { | ||
return originalSendMessage.apply(ctx, originalArgs); | ||
} | ||
if (constants.isExitSpan(parentSpan) && parentSpan.n === 'rabbitmq') { | ||
if (isExitSpan && parentSpan.n === 'rabbitmq') { | ||
// if ConfirmChannel#publish/sendToQueue has been invoked, we have already created a new cls context in | ||
@@ -386,19 +389,15 @@ // instrumentedChannelModelPublish and must not do so again here. | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedChannelModelPublish(this, originalFunction, originalArgs); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedChannelModelPublish(this, originalFunction, originalArgs); | ||
}; | ||
} | ||
// The main work is actually done in instrumentedSendMessage which will be called by ConfirmChannel.publish | ||
// internally. We only instrument ConfirmChannel.publish to hook into the callback. | ||
function instrumentedChannelModelPublish(ctx, originalFunction, originalArgs) { | ||
// The main work is actually done in instrumentedSendMessage which will be called by ConfirmChannel.publish | ||
// internally. We only instrument ConfirmChannel.publish to hook into the callback. | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
@@ -424,19 +423,15 @@ } | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedCallbackModelPublish(this, originalFunction, originalArgs); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedCallbackModelPublish(this, originalFunction, originalArgs); | ||
}; | ||
} | ||
// The main work is actually done in instrumentedSendMessage which will be called by ConfirmChannel.publish | ||
// internally. We only instrument ConfirmChannel.publish to hook into the callback. | ||
function instrumentedCallbackModelPublish(ctx, originalFunction, originalArgs) { | ||
// The main work is actually done in instrumentedSendMessage which will be called by ConfirmChannel.publish | ||
// internally. We only instrument ConfirmChannel.publish to hook into the callback. | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!cls.isTracing() || constants.isExitSpan(parentSpan)) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalFunction.apply(ctx, originalArgs); | ||
@@ -443,0 +438,0 @@ } |
@@ -10,3 +10,3 @@ /* | ||
const cls = require('../../cls'); | ||
const { ENTRY, EXIT, isExitSpan } = require('../../constants'); | ||
const { ENTRY, EXIT } = require('../../constants'); | ||
const requireHook = require('../../../util/requireHook'); | ||
@@ -36,9 +36,40 @@ const tracingUtil = require('../../tracingUtil'); | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = getFunctionArguments(arguments); | ||
const originalArgs = getFunctionArguments(arguments); | ||
const options = originalArgs[3]; | ||
const repeatableJob = options && typeof options.jobId === 'string' && options.jobId.indexOf('repeat') === 0; | ||
const repeatableJobIsSuppressed = repeatableJob && options.X_INSTANA_L === '0'; | ||
const skipIsTracing = !!repeatableJob; | ||
const parentSpan = cls.getCurrentSpan(); | ||
const skipTracingResult = cls.skipExitTracing({ | ||
isActive, | ||
extendedResponse: true, | ||
skipParentSpanCheck: true, | ||
skipIsTracing | ||
}); | ||
return instrumentedJobCreate(this, originalJobCreate, originalArgs); | ||
/** | ||
* Repeatable jobs cannot be persisted to a parent span, since we don't know for how long they will run. | ||
* The backend won't hold a reference to the parent entry span for too long, which will then make this span orphan. | ||
* So we send repeatable jobs as root span. | ||
*/ | ||
if ( | ||
skipTracingResult.skip || | ||
skipTracingResult.isExitSpan || | ||
(!parentSpan && !repeatableJob) || | ||
repeatableJobIsSuppressed | ||
) { | ||
/** | ||
* Repeatable jobs work in a different way than regular ones. | ||
* One single job is created with the repeat options, but the upcoming repetitions will lose the supression, | ||
* making cls.tracingSuppressed() to return false. | ||
* But repeated jobs have the instana header X_INSTANA_L properly set, which is why we include this check here. | ||
*/ | ||
if (skipTracingResult.suppressed || repeatableJobIsSuppressed) { | ||
propagateSuppression(options); | ||
} | ||
return originalJobCreate.apply(this, arguments); | ||
} | ||
return originalJobCreate.apply(this, arguments); | ||
return instrumentedJobCreate(this, originalJobCreate, originalArgs, options); | ||
}; | ||
@@ -48,3 +79,3 @@ } | ||
// Immediate jobs and repeatable jobs are caught here, bulked or not | ||
function instrumentedJobCreate(ctx, originalJobCreate, originalArgs) { | ||
function instrumentedJobCreate(ctx, originalJobCreate, originalArgs, options) { | ||
// Job.create args: Queue data, job name or ctx.DEFAULT_JOB_NAME, job data, options | ||
@@ -54,27 +85,3 @@ | ||
const queueName = (originalArgs[0] && originalArgs[0].name) || 'name not found'; | ||
const options = originalArgs[3]; | ||
const repeatableJob = options && typeof options.jobId === 'string' && options.jobId.indexOf('repeat') === 0; | ||
/** | ||
* Repeatable jobs work in a different way than regular ones. | ||
* One single job is created with the repeat options, but the upcoming repetitions will lose the supression, | ||
* making cls.tracingSuppressed() to return false. | ||
* But repeated jobs have the instana header X_INSTANA_L properly set, which is why we include this check here. | ||
*/ | ||
if (cls.tracingSuppressed() || (repeatableJob && options.X_INSTANA_L === '0')) { | ||
propagateSuppression(options); | ||
return originalJobCreate.apply(ctx, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
/** | ||
* Repeatable jobs cannot be persisted to a parent span, since we don't know for how long they will run. | ||
* The backend won't hold a reference to the parent entry span for too long, which will then make this span orphan. | ||
* So we send repeatable jobs as root span. | ||
*/ | ||
if ((!parentSpan && !repeatableJob) || isExitSpan(parentSpan)) { | ||
return originalJobCreate.apply(ctx, originalArgs); | ||
} | ||
return cls.ns.runAndReturn(() => { | ||
@@ -109,9 +116,20 @@ // inherit parent if exists. eg: ENTRY http server | ||
return function () { | ||
if (isActive) { | ||
const originalArgs = getFunctionArguments(arguments); | ||
const originalArgs = getFunctionArguments(arguments); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
return instrumentedJobCreateBulk(this, originalJobCreateBulk, originalArgs); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
const immediateJobs = originalArgs[1] || []; | ||
immediateJobs.forEach(job => { | ||
propagateSuppression(job.opts); | ||
}); | ||
return originalJobCreateBulk.apply(this, originalArgs); | ||
} | ||
return originalJobCreateBulk.apply(this, originalArgs); | ||
} | ||
return originalJobCreateBulk.apply(this, arguments); | ||
return instrumentedJobCreateBulk(this, originalJobCreateBulk, originalArgs); | ||
}; | ||
@@ -131,29 +149,17 @@ } | ||
if (cls.tracingSuppressed()) { | ||
immediateJobs.forEach(job => { | ||
propagateSuppression(job.opts); | ||
}); | ||
return originalJobCreateBulk.apply(ctx, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
immediateJobs.forEach(job => { | ||
if (parentSpan && !isExitSpan(parentSpan)) { | ||
cls.ns.run(() => { | ||
const span = cls.startSpan(exports.spanName, EXIT); | ||
span.ts = Date.now(); | ||
span.stack = tracingUtil.getStackTrace(instrumentedJobCreateBulk, 2); | ||
span.data.bull = { | ||
sort: 'exit', | ||
queue: queueName | ||
}; | ||
const options = job.opts; | ||
cls.ns.run(() => { | ||
const span = cls.startSpan(exports.spanName, EXIT); | ||
span.ts = Date.now(); | ||
span.stack = tracingUtil.getStackTrace(instrumentedJobCreateBulk, 2); | ||
span.data.bull = { | ||
sort: 'exit', | ||
queue: queueName | ||
}; | ||
const options = job.opts; | ||
propagateTraceContext(options, span); | ||
propagateTraceContext(options, span); | ||
finishSpan(null, job.data, span); | ||
}); | ||
} | ||
finishSpan(null, job.data, span); | ||
}); | ||
}); | ||
@@ -160,0 +166,0 @@ |
@@ -71,13 +71,12 @@ /* | ||
if (cls.tracingSuppressed()) { | ||
addTraceLevelSuppressionToAllMessages(messages); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip || !messages || messages.length === 0) { | ||
if (skipTracingResult.suppressed) { | ||
addTraceLevelSuppressionToAllMessages(messages); | ||
} | ||
return originalSend.apply(this, arguments); | ||
} | ||
if (!isActive || !cls.isTracing() || !messages || messages.length === 0) { | ||
return originalSend.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || constants.isExitSpan(parentSpan)) { | ||
return originalSend.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -125,15 +124,14 @@ for (let argsIdx = 0; argsIdx < arguments.length; argsIdx++) { | ||
if (cls.tracingSuppressed()) { | ||
topicMessages.forEach(topicMessage => { | ||
addTraceLevelSuppressionToAllMessages(topicMessage.messages); | ||
}); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip || !topicMessages || topicMessages.length === 0) { | ||
if (skipTracingResult.suppressed) { | ||
topicMessages.forEach(topicMessage => { | ||
addTraceLevelSuppressionToAllMessages(topicMessage.messages); | ||
}); | ||
} | ||
return originalSendBatch.apply(this, arguments); | ||
} | ||
if (!isActive || !cls.isTracing() || !topicMessages || topicMessages.length === 0) { | ||
return originalSendBatch.apply(this, arguments); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || constants.isExitSpan(parentSpan)) { | ||
return originalSendBatch.apply(this, arguments); | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
@@ -140,0 +138,0 @@ for (let i = 0; i < arguments.length; i++) { |
@@ -41,6 +41,3 @@ /* | ||
return function () { | ||
if (isActive) { | ||
return instrumentedSend(this, original, arguments[0], arguments[1]); | ||
} | ||
return original.apply(this, arguments); | ||
return instrumentedSend(this, original, arguments[0], arguments[1]); | ||
}; | ||
@@ -50,7 +47,6 @@ } | ||
function instrumentedSend(ctx, originalSend, produceRequests, cb) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const args = [produceRequests]; | ||
// Possibly bail early | ||
if (!cls.isTracing() || constants.isExitSpan(parentSpan) || !produceRequests || produceRequests.length === 0) { | ||
if (cls.skipExitTracing({ isActive }) || !produceRequests || produceRequests.length === 0) { | ||
// restore original send args | ||
@@ -60,2 +56,3 @@ if (cb) { | ||
} | ||
return originalSend.apply(ctx, args); | ||
@@ -62,0 +59,0 @@ } |
@@ -44,10 +44,8 @@ /* | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedPublish(this, originalFunction, originalArgs, natsUrl); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedPublish(this, originalFunction, originalArgs, natsUrl); | ||
}; | ||
@@ -57,5 +55,3 @@ } | ||
function instrumentedPublish(ctx, originalPublish, originalArgs, natsUrl) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!cls.isTracing() || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalPublish.apply(ctx, originalArgs); | ||
@@ -62,0 +58,0 @@ } |
@@ -41,10 +41,8 @@ /* | ||
return function () { | ||
if (isActive && cls.isTracing()) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return instrumentedPublish(this, originalFunction, originalArgs, natsUrl); | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedPublish(this, originalFunction, originalArgs, natsUrl); | ||
}; | ||
@@ -54,5 +52,3 @@ } | ||
function instrumentedPublish(ctx, originalPublish, originalArgs, natsUrl) { | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!cls.isTracing() || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (cls.skipExitTracing({ isActive })) { | ||
return originalPublish.apply(ctx, originalArgs); | ||
@@ -129,2 +125,3 @@ } | ||
const activeSpan = cls.getCurrentSpan(); | ||
if (activeSpan && activeSpan.n === 'nats' && constants.isEntrySpan(activeSpan)) { | ||
@@ -131,0 +128,0 @@ // Expected case: The raw nats instrumentation kicks in earlier than the nats-streaming instrumentation, so we |
@@ -15,8 +15,2 @@ /* | ||
const { getFunctionArguments } = require('../../../util/function_arguments'); | ||
let logger; | ||
logger = require('../../../logger').getLogger('tracing/rdkafka', newLogger => { | ||
logger = newLogger; | ||
}); | ||
let traceCorrelationEnabled = constants.kafkaTraceCorrelationDefault; | ||
@@ -123,9 +117,2 @@ let headerFormat = constants.kafkaHeaderFormatDefault; | ||
const originalArgs = getFunctionArguments(arguments); | ||
const message = originalArgs[2]; | ||
if (!isActive || !message) { | ||
logger.debug('Will not instrument'); | ||
return originalProduce.apply(this, originalArgs); | ||
} | ||
return instrumentedProduce(this, originalProduce, originalArgs); | ||
@@ -145,3 +132,2 @@ }; | ||
if (!isActive) { | ||
logger.debug('Will not instrument'); | ||
return originalEmit.apply(this, originalArgs); | ||
@@ -155,10 +141,16 @@ } | ||
function instrumentedProduce(ctx, originalProduce, originalArgs) { | ||
if (cls.tracingSuppressed()) { | ||
const headers = addTraceLevelSuppression(originalArgs[6]); | ||
originalArgs[6] = headers; | ||
return originalProduce.apply(ctx, originalArgs); | ||
const message = originalArgs[2]; | ||
if (!message) { | ||
return originalProduce.apply(this, originalArgs); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan || constants.isExitSpan(parentSpan)) { | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
const headers = addTraceLevelSuppression(originalArgs[6]); | ||
originalArgs[6] = headers; | ||
} | ||
return originalProduce.apply(ctx, originalArgs); | ||
@@ -165,0 +157,0 @@ } |
@@ -199,29 +199,28 @@ /* | ||
function shimmedFunction() { | ||
const parentSpan = cls.getCurrentSpan(); | ||
const isTracing = isActive && cls.isTracing() && parentSpan && !constants.isExitSpan(parentSpan); | ||
const isSuppressed = cls.tracingLevel() === '0'; | ||
if (isTracing || isSuppressed) { | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
const originalArgs = new Array(arguments.length); | ||
for (let i = 0; i < arguments.length; i++) { | ||
originalArgs[i] = arguments[i]; | ||
} | ||
if (isTracing) { | ||
return instrumentedClientMethod( | ||
this, | ||
originalFunction, | ||
originalArgs, | ||
address, | ||
rpcPath, | ||
requestStream, | ||
responseStream | ||
); | ||
} else { | ||
const skipTracingResponse = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResponse.skip) { | ||
if (skipTracingResponse.suppressed) { | ||
// Suppressed: We don't want to trace this call but we need to propagate the x-instana-l=0 header. | ||
modifyArgs(originalArgs); // add x-instana-l: 0 to metadata | ||
return originalFunction.apply(this, originalArgs); | ||
} | ||
return originalFunction.apply(this, originalArgs); | ||
} | ||
return originalFunction.apply(this, arguments); | ||
return instrumentedClientMethod( | ||
this, | ||
originalFunction, | ||
originalArgs, | ||
address, | ||
rpcPath, | ||
requestStream, | ||
responseStream | ||
); | ||
} | ||
return copyAttributes(originalFunction, shimmedFunction); | ||
@@ -228,0 +227,0 @@ } |
@@ -77,18 +77,14 @@ /* | ||
const parentSpan = cls.getCurrentSpan(); | ||
const isTracing = isActive && cls.isTracing() && parentSpan && !constants.isExitSpan(parentSpan); | ||
const isSuppressed = cls.tracingLevel() === '0'; | ||
const originalArgs = copyArgs(arguments); | ||
if (!isTracing && !isSuppressed) { | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true }); | ||
if (skipTracingResult.skip) { | ||
if (skipTracingResult.suppressed) { | ||
modifyArgs(name, originalArgs, null); | ||
return origFn.apply(this, originalArgs); | ||
} | ||
return origFn.apply(this, arguments); | ||
} | ||
const originalArgs = copyArgs(arguments); | ||
// NOTE: isTracing is false when the span should be suppressed | ||
if (isSuppressed) { | ||
modifyArgs(name, originalArgs, null); | ||
return origFn.apply(this, originalArgs); | ||
} | ||
/** | ||
@@ -95,0 +91,0 @@ * https://github.com/grpc/grpc-node/blob/master/packages/grpc-js/src/client.ts#L281 |
@@ -64,8 +64,10 @@ /* | ||
let w3cTraceContext = cls.getW3cTraceContext(); | ||
const skipTracingResult = cls.skipExitTracing({ isActive, extendedResponse: true, skipParentSpanCheck: true }); | ||
const parentSpan = cls.getCurrentSpan() || cls.getReducedSpan(); | ||
if (!isActive || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (cls.tracingSuppressed()) { | ||
if (skipTracingResult.skip || !parentSpan || constants.isExitSpan(parentSpan)) { | ||
if (skipTracingResult.suppressed) { | ||
addTraceLevelHeader(headers, '0', w3cTraceContext); | ||
} | ||
return originalRequest.apply(this, arguments); | ||
@@ -72,0 +74,0 @@ } |
@@ -143,22 +143,31 @@ /* | ||
let w3cTraceContext = cls.getW3cTraceContext(); | ||
const skipTracingResult = cls.skipExitTracing({ | ||
isActive, | ||
extendedResponse: true, | ||
skipParentSpanCheck: true, | ||
skipIsTracing: true | ||
}); | ||
const parentSpan = cls.getCurrentSpan() || cls.getReducedSpan(); | ||
if ( | ||
!isActive || | ||
skipTracingResult.skip || | ||
!parentSpan || | ||
constants.isExitSpan(parentSpan) || | ||
shouldBeBypassed(parentSpan, options) || | ||
cls.tracingSuppressed() | ||
shouldBeBypassed(parentSpan, options) | ||
) { | ||
let traceLevelHeaderHasBeenAdded = false; | ||
if (cls.tracingSuppressed()) { | ||
if (skipTracingResult.suppressed) { | ||
traceLevelHeaderHasBeenAdded = tryToAddTraceLevelAddHeaderToOpts(options, '0', w3cTraceContext); | ||
} | ||
clientRequest = originalRequest.apply(coreModule, arguments); | ||
if (cls.tracingSuppressed() && !traceLevelHeaderHasBeenAdded) { | ||
if (skipTracingResult.suppressed && !traceLevelHeaderHasBeenAdded) { | ||
clientRequest.setHeader(constants.traceLevelHeaderName, '0'); | ||
setW3cHeadersOnRequest(clientRequest, w3cTraceContext); | ||
} | ||
return clientRequest; | ||
} | ||
cls.ns.run(() => { | ||
@@ -165,0 +174,0 @@ const span = cls.startSpan('node.http.client', constants.EXIT); |
@@ -130,2 +130,3 @@ /* | ||
} | ||
if (constants.isExitSpan(parentSpan)) { | ||
@@ -197,24 +198,9 @@ logger.warn( | ||
if (!isActive) { | ||
if (cls === null) { | ||
return callNext(/** @type {Function} */ (callback)); | ||
} | ||
const parentSpan = cls.getCurrentSpan(); | ||
if (!parentSpan) { | ||
logger.warn( | ||
// eslint-disable-next-line max-len | ||
`Cannot start an exit span (${name}) as this requires an active entry (or intermediate) span as parent. Currently there is no span active at all.` | ||
); | ||
if (cls.skipExitTracing({ isActive })) { | ||
return callNext(/** @type {Function} */ (callback)); | ||
} | ||
if (constants.isExitSpan(parentSpan)) { | ||
logger.warn( | ||
// eslint-disable-next-line max-len | ||
`Cannot start an exit span (${name}) as this requires an active entry (or intermediate) span as parent. But the currently active span is itself an exit span: ${JSON.stringify( | ||
parentSpan | ||
)}` | ||
); | ||
return callNext(/** @type {Function} */ (callback)); | ||
} | ||
@@ -221,0 +207,0 @@ return startSdkSpan( |
633923
17377