@@ -226,12 +226,19 @@ def patch(self, modules: Tuple[str] = None):
226226 else :
227227 aws_xray_sdk .core .patch (modules )
228228
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 ):
230230 """Decorator to create subsegment for lambda handlers
231231
232232 As Lambda follows (event, context) signature we can remove some of the boilerplate
233233 and also capture any exception any Lambda function throws or its response as metadata
234234
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+
235242 Example
236243 -------
237244 **Lambda function using capture_lambda_handler decorator**
@@ -241,16 +248,24 @@ def capture_lambda_handler(self, lambda_handler: Callable[[Dict, Any], Any] = No
241248 def handler(event, context):
242249 ...
243250
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+ ...
248257
249258 Raises
250259 ------
251260 err
252261 Exception raised by method
253262 """
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+
254269 lambda_handler_name = lambda_handler .__name__
255270
256271 @functools .wraps (lambda_handler )
@@ -268,7 +283,10 @@ def decorate(event, context):
268283 logger .debug ("Received lambda handler response successfully" )
269284 logger .debug (response )
270285 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 ,
272290 )
273291 except Exception as err :
274292 logger .exception (f"Exception received from { lambda_handler_name } " )
@@ -281,7 +299,7 @@ def decorate(event, context):
281299
282300 return decorate
283301
284- def capture_method (self , method : Callable = None ):
302+ def capture_method (self , method : Callable = None , capture_response : bool = True ):
285303 """Decorator to create subsegment for arbitrary functions
286304
287305 It also captures both response and exceptions as metadata
@@ -295,6 +313,13 @@ def capture_method(self, method: Callable = None):
295313 `async.gather` is called, or use `in_subsegment_async`
296314 context manager via our escape hatch mechanism - See examples.
297315
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+
298323 Example
299324 -------
300325 **Custom function using capture_method decorator**
@@ -416,29 +441,31 @@ async def async_tasks():
416441
417442 return { "task": "done", **ret }
418443
419- Parameters
420- ----------
421- method : Callable
422- Method to annotate on
423-
424444 Raises
425445 ------
426446 err
427447 Exception raised by method
428448 """
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 )
429454
430455 if inspect .iscoroutinefunction (method ):
431- decorate = self ._decorate_async_function (method = method )
456+ decorate = self ._decorate_async_function (method = method , capture_response = capture_response )
432457 elif inspect .isgeneratorfunction (method ):
433- decorate = self ._decorate_generator_function (method = method )
458+ decorate = self ._decorate_generator_function (method = method , capture_response = capture_response )
434459 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+ )
436463 else :
437- decorate = self ._decorate_sync_function (method = method )
464+ decorate = self ._decorate_sync_function (method = method , capture_response = capture_response )
438465
439466 return decorate
440467
441- def _decorate_async_function (self , method : Callable = None ):
468+ def _decorate_async_function (self , method : Callable = None , capture_response : bool = True ):
442469 method_name = f"{ method .__name__ } "
443470
444471 @functools .wraps (method )
@@ -447,7 +474,12 @@ async def decorate(*args, **kwargs):
447474 try :
448475 logger .debug (f"Calling method: { method_name } " )
449476 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+ )
451483 except Exception as err :
452484 logger .exception (f"Exception received from '{ method_name } ' method" )
453485 self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -457,7 +489,7 @@ async def decorate(*args, **kwargs):
457489
458490 return decorate
459491
460- def _decorate_generator_function (self , method : Callable = None ):
492+ def _decorate_generator_function (self , method : Callable = None , capture_response : bool = True ):
461493 method_name = f"{ method .__name__ } "
462494
463495 @functools .wraps (method )
@@ -466,7 +498,9 @@ def decorate(*args, **kwargs):
466498 try :
467499 logger .debug (f"Calling method: { method_name } " )
468500 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+ )
470504 except Exception as err :
471505 logger .exception (f"Exception received from '{ method_name } ' method" )
472506 self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -476,7 +510,7 @@ def decorate(*args, **kwargs):
476510
477511 return decorate
478512
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 ):
480514 method_name = f"{ method .__name__ } "
481515
482516 @functools .wraps (method )
@@ -488,15 +522,17 @@ def decorate(*args, **kwargs):
488522 with method (* args , ** kwargs ) as return_val :
489523 result = return_val
490524 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+ )
492528 except Exception as err :
493529 logger .exception (f"Exception received from '{ method_name } ' method" )
494530 self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
495531 raise
496532
497533 return decorate
498534
499- def _decorate_sync_function (self , method : Callable = None ):
535+ def _decorate_sync_function (self , method : Callable = None , capture_response : bool = True ):
500536 method_name = f"{ method .__name__ } "
501537
502538 @functools .wraps (method )
@@ -505,7 +541,12 @@ def decorate(*args, **kwargs):
505541 try :
506542 logger .debug (f"Calling method: { method_name } " )
507543 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+ )
509550 except Exception as err :
510551 logger .exception (f"Exception received from '{ method_name } ' method" )
511552 self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
@@ -516,7 +557,11 @@ def decorate(*args, **kwargs):
516557 return decorate
517558
518559 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 ,
520565 ):
521566 """Add response as metadata for given subsegment
522567
@@ -528,8 +573,10 @@ def _add_response_as_metadata(
528573 data to add as subsegment metadata, by default None
529574 subsegment : aws_xray_sdk.core.models.subsegment, optional
530575 existing subsegment to add metadata on, by default None
576+ capture_response : bool, optional
577+ Do not include response as metadata, by default True
531578 """
532- if data is None or subsegment is None :
579+ if data is None or not capture_response or subsegment is None :
533580 return
534581
535582 subsegment .put_metadata (key = f"{ function_name } response" , value = data , namespace = self ._config ["service" ])
0 commit comments