@@ -226,12 +226,19 @@ def patch(self, modules: Tuple[str] = None):
226
226
else :
227
227
aws_xray_sdk .core .patch (modules )
228
228
229
- def capture_lambda_handler (self , lambda_handler : Callable [[Dict , Any ], Any ] = None ):
229
+ def capture_lambda_handler (self , lambda_handler : Callable [[Dict , Any ], Any ] = None , capture_response : bool = True ):
230
230
"""Decorator to create subsegment for lambda handlers
231
231
232
232
As Lambda follows (event, context) signature we can remove some of the boilerplate
233
233
and also capture any exception any Lambda function throws or its response as metadata
234
234
235
+ Parameters
236
+ ----------
237
+ lambda_handler : Callable
238
+ Method to annotate on
239
+ capture_response : bool, optional
240
+ Instructs tracer to not include handler's response as metadata, by default True
241
+
235
242
Example
236
243
-------
237
244
**Lambda function using capture_lambda_handler decorator**
@@ -241,16 +248,24 @@ def capture_lambda_handler(self, lambda_handler: Callable[[Dict, Any], Any] = No
241
248
def handler(event, context):
242
249
...
243
250
244
- Parameters
245
- ----------
246
- method : Callable
247
- Method to annotate on
251
+ **Preventing Tracer to log response as metadata**
252
+
253
+ tracer = Tracer(service="payment")
254
+ @tracer.capture_lambda_handler(capture_response=False)
255
+ def handler(event, context):
256
+ ...
248
257
249
258
Raises
250
259
------
251
260
err
252
261
Exception raised by method
253
262
"""
263
+ # If handler is None we've been called with parameters
264
+ # Return a partial function with args filled
265
+ if lambda_handler is None :
266
+ logger .debug ("Decorator called with parameters" )
267
+ return functools .partial (self .capture_lambda_handler , capture_response = capture_response )
268
+
254
269
lambda_handler_name = lambda_handler .__name__
255
270
256
271
@functools .wraps (lambda_handler )
@@ -268,7 +283,10 @@ def decorate(event, context):
268
283
logger .debug ("Received lambda handler response successfully" )
269
284
logger .debug (response )
270
285
self ._add_response_as_metadata (
271
- function_name = lambda_handler_name , data = response , subsegment = subsegment
286
+ function_name = lambda_handler_name ,
287
+ data = response ,
288
+ subsegment = subsegment ,
289
+ capture_response = capture_response ,
272
290
)
273
291
except Exception as err :
274
292
logger .exception (f"Exception received from { lambda_handler_name } " )
@@ -281,7 +299,7 @@ def decorate(event, context):
281
299
282
300
return decorate
283
301
284
- def capture_method (self , method : Callable = None ):
302
+ def capture_method (self , method : Callable = None , capture_response : bool = True ):
285
303
"""Decorator to create subsegment for arbitrary functions
286
304
287
305
It also captures both response and exceptions as metadata
@@ -295,6 +313,13 @@ def capture_method(self, method: Callable = None):
295
313
`async.gather` is called, or use `in_subsegment_async`
296
314
context manager via our escape hatch mechanism - See examples.
297
315
316
+ Parameters
317
+ ----------
318
+ method : Callable
319
+ Method to annotate on
320
+ capture_response : bool, optional
321
+ Instructs tracer to not include method's response as metadata, by default True
322
+
298
323
Example
299
324
-------
300
325
**Custom function using capture_method decorator**
@@ -416,29 +441,31 @@ async def async_tasks():
416
441
417
442
return { "task": "done", **ret }
418
443
419
- Parameters
420
- ----------
421
- method : Callable
422
- Method to annotate on
423
-
424
444
Raises
425
445
------
426
446
err
427
447
Exception raised by method
428
448
"""
449
+ # If method is None we've been called with parameters
450
+ # Return a partial function with args filled
451
+ if method is None :
452
+ logger .debug ("Decorator called with parameters" )
453
+ return functools .partial (self .capture_method , capture_response = capture_response )
429
454
430
455
if inspect .iscoroutinefunction (method ):
431
- decorate = self ._decorate_async_function (method = method )
456
+ decorate = self ._decorate_async_function (method = method , capture_response = capture_response )
432
457
elif inspect .isgeneratorfunction (method ):
433
- decorate = self ._decorate_generator_function (method = method )
458
+ decorate = self ._decorate_generator_function (method = method , capture_response = capture_response )
434
459
elif hasattr (method , "__wrapped__" ) and inspect .isgeneratorfunction (method .__wrapped__ ):
435
- decorate = self ._decorate_generator_function_with_context_manager (method = method )
460
+ decorate = self ._decorate_generator_function_with_context_manager (
461
+ method = method , capture_response = capture_response
462
+ )
436
463
else :
437
- decorate = self ._decorate_sync_function (method = method )
464
+ decorate = self ._decorate_sync_function (method = method , capture_response = capture_response )
438
465
439
466
return decorate
440
467
441
- def _decorate_async_function (self , method : Callable = None ):
468
+ def _decorate_async_function (self , method : Callable = None , capture_response : bool = True ):
442
469
method_name = f"{ method .__name__ } "
443
470
444
471
@functools .wraps (method )
@@ -447,7 +474,12 @@ async def decorate(*args, **kwargs):
447
474
try :
448
475
logger .debug (f"Calling method: { method_name } " )
449
476
response = await method (* args , ** kwargs )
450
- self ._add_response_as_metadata (function_name = method_name , data = response , subsegment = subsegment )
477
+ self ._add_response_as_metadata (
478
+ function_name = method_name ,
479
+ data = response ,
480
+ subsegment = subsegment ,
481
+ capture_response = capture_response ,
482
+ )
451
483
except Exception as err :
452
484
logger .exception (f"Exception received from '{ method_name } ' method" )
453
485
self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -457,7 +489,7 @@ async def decorate(*args, **kwargs):
457
489
458
490
return decorate
459
491
460
- def _decorate_generator_function (self , method : Callable = None ):
492
+ def _decorate_generator_function (self , method : Callable = None , capture_response : bool = True ):
461
493
method_name = f"{ method .__name__ } "
462
494
463
495
@functools .wraps (method )
@@ -466,7 +498,9 @@ def decorate(*args, **kwargs):
466
498
try :
467
499
logger .debug (f"Calling method: { method_name } " )
468
500
result = yield from method (* args , ** kwargs )
469
- self ._add_response_as_metadata (function_name = method_name , data = result , subsegment = subsegment )
501
+ self ._add_response_as_metadata (
502
+ function_name = method_name , data = result , subsegment = subsegment , capture_response = capture_response
503
+ )
470
504
except Exception as err :
471
505
logger .exception (f"Exception received from '{ method_name } ' method" )
472
506
self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -476,7 +510,7 @@ def decorate(*args, **kwargs):
476
510
477
511
return decorate
478
512
479
- def _decorate_generator_function_with_context_manager (self , method : Callable = None ):
513
+ def _decorate_generator_function_with_context_manager (self , method : Callable = None , capture_response : bool = True ):
480
514
method_name = f"{ method .__name__ } "
481
515
482
516
@functools .wraps (method )
@@ -488,15 +522,17 @@ def decorate(*args, **kwargs):
488
522
with method (* args , ** kwargs ) as return_val :
489
523
result = return_val
490
524
yield result
491
- self ._add_response_as_metadata (function_name = method_name , data = result , subsegment = subsegment )
525
+ self ._add_response_as_metadata (
526
+ function_name = method_name , data = result , subsegment = subsegment , capture_response = capture_response
527
+ )
492
528
except Exception as err :
493
529
logger .exception (f"Exception received from '{ method_name } ' method" )
494
530
self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
495
531
raise
496
532
497
533
return decorate
498
534
499
- def _decorate_sync_function (self , method : Callable = None ):
535
+ def _decorate_sync_function (self , method : Callable = None , capture_response : bool = True ):
500
536
method_name = f"{ method .__name__ } "
501
537
502
538
@functools .wraps (method )
@@ -505,7 +541,12 @@ def decorate(*args, **kwargs):
505
541
try :
506
542
logger .debug (f"Calling method: { method_name } " )
507
543
response = method (* args , ** kwargs )
508
- self ._add_response_as_metadata (function_name = method_name , data = response , subsegment = subsegment )
544
+ self ._add_response_as_metadata (
545
+ function_name = method_name ,
546
+ data = response ,
547
+ subsegment = subsegment ,
548
+ capture_response = capture_response ,
549
+ )
509
550
except Exception as err :
510
551
logger .exception (f"Exception received from '{ method_name } ' method" )
511
552
self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -516,7 +557,11 @@ def decorate(*args, **kwargs):
516
557
return decorate
517
558
518
559
def _add_response_as_metadata (
519
- self , function_name : str = None , data : Any = None , subsegment : aws_xray_sdk .core .models .subsegment = None
560
+ self ,
561
+ function_name : str = None ,
562
+ data : Any = None ,
563
+ subsegment : aws_xray_sdk .core .models .subsegment = None ,
564
+ capture_response : bool = True ,
520
565
):
521
566
"""Add response as metadata for given subsegment
522
567
@@ -528,8 +573,10 @@ def _add_response_as_metadata(
528
573
data to add as subsegment metadata, by default None
529
574
subsegment : aws_xray_sdk.core.models.subsegment, optional
530
575
existing subsegment to add metadata on, by default None
576
+ capture_response : bool, optional
577
+ Do not include response as metadata, by default True
531
578
"""
532
- if data is None or subsegment is None :
579
+ if data is None or not capture_response or subsegment is None :
533
580
return
534
581
535
582
subsegment .put_metadata (key = f"{ function_name } response" , value = data , namespace = self ._config ["service" ])
0 commit comments