11import { Handler } from 'aws-lambda' ;
2- import { Utility } from '@aws-lambda-powertools/commons' ;
2+ import { AsyncHandler , SyncHandler , Utility } from '@aws-lambda-powertools/commons' ;
33import { TracerInterface } from '.' ;
44import { ConfigServiceInterface , EnvironmentVariablesService } from './config' ;
55import { HandlerMethodDecorator , TracerOptions , MethodDecorator } from './types' ;
@@ -67,7 +67,7 @@ import { Segment, Subsegment } from 'aws-xray-sdk-core';
6767 * }
6868 *
6969 * export const handlerClass = new Lambda();
70- * export const handler = handlerClass.handler;
70+ * export const handler = handlerClass.handler.bind(handlerClass);
7171 * ```
7272 *
7373 * ### Functions usage with manual instrumentation
@@ -334,33 +334,40 @@ class Tracer extends Utility implements TracerInterface {
334334 * }
335335 *
336336 * export const handlerClass = new Lambda();
337- * export const handler = handlerClass.handler;
337+ * export const handler = handlerClass.handler.bind(handlerClass);
338338 * ```
339339 *
340340 * @decorator Class
341341 */
342342 public captureLambdaHandler ( ) : HandlerMethodDecorator {
343- return ( target , _propertyKey , descriptor ) => {
343+ return ( _target , _propertyKey , descriptor ) => {
344344 /**
345345 * The descriptor.value is the method this decorator decorates, it cannot be undefined.
346346 */
347347 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
348348 const originalMethod = descriptor . value ! ;
349349
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 ] ) ;
353360 }
354361
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 ( ) ;
358365 let result : unknown ;
359366 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 ) ;
362369 } catch ( error ) {
363- this . addErrorAsMetadata ( error as Error ) ;
370+ tracerRef . addErrorAsMetadata ( error as Error ) ;
364371 throw error ;
365372 } finally {
366373 subsegment ?. close ( ) ;
@@ -369,7 +376,7 @@ class Tracer extends Utility implements TracerInterface {
369376
370377 return result ;
371378 } ) ;
372- } ) as Handler ;
379+ } ) as SyncHandler < Handler > | AsyncHandler < Handler > ;
373380
374381 return descriptor ;
375382 } ;
@@ -411,23 +418,27 @@ class Tracer extends Utility implements TracerInterface {
411418 * @decorator Class
412419 */
413420 public captureMethod ( ) : MethodDecorator {
414- return ( target , _propertyKey , descriptor ) => {
421+ return ( _target , _propertyKey , descriptor ) => {
415422 // The descriptor.value is the method this decorator decorates, it cannot be undefined.
416423 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
417424 const originalMethod = descriptor . value ! ;
418425
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 ] ) ;
422433 }
423434
424- return this . provider . captureAsyncFunc ( `### ${ originalMethod . name } ` , async subsegment => {
435+ return tracerRef . provider . captureAsyncFunc ( `### ${ originalMethod . name } ` , async subsegment => {
425436 let result ;
426437 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 ) ;
429440 } catch ( error ) {
430- this . addErrorAsMetadata ( error as Error ) ;
441+ tracerRef . addErrorAsMetadata ( error as Error ) ;
431442
432443 throw error ;
433444 } finally {
0 commit comments