@@ -150,27 +150,27 @@ def __init__(
150150 self .auto_patch = self ._config ["auto_patch" ]
151151
152152 if self .disabled :
153- self .__disable_tracing_provider ()
153+ self ._disable_tracer_provider ()
154154
155155 if self .auto_patch :
156156 self .patch (modules = patch_modules )
157157
158158 def put_annotation (self , key : str , value : Any ):
159159 """Adds annotation to existing segment or subsegment
160160
161+ Parameters
162+ ----------
163+ key : str
164+ Annotation key
165+ value : any
166+ Value for annotation
167+
161168 Example
162169 -------
163170 Custom annotation for a pseudo service named payment
164171
165172 tracer = Tracer(service="payment")
166173 tracer.put_annotation("PaymentStatus", "CONFIRMED")
167-
168- Parameters
169- ----------
170- key : str
171- Annotation key (e.g. PaymentStatus)
172- value : any
173- Value for annotation (e.g. "CONFIRMED")
174174 """
175175 if self .disabled :
176176 logger .debug ("Tracing has been disabled, aborting put_annotation" )
@@ -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 )
@@ -266,22 +281,24 @@ def decorate(event, context):
266281 logger .debug ("Calling lambda handler" )
267282 response = lambda_handler (event , context )
268283 logger .debug ("Received lambda handler response successfully" )
269- logger .debug (response )
270284 self ._add_response_as_metadata (
271- function_name = lambda_handler_name , data = response , subsegment = subsegment
285+ method_name = lambda_handler_name ,
286+ data = response ,
287+ subsegment = subsegment ,
288+ capture_response = capture_response ,
272289 )
273290 except Exception as err :
274291 logger .exception (f"Exception received from { lambda_handler_name } " )
275292 self ._add_full_exception_as_metadata (
276- function_name = lambda_handler_name , error = err , subsegment = subsegment
293+ method_name = lambda_handler_name , error = err , subsegment = subsegment
277294 )
278295 raise
279296
280297 return response
281298
282299 return decorate
283300
284- def capture_method (self , method : Callable = None ):
301+ def capture_method (self , method : Callable = None , capture_response : bool = True ):
285302 """Decorator to create subsegment for arbitrary functions
286303
287304 It also captures both response and exceptions as metadata
@@ -295,6 +312,13 @@ def capture_method(self, method: Callable = None):
295312 `async.gather` is called, or use `in_subsegment_async`
296313 context manager via our escape hatch mechanism - See examples.
297314
315+ Parameters
316+ ----------
317+ method : Callable
318+ Method to annotate on
319+ capture_response : bool, optional
320+ Instructs tracer to not include method's response as metadata, by default True
321+
298322 Example
299323 -------
300324 **Custom function using capture_method decorator**
@@ -416,69 +440,84 @@ async def async_tasks():
416440
417441 return { "task": "done", **ret }
418442
419- Parameters
420- ----------
421- method : Callable
422- Method to annotate on
423-
424443 Raises
425444 ------
426445 err
427446 Exception raised by method
428447 """
448+ # If method is None we've been called with parameters
449+ # Return a partial function with args filled
450+ if method is None :
451+ logger .debug ("Decorator called with parameters" )
452+ return functools .partial (self .capture_method , capture_response = capture_response )
453+
454+ method_name = f"{ method .__name__ } "
429455
430456 if inspect .iscoroutinefunction (method ):
431- decorate = self ._decorate_async_function (method = method )
457+ decorate = self ._decorate_async_function (
458+ method = method , capture_response = capture_response , method_name = method_name
459+ )
432460 elif inspect .isgeneratorfunction (method ):
433- decorate = self ._decorate_generator_function (method = method )
461+ decorate = self ._decorate_generator_function (
462+ method = method , capture_response = capture_response , method_name = method_name
463+ )
434464 elif hasattr (method , "__wrapped__" ) and inspect .isgeneratorfunction (method .__wrapped__ ):
435- decorate = self ._decorate_generator_function_with_context_manager (method = method )
465+ decorate = self ._decorate_generator_function_with_context_manager (
466+ method = method , capture_response = capture_response , method_name = method_name
467+ )
436468 else :
437- decorate = self ._decorate_sync_function (method = method )
469+ decorate = self ._decorate_sync_function (
470+ method = method , capture_response = capture_response , method_name = method_name
471+ )
438472
439473 return decorate
440474
441- def _decorate_async_function (self , method : Callable = None ):
442- method_name = f"{ method .__name__ } "
443-
475+ def _decorate_async_function (self , method : Callable = None , capture_response : bool = True , method_name : str = None ):
444476 @functools .wraps (method )
445477 async def decorate (* args , ** kwargs ):
446478 async with self .provider .in_subsegment_async (name = f"## { method_name } " ) as subsegment :
447479 try :
448480 logger .debug (f"Calling method: { method_name } " )
449481 response = await method (* args , ** kwargs )
450- self ._add_response_as_metadata (function_name = method_name , data = response , subsegment = subsegment )
482+ self ._add_response_as_metadata (
483+ method_name = method_name ,
484+ data = response ,
485+ subsegment = subsegment ,
486+ capture_response = capture_response ,
487+ )
451488 except Exception as err :
452489 logger .exception (f"Exception received from '{ method_name } ' method" )
453- self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
490+ self ._add_full_exception_as_metadata (method_name = method_name , error = err , subsegment = subsegment )
454491 raise
455492
456493 return response
457494
458495 return decorate
459496
460- def _decorate_generator_function (self , method : Callable = None ):
461- method_name = f" { method . __name__ } "
462-
497+ def _decorate_generator_function (
498+ self , method : Callable = None , capture_response : bool = True , method_name : str = None
499+ ):
463500 @functools .wraps (method )
464501 def decorate (* args , ** kwargs ):
465502 with self .provider .in_subsegment (name = f"## { method_name } " ) as subsegment :
466503 try :
467504 logger .debug (f"Calling method: { method_name } " )
468505 result = yield from method (* args , ** kwargs )
469- self ._add_response_as_metadata (function_name = method_name , data = result , subsegment = subsegment )
506+ self ._add_response_as_metadata (
507+ method_name = method_name , data = result , subsegment = subsegment , capture_response = capture_response
508+ )
470509 except Exception as err :
471510 logger .exception (f"Exception received from '{ method_name } ' method" )
472- self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
511+ self ._add_full_exception_as_metadata (method_name = method_name , error = err , subsegment = subsegment )
473512 raise
474513
475514 return result
476515
477516 return decorate
478517
479- def _decorate_generator_function_with_context_manager (self , method : Callable = None ):
480- method_name = f" { method . __name__ } "
481-
518+ def _decorate_generator_function_with_context_manager (
519+ self , method : Callable = None , capture_response : bool = True , method_name : str = None
520+ ):
482521 @functools .wraps (method )
483522 @contextlib .contextmanager
484523 def decorate (* args , ** kwargs ):
@@ -488,74 +527,87 @@ def decorate(*args, **kwargs):
488527 with method (* args , ** kwargs ) as return_val :
489528 result = return_val
490529 yield result
491- self ._add_response_as_metadata (function_name = method_name , data = result , subsegment = subsegment )
530+ self ._add_response_as_metadata (
531+ method_name = method_name , data = result , subsegment = subsegment , capture_response = capture_response
532+ )
492533 except Exception as err :
493534 logger .exception (f"Exception received from '{ method_name } ' method" )
494- self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
535+ self ._add_full_exception_as_metadata (method_name = method_name , error = err , subsegment = subsegment )
495536 raise
496537
497538 return decorate
498539
499- def _decorate_sync_function (self , method : Callable = None ):
500- method_name = f"{ method .__name__ } "
501-
540+ def _decorate_sync_function (self , method : Callable = None , capture_response : bool = True , method_name : str = None ):
502541 @functools .wraps (method )
503542 def decorate (* args , ** kwargs ):
504543 with self .provider .in_subsegment (name = f"## { method_name } " ) as subsegment :
505544 try :
506545 logger .debug (f"Calling method: { method_name } " )
507546 response = method (* args , ** kwargs )
508- self ._add_response_as_metadata (function_name = method_name , data = response , subsegment = subsegment )
547+ self ._add_response_as_metadata (
548+ method_name = method_name ,
549+ data = response ,
550+ subsegment = subsegment ,
551+ capture_response = capture_response ,
552+ )
509553 except Exception as err :
510554 logger .exception (f"Exception received from '{ method_name } ' method" )
511- self ._add_full_exception_as_metadata (function_name = method_name , error = err , subsegment = subsegment )
555+ self ._add_full_exception_as_metadata (method_name = method_name , error = err , subsegment = subsegment )
512556 raise
513557
514558 return response
515559
516560 return decorate
517561
518562 def _add_response_as_metadata (
519- self , function_name : str = None , data : Any = None , subsegment : aws_xray_sdk .core .models .subsegment = None
563+ self ,
564+ method_name : str = None ,
565+ data : Any = None ,
566+ subsegment : aws_xray_sdk .core .models .subsegment = None ,
567+ capture_response : bool = True ,
520568 ):
521569 """Add response as metadata for given subsegment
522570
523571 Parameters
524572 ----------
525- function_name : str, optional
526- function name to add as metadata key, by default None
573+ method_name : str, optional
574+ method name to add as metadata key, by default None
527575 data : Any, optional
528576 data to add as subsegment metadata, by default None
529577 subsegment : aws_xray_sdk.core.models.subsegment, optional
530578 existing subsegment to add metadata on, by default None
579+ capture_response : bool, optional
580+ Do not include response as metadata, by default True
531581 """
532- if data is None or subsegment is None :
582+ if data is None or not capture_response or subsegment is None :
533583 return
534584
535- subsegment .put_metadata (key = f"{ function_name } response" , value = data , namespace = self ._config ["service" ])
585+ subsegment .put_metadata (key = f"{ method_name } response" , value = data , namespace = self ._config ["service" ])
536586
537587 def _add_full_exception_as_metadata (
538- self , function_name : str = None , error : Exception = None , subsegment : aws_xray_sdk .core .models .subsegment = None
588+ self , method_name : str = None , error : Exception = None , subsegment : aws_xray_sdk .core .models .subsegment = None
539589 ):
540590 """Add full exception object as metadata for given subsegment
541591
542592 Parameters
543593 ----------
544- function_name : str, optional
545- function name to add as metadata key, by default None
594+ method_name : str, optional
595+ method name to add as metadata key, by default None
546596 error : Exception, optional
547597 error to add as subsegment metadata, by default None
548598 subsegment : aws_xray_sdk.core.models.subsegment, optional
549599 existing subsegment to add metadata on, by default None
550600 """
551- subsegment .put_metadata (key = f"{ function_name } error" , value = error , namespace = self ._config ["service" ])
601+ subsegment .put_metadata (key = f"{ method_name } error" , value = error , namespace = self ._config ["service" ])
552602
553- def __disable_tracing_provider (self ):
603+ @staticmethod
604+ def _disable_tracer_provider ():
554605 """Forcefully disables tracing"""
555606 logger .debug ("Disabling tracer provider..." )
556607 aws_xray_sdk .global_sdk_config .set_sdk_enabled (False )
557608
558- def __is_trace_disabled (self ) -> bool :
609+ @staticmethod
610+ def _is_tracer_disabled () -> bool :
559611 """Detects whether trace has been disabled
560612
561613 Tracing is automatically disabled in the following conditions:
@@ -592,7 +644,7 @@ def __build_config(
592644 provider : aws_xray_sdk .core .xray_recorder = None ,
593645 ):
594646 """ Populates Tracer config for new and existing initializations """
595- is_disabled = disabled if disabled is not None else self .__is_trace_disabled ()
647+ is_disabled = disabled if disabled is not None else self ._is_tracer_disabled ()
596648 is_service = service if service is not None else os .getenv ("POWERTOOLS_SERVICE_NAME" )
597649
598650 self ._config ["provider" ] = provider if provider is not None else self ._config ["provider" ]
0 commit comments