From 6ae90e74fee5c47cc4ade67d21c4885d34c08847 Mon Sep 17 00:00:00 2001 From: kirrg001 Date: Thu, 11 May 2023 14:25:18 +0200 Subject: [PATCH] fix(sqs): fix missing async context in recent aws-sdk/client-sqs version --- .gitignore | 1 + package-lock.json | 84 +++++++++---------- .../cloud/aws-sdk/v2/sqs/receiveMessage.js | 2 + .../tracing/cloud/aws-sdk/v3/sqs/receiver.js | 1 + .../cloud/aws-sdk/v3/sqs/test_definition.js | 1 + .../instrumentation/cloud/aws-sdk/v2/sqs.js | 1 + .../instrumentation/cloud/aws-sdk/v3/index.js | 3 + .../instrumentation/cloud/aws-sdk/v3/sqs.js | 30 ++++++- packages/core/test/config.js | 4 + 9 files changed, 84 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index bb377cb828..156f3bea80 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ test-duration-breakdown coverage /db2 instana-*.tgz +.vscode \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ff860faeae..e4ce1adc23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4267,17 +4267,6 @@ "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/md5-js": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.310.0.tgz", - "integrity": "sha512-x5sRBUrEfLWAS1EhwbbDQ7cXq6uvBxh3qR2XAsnGvFFceTeAadk7cVogWxlk3PC+OCeeym7c3/6Bv2HQ2f1YyQ==", - "dev": true, - "dependencies": { - "@aws-sdk/types": "3.310.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - } - }, "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-content-length": { "version": "3.310.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.310.0.tgz", @@ -5117,6 +5106,17 @@ "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/md5-js": { + "version": "3.329.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.329.0.tgz", + "integrity": "sha512-newSeHd+CO2hNmXhQOrUk5Y1hH7BsJ5J4IldcqHKY93UwWqvQNiepRowSa2bV5EuS1qx3kfXhD66PFNRprrIlQ==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.329.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" + } + }, "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/middleware-content-length": { "version": "3.329.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.329.0.tgz", @@ -8980,12 +8980,12 @@ } }, "node_modules/@aws-sdk/md5-js": { - "version": "3.329.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.329.0.tgz", - "integrity": "sha512-newSeHd+CO2hNmXhQOrUk5Y1hH7BsJ5J4IldcqHKY93UwWqvQNiepRowSa2bV5EuS1qx3kfXhD66PFNRprrIlQ==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.310.0.tgz", + "integrity": "sha512-x5sRBUrEfLWAS1EhwbbDQ7cXq6uvBxh3qR2XAsnGvFFceTeAadk7cVogWxlk3PC+OCeeym7c3/6Bv2HQ2f1YyQ==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.329.0", + "@aws-sdk/types": "3.310.0", "@aws-sdk/util-utf8": "3.310.0", "tslib": "^2.5.0" } @@ -9003,9 +9003,9 @@ } }, "node_modules/@aws-sdk/md5-js/node_modules/@aws-sdk/types": { - "version": "3.329.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.329.0.tgz", - "integrity": "sha512-wFBW4yciDfzQBSFmWNaEvHShnSGLMxSu9Lls6EUf6xDMavxSB36bsrVRX6CyAo/W0NeIIyEOW1LclGPgJV1okg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz", + "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==", "dev": true, "dependencies": { "tslib": "^2.5.0" @@ -10675,9 +10675,9 @@ } }, "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.55.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.55.0.tgz", - "integrity": "sha512-ljzqJcyjfJpEVSIAxwtIS8xMRUly84BdjlBXyp6cu4G8TUufgjNS31LWdhyGhgmW5vYBNr+LTz0Kwf6J+ou7Ug==", + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz", + "integrity": "sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==", "dev": true, "dependencies": { "tslib": "^2.3.1" @@ -50238,17 +50238,6 @@ "tslib": "^2.5.0" } }, - "@aws-sdk/md5-js": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.310.0.tgz", - "integrity": "sha512-x5sRBUrEfLWAS1EhwbbDQ7cXq6uvBxh3qR2XAsnGvFFceTeAadk7cVogWxlk3PC+OCeeym7c3/6Bv2HQ2f1YyQ==", - "dev": true, - "requires": { - "@aws-sdk/types": "3.310.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - } - }, "@aws-sdk/middleware-content-length": { "version": "3.310.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.310.0.tgz", @@ -51892,6 +51881,17 @@ "tslib": "^2.5.0" } }, + "@aws-sdk/md5-js": { + "version": "3.329.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.329.0.tgz", + "integrity": "sha512-newSeHd+CO2hNmXhQOrUk5Y1hH7BsJ5J4IldcqHKY93UwWqvQNiepRowSa2bV5EuS1qx3kfXhD66PFNRprrIlQ==", + "dev": true, + "requires": { + "@aws-sdk/types": "3.329.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" + } + }, "@aws-sdk/middleware-content-length": { "version": "3.329.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.329.0.tgz", @@ -55123,12 +55123,12 @@ } }, "@aws-sdk/md5-js": { - "version": "3.329.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.329.0.tgz", - "integrity": "sha512-newSeHd+CO2hNmXhQOrUk5Y1hH7BsJ5J4IldcqHKY93UwWqvQNiepRowSa2bV5EuS1qx3kfXhD66PFNRprrIlQ==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.310.0.tgz", + "integrity": "sha512-x5sRBUrEfLWAS1EhwbbDQ7cXq6uvBxh3qR2XAsnGvFFceTeAadk7cVogWxlk3PC+OCeeym7c3/6Bv2HQ2f1YyQ==", "dev": true, "requires": { - "@aws-sdk/types": "3.329.0", + "@aws-sdk/types": "3.310.0", "@aws-sdk/util-utf8": "3.310.0", "tslib": "^2.5.0" }, @@ -55143,9 +55143,9 @@ } }, "@aws-sdk/types": { - "version": "3.329.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.329.0.tgz", - "integrity": "sha512-wFBW4yciDfzQBSFmWNaEvHShnSGLMxSu9Lls6EUf6xDMavxSB36bsrVRX6CyAo/W0NeIIyEOW1LclGPgJV1okg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz", + "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==", "dev": true, "requires": { "tslib": "^2.5.0" @@ -56480,9 +56480,9 @@ } }, "@aws-sdk/util-utf8-browser": { - "version": "3.55.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.55.0.tgz", - "integrity": "sha512-ljzqJcyjfJpEVSIAxwtIS8xMRUly84BdjlBXyp6cu4G8TUufgjNS31LWdhyGhgmW5vYBNr+LTz0Kwf6J+ou7Ug==", + "version": "3.188.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz", + "integrity": "sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q==", "dev": true, "requires": { "tslib": "^2.3.1" diff --git a/packages/collector/test/tracing/cloud/aws-sdk/v2/sqs/receiveMessage.js b/packages/collector/test/tracing/cloud/aws-sdk/v2/sqs/receiveMessage.js index 4db09ee24c..c56f61c259 100644 --- a/packages/collector/test/tracing/cloud/aws-sdk/v2/sqs/receiveMessage.js +++ b/packages/collector/test/tracing/cloud/aws-sdk/v2/sqs/receiveMessage.js @@ -131,6 +131,8 @@ async function receiveAsync() { const data = await sqsPromise; return new Promise(resolve => { + // TODO: This could be simplified by wrapping the SQS.prototype.receiveMessage method. + // See v3/sqs.js instana.sdk.runInAsyncContext(sqsPromise.instanaAsyncContext, async () => { if (data && data.error) { log('receive message data error', data.error); diff --git a/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/receiver.js b/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/receiver.js index f238f0a297..4d77854a61 100644 --- a/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/receiver.js +++ b/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/receiver.js @@ -87,6 +87,7 @@ app.get('/warn-logs', (req, res) => { async function runAsPromise(isV2Style = false) { const command = new awsSdk3.ReceiveMessageCommand(receiveParams); numberOfReceiveMessageAttempts++; + const promise = isV2Style ? sqsv2.receiveMessage(receiveParams) : sqs.send(command); let span; diff --git a/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/test_definition.js b/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/test_definition.js index 0904c23ef7..a89efc7b16 100644 --- a/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/test_definition.js +++ b/packages/collector/test/tracing/cloud/aws-sdk/v3/sqs/test_definition.js @@ -32,6 +32,7 @@ const sendSnsNotificationToSqsQueue = require('./sendNonInstrumented').sendSnsNo const sendingMethods = ['v3', 'cb', 'v2']; const receivingMethods = ['v3', 'cb', 'v2']; + const getNextSendMethod = require('@instana/core/test/test_util/circular_list').getCircularList(sendingMethods); const getNextReceiveMethod = require('@instana/core/test/test_util/circular_list').getCircularList(receivingMethods); diff --git a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v2/sqs.js b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v2/sqs.js index e483fed05d..a906e8b768 100644 --- a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v2/sqs.js +++ b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v2/sqs.js @@ -309,6 +309,7 @@ function instrumentedReceiveMessage(ctx, originalReceiveMessage, originalArgs) { // promise use case if (typeof awsRequest.promise === 'function' && typeof originalCallback !== 'function') { const originalPromiseFn = awsRequest.promise; + awsRequest.promise = cls.ns.bind(function () { const promise = originalPromiseFn.apply(awsRequest, arguments); diff --git a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/index.js b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/index.js index 89bbd11ec9..ce6517be5f 100644 --- a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/index.js +++ b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/index.js @@ -32,6 +32,9 @@ let onFileLoaded = false; exports.init = function init() { sqsConsumer.init(); + // NOTE: each aws product can have it's own init fn to wrap or unwrap specific functions + awsProducts.forEach(awsProduct => awsProduct.init && awsProduct.init(requireHook, shimmer)); + /** * @aws-sdk/smithly-client >= 3.36.0 changed how the dist structure gets delivered * https://github.com/aws/aws-sdk-js-v3/blob/main/packages/smithy-client/CHANGELOG.md#3360-2021-10-08 diff --git a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/sqs.js b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/sqs.js index 30abd9df2c..0d89b75cd5 100644 --- a/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/sqs.js +++ b/packages/core/src/tracing/instrumentation/cloud/aws-sdk/v3/sqs.js @@ -39,6 +39,31 @@ const operations = Object.keys(operationsInfo); const SPAN_NAME = 'sqs'; class InstanaAWSSQS extends InstanaAWSProduct { + init(requireHook, shimmer) { + requireHook.onFileLoad(/@aws-sdk\/client-sqs\/dist-cjs\/SQS\.js/, function (module) { + shimmer.wrap(module.SQS.prototype, 'receiveMessage', function (originalReceiveMsgFn) { + return function instanaReceiveMessage() { + return cls.ns.runAndReturn(() => { + const ctx = cls.getAsyncContext(); + this._instanaCtx = ctx; + const promise = originalReceiveMsgFn.apply(this, arguments); + + promise.then = cls.ns.bind(promise.then); + + if (promise.catch) { + promise.catch = cls.ns.bind(promise.catch); + } + if (promise.finally) { + promise.finally = cls.ns.bind(promise.finally); + } + + return promise; + }); + }; + }); + }); + } + instrumentedSmithySend(ctx, originalSend, smithySendArgs) { const commandName = smithySendArgs[0].constructor.name; const operation = operationsInfo[commandName]; @@ -166,6 +191,8 @@ class InstanaAWSSQS extends InstanaAWSProduct { const command = smithySendArgs[0]; const sendMessageInput = command.input; + // Note: we pass in ctx._instanaCtx as the second parameter to runAndReturn which will run the function in the + // context belonging to this SQS promise. return cls.ns.runAndReturn(() => { const self = this; const span = cls.startSpan(SPAN_NAME, ENTRY); @@ -237,6 +264,7 @@ class InstanaAWSSQS extends InstanaAWSProduct { setImmediate(() => this.finishSpan(null, span)); } else if (data && data.Messages && data.Messages.length > 0) { const messages = data.Messages; + let tracingAttributes = readTracingAttributes(messages[0].MessageAttributes); if (!hasTracingAttributes(tracingAttributes)) { tracingAttributes = readTracingAttributesFromSns(messages[0].Body); @@ -283,7 +311,7 @@ class InstanaAWSSQS extends InstanaAWSProduct { return request; } - }); + }, ctx._instanaCtx); } buildSpanData(operation, sendMessageInput) { diff --git a/packages/core/test/config.js b/packages/core/test/config.js index 39e1c21fd2..c5b8543111 100644 --- a/packages/core/test/config.js +++ b/packages/core/test/config.js @@ -18,5 +18,9 @@ exports.getTestTimeout = () => { if (isCI()) { return 30000; } + // NOTE: Otherwise mocha will interrupt the debugging session quickly. + if (process.env.VSCODE_DEBUG === 'true') { + return 30000; + } return 5000; };