1
1
import { Handler } from 'aws-lambda' ;
2
- import { Utility } from '@aws-lambda-powertools/commons' ;
2
+ import { AsyncHandler , SyncHandler , Utility } from '@aws-lambda-powertools/commons' ;
3
3
import { TracerInterface } from '.' ;
4
4
import { ConfigServiceInterface , EnvironmentVariablesService } from './config' ;
5
5
import { HandlerMethodDecorator , TracerOptions , MethodDecorator } from './types' ;
@@ -67,7 +67,7 @@ import { Segment, Subsegment } from 'aws-xray-sdk-core';
67
67
* }
68
68
*
69
69
* export const handlerClass = new Lambda();
70
- * export const handler = handlerClass.handler;
70
+ * export const handler = handlerClass.handler.bind(handlerClass);
71
71
* ```
72
72
*
73
73
* ### Functions usage with manual instrumentation
@@ -334,33 +334,40 @@ class Tracer extends Utility implements TracerInterface {
334
334
* }
335
335
*
336
336
* export const handlerClass = new Lambda();
337
- * export const handler = handlerClass.handler;
337
+ * export const handler = handlerClass.handler.bind(handlerClass);
338
338
* ```
339
339
*
340
340
* @decorator Class
341
341
*/
342
342
public captureLambdaHandler ( ) : HandlerMethodDecorator {
343
- return ( target , _propertyKey , descriptor ) => {
343
+ return ( _target , _propertyKey , descriptor ) => {
344
344
/**
345
345
* The descriptor.value is the method this decorator decorates, it cannot be undefined.
346
346
*/
347
347
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
348
348
const originalMethod = descriptor . value ! ;
349
349
350
- descriptor . value = ( ( event , context , callback ) => {
351
- if ( ! this . isTracingEnabled ( ) ) {
352
- return originalMethod . apply ( target , [ event , context , callback ] ) ;
350
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
351
+ const tracerRef = this ;
352
+ // Use a function() {} instead of an () => {} arrow function so that we can
353
+ // access `myClass` as `this` in a decorated `myClass.myMethod()`.
354
+ descriptor . value = ( function ( this : Handler , event , context , callback ) {
355
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
356
+ const handlerRef : Handler = this ;
357
+
358
+ if ( ! tracerRef . isTracingEnabled ( ) ) {
359
+ return originalMethod . apply ( handlerRef , [ event , context , callback ] ) ;
353
360
}
354
361
355
- return this . provider . captureAsyncFunc ( `## ${ process . env . _HANDLER } ` , async subsegment => {
356
- this . annotateColdStart ( ) ;
357
- this . addServiceNameAnnotation ( ) ;
362
+ return tracerRef . provider . captureAsyncFunc ( `## ${ process . env . _HANDLER } ` , async subsegment => {
363
+ tracerRef . annotateColdStart ( ) ;
364
+ tracerRef . addServiceNameAnnotation ( ) ;
358
365
let result : unknown ;
359
366
try {
360
- result = await originalMethod . apply ( target , [ event , context , callback ] ) ;
361
- this . addResponseAsMetadata ( result , process . env . _HANDLER ) ;
367
+ result = await originalMethod . apply ( handlerRef , [ event , context , callback ] ) ;
368
+ tracerRef . addResponseAsMetadata ( result , process . env . _HANDLER ) ;
362
369
} catch ( error ) {
363
- this . addErrorAsMetadata ( error as Error ) ;
370
+ tracerRef . addErrorAsMetadata ( error as Error ) ;
364
371
throw error ;
365
372
} finally {
366
373
subsegment ?. close ( ) ;
@@ -369,7 +376,7 @@ class Tracer extends Utility implements TracerInterface {
369
376
370
377
return result ;
371
378
} ) ;
372
- } ) as Handler ;
379
+ } ) as SyncHandler < Handler > | AsyncHandler < Handler > ;
373
380
374
381
return descriptor ;
375
382
} ;
@@ -411,23 +418,27 @@ class Tracer extends Utility implements TracerInterface {
411
418
* @decorator Class
412
419
*/
413
420
public captureMethod ( ) : MethodDecorator {
414
- return ( target , _propertyKey , descriptor ) => {
421
+ return ( _target , _propertyKey , descriptor ) => {
415
422
// The descriptor.value is the method this decorator decorates, it cannot be undefined.
416
423
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
417
424
const originalMethod = descriptor . value ! ;
418
425
419
- descriptor . value = ( ...args : unknown [ ] ) => {
420
- if ( ! this . isTracingEnabled ( ) ) {
421
- return originalMethod . apply ( target , [ ...args ] ) ;
426
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
427
+ const tracerRef = this ;
428
+ // Use a function() {} instead of an () => {} arrow function so that we can
429
+ // access `myClass` as `this` in a decorated `myClass.myMethod()`.
430
+ descriptor . value = function ( ...args : unknown [ ] ) {
431
+ if ( ! tracerRef . isTracingEnabled ( ) ) {
432
+ return originalMethod . apply ( this , [ ...args ] ) ;
422
433
}
423
434
424
- return this . provider . captureAsyncFunc ( `### ${ originalMethod . name } ` , async subsegment => {
435
+ return tracerRef . provider . captureAsyncFunc ( `### ${ originalMethod . name } ` , async subsegment => {
425
436
let result ;
426
437
try {
427
- result = await originalMethod . apply ( target , [ ...args ] ) ;
428
- this . addResponseAsMetadata ( result , originalMethod . name ) ;
438
+ result = await originalMethod . apply ( this , [ ...args ] ) ;
439
+ tracerRef . addResponseAsMetadata ( result , originalMethod . name ) ;
429
440
} catch ( error ) {
430
- this . addErrorAsMetadata ( error as Error ) ;
441
+ tracerRef . addErrorAsMetadata ( error as Error ) ;
431
442
432
443
throw error ;
433
444
} finally {
0 commit comments