Skip to content

Commit dd9b3b3

Browse files
committed
feat(aws-sdk): add exception hook
1 parent ca70bb9 commit dd9b3b3

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

plugins/node/opentelemetry-instrumentation-aws-sdk/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ aws-sdk instrumentation has few options available to choose from. You can set th
5353
| ----------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
5454
| `preRequestHook` | `AwsSdkRequestCustomAttributeFunction` | Hook called before request send, which allow to add custom attributes to span. |
5555
| `responseHook` | `AwsSdkResponseCustomAttributeFunction` | Hook for adding custom attributes when response is received from aws. |
56+
| `exceptionHook` | `AwsSdkExceptionCustomAttributeFunction` | Hook for adding custom attributes when exception is received from aws. |
5657
| `sqsProcessHook` | `AwsSdkSqsProcessCustomAttributeFunction` | Hook called after starting sqs `process` span (for each sqs received message), which allow to add custom attributes to it. |
5758
| `suppressInternalInstrumentation` | `boolean` | Most aws operation use http requests under the hood. Set this to `true` to hide all underlying http spans. |
5859
| `sqsExtractContextPropagationFromPayload` | `boolean` | Will parse and extract context propagation headers from SQS Payload, false by default. [When should it be used?](./doc/sns.md#integration-with-sqs) |

plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,30 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
309309
);
310310
}
311311

312+
private _callUserExceptionResponseHook(
313+
span: Span,
314+
request: NormalizedRequest,
315+
err: any
316+
) {
317+
const { exceptionHook } = this.getConfig();
318+
if (!exceptionHook) return;
319+
const requestInfo: AwsSdkRequestHookInformation = {
320+
request,
321+
};
322+
323+
safeExecuteInTheMiddle(
324+
() => exceptionHook(span, requestInfo, err),
325+
(e: Error | undefined) => {
326+
if (e)
327+
diag.error(
328+
`${AwsInstrumentation.component} instrumentation: exceptionHook error`,
329+
e
330+
);
331+
},
332+
true
333+
);
334+
}
335+
312336
private _registerV2CompletedEvent(
313337
span: Span,
314338
v2Request: V2PluginRequest,
@@ -555,6 +579,11 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
555579
code: SpanStatusCode.ERROR,
556580
message: err.message,
557581
});
582+
self._callUserExceptionResponseHook(
583+
span,
584+
normalizedRequest,
585+
err
586+
);
558587
span.recordException(err);
559588
throw err;
560589
})

plugins/node/opentelemetry-instrumentation-aws-sdk/src/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export interface AwsSdkResponseHookInformation {
4848
moduleVersion?: string;
4949
response: NormalizedResponse;
5050
}
51+
5152
/**
5253
* span can be used to add custom attributes, or for any other need.
5354
* response is the object that is returned to the user calling the aws-sdk operation.
@@ -57,6 +58,14 @@ export interface AwsSdkResponseCustomAttributeFunction {
5758
(span: Span, responseInfo: AwsSdkResponseHookInformation): void;
5859
}
5960

61+
/**
62+
* span can be used to modify the status.
63+
* As we have no response object, the request can be used to determine the failed aws-sdk operation.
64+
*/
65+
export interface AwsSdkExceptionCustomAttributeFunction {
66+
(span: Span, requestInfo: AwsSdkRequestHookInformation, err: any): void;
67+
}
68+
6069
export interface AwsSdkSqsProcessHookInformation {
6170
message: SQS.Message;
6271
}
@@ -76,6 +85,12 @@ export interface AwsSdkInstrumentationConfig extends InstrumentationConfig {
7685
/** hook for adding custom attributes when response is received from aws */
7786
responseHook?: AwsSdkResponseCustomAttributeFunction;
7887

88+
/**
89+
* Hook for adding custom attributes when exception is received from aws.
90+
* This hook is only available with aws sdk v3
91+
*/
92+
exceptionHook?: AwsSdkExceptionCustomAttributeFunction;
93+
7994
/** hook for adding custom attribute when an sqs process span is started */
8095
sqsProcessHook?: AwsSdkSqsProcessCustomAttributeFunction;
8196

plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v3.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,50 @@ describe('instrumentation-aws-sdk-v3', () => {
272272
);
273273
});
274274
});
275+
276+
it('handle aws sdk exception', async () => {
277+
instrumentation.disable();
278+
instrumentation.setConfig({
279+
exceptionHook: (
280+
span: Span,
281+
requestInfo: AwsSdkRequestHookInformation,
282+
err: any
283+
) => {
284+
span.setAttribute(
285+
'attribute.from.exception.hook',
286+
requestInfo.request.commandInput.Bucket
287+
);
288+
span.setAttribute('error.from.exception.hook', err.name);
289+
},
290+
291+
suppressInternalInstrumentation: true,
292+
});
293+
instrumentation.enable();
294+
295+
nock(`https://ot-demo-test.s3.${region}.amazonaws.com/`)
296+
.put('/aws-ot-s3-test-object.txt?x-id=PutObject')
297+
.reply(
298+
404,
299+
fs.readFileSync('./test/mock-responses/s3-put-object.xml', 'utf8')
300+
);
301+
302+
const params = {
303+
Bucket: 'ot-demo-test',
304+
Key: 'aws-ot-s3-test-object.txt',
305+
};
306+
try {
307+
await s3Client.putObject(params);
308+
} catch {
309+
expect(getTestSpans().length).toBe(1);
310+
const [span] = getTestSpans();
311+
expect(span.attributes['attribute.from.exception.hook']).toEqual(
312+
params.Bucket
313+
);
314+
expect(span.attributes['error.from.exception.hook']).toEqual(
315+
'NotFound'
316+
);
317+
}
318+
});
275319
});
276320

277321
describe('custom service behavior', () => {

0 commit comments

Comments
 (0)