Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit 527e266

Browse files
author
Amir Blum
authored
feat(aws-sdk): add suppressInternalInstrumentation config option (#53)
1 parent 0711efb commit 527e266

File tree

5 files changed

+66
-8
lines changed

5 files changed

+66
-8
lines changed

packages/plugin-aws-sdk/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ aws-sdk plugin has few options available to choose from. You can set the followi
3434
| Options | Type | Description |
3535
| -------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------- |
3636
| `preRequestHook` | `AwsSdkRequestCustomAttributeFunction` | Hook called before request send, which allow to add custom attributes to span. |
37+
| `responseHook` | `AwsSdkResponseCustomAttributeFunction` | Hook for adding custom attributes when response is received from aws. |
3738
| `sqsProcessHook` | `AwsSdkSqsProcessCustomAttributeFunction` | Hook called after starting sqs `process` span (for each sqs received message), which allow to add custom attributes to it. |
39+
| `suppressInternalInstrumentation` | boolean | Most aws operation use http request under the hood. If http instrumentation is enabled, each aws operation will also create an http/s child describing the communication with amazon servers. Setting the suppressInternalInstrumentation` config value to `true` will cause the plugin to suppress instrumentation of underlying operations, effectively causing those http spans to be non-recordable. |
40+
3841

3942

4043
## Span Attributes

packages/plugin-aws-sdk/src/aws-sdk.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
callback | 1 | 2
1010
*/
1111
import { BasePlugin } from '@opentelemetry/core';
12-
import { Span, StatusCode, Attributes, SpanKind } from '@opentelemetry/api';
12+
import { Span, StatusCode, Attributes, SpanKind, context, suppressInstrumentation } from '@opentelemetry/api';
1313
import * as shimmer from 'shimmer';
1414
import AWS from 'aws-sdk';
1515
import { AttributeNames } from './enums';
@@ -143,7 +143,7 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
143143
const callbackWithContext = thisPlugin._tracer.bind(callback, span);
144144
return thisPlugin._tracer.withSpan(span, () => {
145145
thisPlugin.servicesExtensions.requestPostSpanHook(awsRequest);
146-
return original.call(awsRequest, callbackWithContext);
146+
return thisPlugin._callOriginalFunction(() => original.call(awsRequest, callbackWithContext));
147147
});
148148
};
149149
}
@@ -172,7 +172,7 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
172172

173173
const origPromise: Promise<any> = thisPlugin._tracer.withSpan(span, () => {
174174
thisPlugin.servicesExtensions.requestPostSpanHook(awsRequest);
175-
return original.apply(awsRequest, arguments);
175+
return thisPlugin._callOriginalFunction(() => original.call(awsRequest, arguments));
176176
});
177177

178178
return requestMetadata.isIncoming ? thisPlugin._bindPromise(origPromise, span) : origPromise;
@@ -206,6 +206,14 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
206206
this._logger.error('caught error ', error);
207207
}
208208
}
209+
210+
private _callOriginalFunction<T>(originalFunction: (...args: any[]) => T): T {
211+
if (this._config?.suppressInternalInstrumentation) {
212+
return context.with(suppressInstrumentation(context.active()), originalFunction);
213+
} else {
214+
return originalFunction();
215+
}
216+
}
209217
}
210218

211219
export const plugin = new AwsPlugin('aws-sdk');

packages/plugin-aws-sdk/src/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ export interface AwsSdkPluginConfig extends PluginConfig {
2323

2424
/** hook for adding custom attribute when an sqs process span is started */
2525
sqsProcessHook?: AwsSdkSqsProcessCustomAttributeFunction;
26+
27+
/**
28+
* Most aws operation use http request under the hood.
29+
* if http instrumentation is enabled, each aws operation will also create
30+
* an http/s child describing the communication with amazon servers.
31+
* Setting the `suppressInternalInstrumentation` config value to `true` will
32+
* cause the plugin to suppress instrumentation of underlying operations,
33+
* effectively causing those http spans to be non-recordable.
34+
*/
35+
suppressInternalInstrumentation?: boolean;
2636
}

packages/plugin-aws-sdk/test/aws-sdk.spec.ts

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,8 @@ describe('plugin-aws-sdk', () => {
219219
});
220220

221221
describe('plugin config', () => {
222-
beforeAll(() => {
223-
mockAwsSend(responseMockSuccess, 'data returned from operation');
224-
});
225-
226222
it('preRequestHook called and add request attribute to span', (done) => {
223+
mockAwsSend(responseMockSuccess, 'data returned from operation');
227224
const pluginConfig = {
228225
enabled: true,
229226
preRequestHook: (span: Span, request: { params: Record<string, any> }) => {
@@ -245,6 +242,7 @@ describe('plugin-aws-sdk', () => {
245242
});
246243

247244
it('preRequestHook throws does not fail span', (done) => {
245+
mockAwsSend(responseMockSuccess, 'data returned from operation');
248246
const pluginConfig = {
249247
enabled: true,
250248
preRequestHook: (span: Span, request: any) => {
@@ -266,6 +264,7 @@ describe('plugin-aws-sdk', () => {
266264
});
267265

268266
it('responseHook called and add response attribute to span', (done) => {
267+
mockAwsSend(responseMockSuccess, 'data returned from operation');
269268
const pluginConfig = {
270269
enabled: true,
271270
responseHook: (span: Span, response: { params: AWS.Response<any, any> }) => {
@@ -287,5 +286,40 @@ describe('plugin-aws-sdk', () => {
287286
done();
288287
});
289288
});
289+
290+
it('suppressInternalInstrumentation set to true with send()', (done) => {
291+
mockAwsSend(responseMockSuccess, 'data returned from operation', true);
292+
const pluginConfig = {
293+
enabled: true,
294+
suppressInternalInstrumentation: true,
295+
};
296+
297+
plugin.enable(AWS, provider, logger, pluginConfig);
298+
299+
const s3 = new AWS.S3();
300+
301+
s3.createBucket({ Bucket: 'aws-test-bucket' }, function (err, data) {
302+
const awsSpans = getAwsSpans();
303+
expect(awsSpans.length).toBe(1);
304+
done();
305+
});
306+
});
307+
308+
it('suppressInternalInstrumentation set to true with promise()', async () => {
309+
mockAwsSend(responseMockSuccess, 'data returned from operation', true);
310+
const pluginConfig = {
311+
enabled: true,
312+
suppressInternalInstrumentation: true,
313+
};
314+
315+
plugin.enable(AWS, provider, logger, pluginConfig);
316+
317+
const s3 = new AWS.S3();
318+
319+
await s3.createBucket({ Bucket: 'aws-test-bucket' }).promise();
320+
const awsSpans = getAwsSpans();
321+
expect(awsSpans.length).toBe(1);
322+
})
323+
290324
});
291325
});

packages/plugin-aws-sdk/test/testing-utils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import { isInstrumentationSuppressed, context } from '@opentelemetry/api';
12
import AWS from 'aws-sdk';
23

3-
export const mockAwsSend = (sendResult: any, data: any = undefined) => {
4+
export const mockAwsSend = (sendResult: any, data: any = undefined, expectedInstrumentationSuppressed: boolean = false) => {
45
AWS.Request.prototype.send = function (cb?: (error, response) => void) {
6+
expect(isInstrumentationSuppressed(context.active())).toStrictEqual(expectedInstrumentationSuppressed);
57
if (cb) {
68
(this as AWS.Request<any, any>).on('complete', (response) => {
79
cb(response.error, response);
@@ -19,6 +21,7 @@ export const mockAwsSend = (sendResult: any, data: any = undefined) => {
1921
};
2022

2123
AWS.Request.prototype.promise = function () {
24+
expect(isInstrumentationSuppressed(context.active())).toStrictEqual(expectedInstrumentationSuppressed);
2225
const response = {
2326
...sendResult,
2427
data,

0 commit comments

Comments
 (0)