From 8ab35071da8147f8ee8733849cc6a184bb824e82 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 12 Jan 2021 18:26:08 +0100 Subject: [PATCH 1/5] improv: add capture_response/error env vars --- aws_lambda_powertools/tracing/tracer.py | 100 ++++++++++++++++++------ 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/aws_lambda_powertools/tracing/tracer.py b/aws_lambda_powertools/tracing/tracer.py index 079f662a9ad..49fe20d4ead 100644 --- a/aws_lambda_powertools/tracing/tracer.py +++ b/aws_lambda_powertools/tracing/tracer.py @@ -34,6 +34,10 @@ class Tracer: disable tracer (e.g. `"true", "True", "TRUE"`) POWERTOOLS_SERVICE_NAME : str service name + POWERTOOLS_TRACER_CAPTURE_RESPONSE : str + disable auto-capture response as metadata (e.g. `"true", "True", "TRUE"`) + POWERTOOLS_TRACER_CAPTURE_ERROR : str + disable auto-capture error as metadata (e.g. `"true", "True", "TRUE"`) Parameters ---------- @@ -226,7 +230,12 @@ def patch(self, modules: Tuple[str] = None): else: aws_xray_sdk.core.patch(modules) - def capture_lambda_handler(self, lambda_handler: Callable[[Dict, Any], Any] = None, capture_response: bool = True): + def capture_lambda_handler( + self, + lambda_handler: Callable[[Dict, Any], Any] = None, + capture_response: bool = True, + capture_error: bool = True, + ): """Decorator to create subsegment for lambda handlers As Lambda follows (event, context) signature we can remove some of the boilerplate @@ -238,6 +247,8 @@ def capture_lambda_handler(self, lambda_handler: Callable[[Dict, Any], Any] = No Method to annotate on capture_response : bool, optional Instructs tracer to not include handler's response as metadata, by default True + capture_error : bool, optional + Instructs tracer to not include handler's error as metadata, by default True Example ------- @@ -264,10 +275,17 @@ def handler(event, context): # Return a partial function with args filled if lambda_handler is None: logger.debug("Decorator called with parameters") - return functools.partial(self.capture_lambda_handler, capture_response=capture_response) + return functools.partial( + self.capture_lambda_handler, capture_response=capture_response, capture_error=capture_error + ) lambda_handler_name = lambda_handler.__name__ + capture_response_env_option = str(os.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE", "false")) + capture_error_env_option = str(os.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR", "false")) + capture_response = strtobool(capture_response_env_option) or capture_response + capture_error = strtobool(capture_error_env_option) or capture_error + @functools.wraps(lambda_handler) def decorate(event, context): with self.provider.in_subsegment(name=f"## {lambda_handler_name}") as subsegment: @@ -290,7 +308,7 @@ def decorate(event, context): except Exception as err: logger.exception(f"Exception received from {lambda_handler_name}") self._add_full_exception_as_metadata( - method_name=lambda_handler_name, error=err, subsegment=subsegment + method_name=lambda_handler_name, error=err, subsegment=subsegment, capture_error=capture_error ) raise @@ -298,7 +316,7 @@ def decorate(event, context): return decorate - def capture_method(self, method: Callable = None, capture_response: bool = True): + def capture_method(self, method: Callable = None, capture_response: bool = True, capture_error: bool = True): """Decorator to create subsegment for arbitrary functions It also captures both response and exceptions as metadata @@ -318,6 +336,8 @@ def capture_method(self, method: Callable = None, capture_response: bool = True) Method to annotate on capture_response : bool, optional Instructs tracer to not include method's response as metadata, by default True + capture_error : bool, optional + Instructs tracer to not include handler's error as metadata, by default True Example ------- @@ -449,28 +469,36 @@ async def async_tasks(): # Return a partial function with args filled if method is None: logger.debug("Decorator called with parameters") - return functools.partial(self.capture_method, capture_response=capture_response) + return functools.partial( + self.capture_method, capture_response=capture_response, capture_error=capture_error + ) method_name = f"{method.__name__}" if inspect.iscoroutinefunction(method): return self._decorate_async_function( - method=method, capture_response=capture_response, method_name=method_name + method=method, capture_response=capture_response, capture_error=True, method_name=method_name ) elif inspect.isgeneratorfunction(method): return self._decorate_generator_function( - method=method, capture_response=capture_response, method_name=method_name + method=method, capture_response=capture_response, capture_error=True, method_name=method_name ) elif hasattr(method, "__wrapped__") and inspect.isgeneratorfunction(method.__wrapped__): return self._decorate_generator_function_with_context_manager( - method=method, capture_response=capture_response, method_name=method_name + method=method, capture_response=capture_response, capture_error=True, method_name=method_name ) else: return self._decorate_sync_function( - method=method, capture_response=capture_response, method_name=method_name + method=method, capture_response=capture_response, capture_error=True, method_name=method_name ) - def _decorate_async_function(self, method: Callable = None, capture_response: bool = True, method_name: str = None): + def _decorate_async_function( + self, + method: Callable = None, + capture_response: bool = True, + capture_error: bool = True, + method_name: str = None, + ): @functools.wraps(method) async def decorate(*args, **kwargs): async with self.provider.in_subsegment_async(name=f"## {method_name}") as subsegment: @@ -478,14 +506,13 @@ async def decorate(*args, **kwargs): logger.debug(f"Calling method: {method_name}") response = await method(*args, **kwargs) self._add_response_as_metadata( - method_name=method_name, - data=response, - subsegment=subsegment, - capture_response=capture_response, + method_name=method_name, data=response, subsegment=subsegment, capture_response=capture_response ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") - self._add_full_exception_as_metadata(method_name=method_name, error=err, subsegment=subsegment) + self._add_full_exception_as_metadata( + method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + ) raise return response @@ -493,7 +520,11 @@ async def decorate(*args, **kwargs): return decorate def _decorate_generator_function( - self, method: Callable = None, capture_response: bool = True, method_name: str = None + self, + method: Callable = None, + capture_response: bool = True, + capture_error: bool = True, + method_name: str = None, ): @functools.wraps(method) def decorate(*args, **kwargs): @@ -506,7 +537,9 @@ def decorate(*args, **kwargs): ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") - self._add_full_exception_as_metadata(method_name=method_name, error=err, subsegment=subsegment) + self._add_full_exception_as_metadata( + method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + ) raise return result @@ -514,7 +547,11 @@ def decorate(*args, **kwargs): return decorate def _decorate_generator_function_with_context_manager( - self, method: Callable = None, capture_response: bool = True, method_name: str = None + self, + method: Callable = None, + capture_response: bool = True, + capture_error: bool = True, + method_name: str = None, ): @functools.wraps(method) @contextlib.contextmanager @@ -530,12 +567,20 @@ def decorate(*args, **kwargs): ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") - self._add_full_exception_as_metadata(method_name=method_name, error=err, subsegment=subsegment) + self._add_full_exception_as_metadata( + method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + ) raise return decorate - def _decorate_sync_function(self, method: Callable = None, capture_response: bool = True, method_name: str = None): + def _decorate_sync_function( + self, + method: Callable = None, + capture_response: bool = True, + capture_error: bool = True, + method_name: str = None, + ): @functools.wraps(method) def decorate(*args, **kwargs): with self.provider.in_subsegment(name=f"## {method_name}") as subsegment: @@ -550,7 +595,9 @@ def decorate(*args, **kwargs): ) except Exception as err: logger.exception(f"Exception received from '{method_name}' method") - self._add_full_exception_as_metadata(method_name=method_name, error=err, subsegment=subsegment) + self._add_full_exception_as_metadata( + method_name=method_name, error=err, subsegment=subsegment, capture_error=capture_error + ) raise return response @@ -583,7 +630,11 @@ def _add_response_as_metadata( subsegment.put_metadata(key=f"{method_name} response", value=data, namespace=self._config["service"]) def _add_full_exception_as_metadata( - self, method_name: str = None, error: Exception = None, subsegment: aws_xray_sdk.core.models.subsegment = None + self, + method_name: str = None, + error: Exception = None, + subsegment: aws_xray_sdk.core.models.subsegment = None, + capture_error: bool = True, ): """Add full exception object as metadata for given subsegment @@ -595,7 +646,12 @@ def _add_full_exception_as_metadata( error to add as subsegment metadata, by default None subsegment : aws_xray_sdk.core.models.subsegment, optional existing subsegment to add metadata on, by default None + capture_error : bool, optional + Do not include error as metadata, by default True """ + if error is None or not capture_error or subsegment is None: + return + subsegment.put_metadata(key=f"{method_name} error", value=error, namespace=self._config["service"]) @staticmethod From a35976695ffce55e749b20af5b82c5978fdc7d56 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 13 Jan 2021 13:26:49 +0100 Subject: [PATCH 2/5] improv: add tests for capture_response/error env vars --- aws_lambda_powertools/shared/__init__.py | 0 aws_lambda_powertools/shared/constants.py | 4 ++ aws_lambda_powertools/shared/functions.py | 5 ++ aws_lambda_powertools/tracing/tracer.py | 58 +++++++++++++---------- tests/functional/test_shared_functions.py | 11 +++++ tests/unit/test_tracing.py | 8 ++-- 6 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 aws_lambda_powertools/shared/__init__.py create mode 100644 aws_lambda_powertools/shared/constants.py create mode 100644 aws_lambda_powertools/shared/functions.py create mode 100644 tests/functional/test_shared_functions.py diff --git a/aws_lambda_powertools/shared/__init__.py b/aws_lambda_powertools/shared/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/aws_lambda_powertools/shared/constants.py b/aws_lambda_powertools/shared/constants.py new file mode 100644 index 00000000000..a3863c33286 --- /dev/null +++ b/aws_lambda_powertools/shared/constants.py @@ -0,0 +1,4 @@ +import os + +TRACER_CAPTURE_RESPONSE_ENV: str = os.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE", "true") +TRACER_CAPTURE_ERROR_ENV: str = os.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR", "true") diff --git a/aws_lambda_powertools/shared/functions.py b/aws_lambda_powertools/shared/functions.py new file mode 100644 index 00000000000..2a3af7db5f3 --- /dev/null +++ b/aws_lambda_powertools/shared/functions.py @@ -0,0 +1,5 @@ +from distutils.util import strtobool + + +def resolve_env_var_choice(env: str, choice: bool = None) -> bool: + return choice if choice is not None else strtobool(env) diff --git a/aws_lambda_powertools/tracing/tracer.py b/aws_lambda_powertools/tracing/tracer.py index 49fe20d4ead..2e083e5ebab 100644 --- a/aws_lambda_powertools/tracing/tracer.py +++ b/aws_lambda_powertools/tracing/tracer.py @@ -5,11 +5,14 @@ import logging import os from distutils.util import strtobool -from typing import Any, Callable, Dict, List, Tuple +from typing import Any, Callable, Dict, List, Optional, Tuple import aws_xray_sdk import aws_xray_sdk.core +from aws_lambda_powertools.shared.constants import TRACER_CAPTURE_ERROR_ENV, TRACER_CAPTURE_RESPONSE_ENV +from aws_lambda_powertools.shared.functions import resolve_env_var_choice + is_cold_start = True logger = logging.getLogger(__name__) @@ -233,8 +236,8 @@ def patch(self, modules: Tuple[str] = None): def capture_lambda_handler( self, lambda_handler: Callable[[Dict, Any], Any] = None, - capture_response: bool = True, - capture_error: bool = True, + capture_response: Optional[bool] = None, + capture_error: Optional[bool] = None, ): """Decorator to create subsegment for lambda handlers @@ -246,7 +249,7 @@ def capture_lambda_handler( lambda_handler : Callable Method to annotate on capture_response : bool, optional - Instructs tracer to not include handler's response as metadata, by default True + Instructs tracer to not include handler's response as metadata capture_error : bool, optional Instructs tracer to not include handler's error as metadata, by default True @@ -281,10 +284,8 @@ def handler(event, context): lambda_handler_name = lambda_handler.__name__ - capture_response_env_option = str(os.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE", "false")) - capture_error_env_option = str(os.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR", "false")) - capture_response = strtobool(capture_response_env_option) or capture_response - capture_error = strtobool(capture_error_env_option) or capture_error + capture_response = resolve_env_var_choice(env=TRACER_CAPTURE_RESPONSE_ENV, choice=capture_response) + capture_error = resolve_env_var_choice(env=TRACER_CAPTURE_ERROR_ENV, choice=capture_error) @functools.wraps(lambda_handler) def decorate(event, context): @@ -316,7 +317,9 @@ def decorate(event, context): return decorate - def capture_method(self, method: Callable = None, capture_response: bool = True, capture_error: bool = True): + def capture_method( + self, method: Callable = None, capture_response: Optional[bool] = None, capture_error: Optional[bool] = None + ): """Decorator to create subsegment for arbitrary functions It also captures both response and exceptions as metadata @@ -335,7 +338,7 @@ def capture_method(self, method: Callable = None, capture_response: bool = True, method : Callable Method to annotate on capture_response : bool, optional - Instructs tracer to not include method's response as metadata, by default True + Instructs tracer to not include method's response as metadata capture_error : bool, optional Instructs tracer to not include handler's error as metadata, by default True @@ -475,28 +478,31 @@ async def async_tasks(): method_name = f"{method.__name__}" + capture_response = resolve_env_var_choice(env=TRACER_CAPTURE_RESPONSE_ENV, choice=capture_response) + capture_error = resolve_env_var_choice(env=TRACER_CAPTURE_ERROR_ENV, choice=capture_error) + if inspect.iscoroutinefunction(method): return self._decorate_async_function( - method=method, capture_response=capture_response, capture_error=True, method_name=method_name + method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name ) elif inspect.isgeneratorfunction(method): return self._decorate_generator_function( - method=method, capture_response=capture_response, capture_error=True, method_name=method_name + method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name ) elif hasattr(method, "__wrapped__") and inspect.isgeneratorfunction(method.__wrapped__): return self._decorate_generator_function_with_context_manager( - method=method, capture_response=capture_response, capture_error=True, method_name=method_name + method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name ) else: return self._decorate_sync_function( - method=method, capture_response=capture_response, capture_error=True, method_name=method_name + method=method, capture_response=capture_response, capture_error=capture_error, method_name=method_name ) def _decorate_async_function( self, method: Callable = None, - capture_response: bool = True, - capture_error: bool = True, + capture_response: Optional[bool] = None, + capture_error: Optional[bool] = None, method_name: str = None, ): @functools.wraps(method) @@ -522,8 +528,8 @@ async def decorate(*args, **kwargs): def _decorate_generator_function( self, method: Callable = None, - capture_response: bool = True, - capture_error: bool = True, + capture_response: Optional[bool] = None, + capture_error: Optional[bool] = None, method_name: str = None, ): @functools.wraps(method) @@ -549,8 +555,8 @@ def decorate(*args, **kwargs): def _decorate_generator_function_with_context_manager( self, method: Callable = None, - capture_response: bool = True, - capture_error: bool = True, + capture_response: Optional[bool] = None, + capture_error: Optional[bool] = None, method_name: str = None, ): @functools.wraps(method) @@ -577,8 +583,8 @@ def decorate(*args, **kwargs): def _decorate_sync_function( self, method: Callable = None, - capture_response: bool = True, - capture_error: bool = True, + capture_response: Optional[bool] = None, + capture_error: Optional[bool] = None, method_name: str = None, ): @functools.wraps(method) @@ -609,7 +615,7 @@ def _add_response_as_metadata( method_name: str = None, data: Any = None, subsegment: aws_xray_sdk.core.models.subsegment = None, - capture_response: bool = True, + capture_response: Optional[bool] = None, ): """Add response as metadata for given subsegment @@ -622,7 +628,7 @@ def _add_response_as_metadata( subsegment : aws_xray_sdk.core.models.subsegment, optional existing subsegment to add metadata on, by default None capture_response : bool, optional - Do not include response as metadata, by default True + Do not include response as metadata """ if data is None or not capture_response or subsegment is None: return @@ -634,7 +640,7 @@ def _add_full_exception_as_metadata( method_name: str = None, error: Exception = None, subsegment: aws_xray_sdk.core.models.subsegment = None, - capture_error: bool = True, + capture_error: Optional[bool] = None, ): """Add full exception object as metadata for given subsegment @@ -649,7 +655,7 @@ def _add_full_exception_as_metadata( capture_error : bool, optional Do not include error as metadata, by default True """ - if error is None or not capture_error or subsegment is None: + if not capture_error: return subsegment.put_metadata(key=f"{method_name} error", value=error, namespace=self._config["service"]) diff --git a/tests/functional/test_shared_functions.py b/tests/functional/test_shared_functions.py new file mode 100644 index 00000000000..3c13ebd5f5b --- /dev/null +++ b/tests/functional/test_shared_functions.py @@ -0,0 +1,11 @@ +import os + +from aws_lambda_powertools.shared.functions import resolve_env_var_choice + + +def test_explicit_wins_over_env_var(): + choice_env = os.getenv("CHOICE", True) + + choice = resolve_env_var_choice(env=choice_env, choice=False) + + assert choice is False diff --git a/tests/unit/test_tracing.py b/tests/unit/test_tracing.py index c8df34a76a6..71188e216ec 100644 --- a/tests/unit/test_tracing.py +++ b/tests/unit/test_tracing.py @@ -502,13 +502,15 @@ def generator_fn(): assert str(put_metadata_mock_args["value"]) == "test" -def test_tracer_lambda_handler_does_not_add_response_as_metadata(mocker, provider_stub, in_subsegment_mock): +def test_tracer_lambda_handler_override_response_as_metadata(mocker, provider_stub, in_subsegment_mock): # GIVEN tracer is initialized provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment) + + mocker.patch("aws_lambda_powertools.tracing.tracer.TRACER_CAPTURE_RESPONSE_ENV", return_value=True) tracer = Tracer(provider=provider, auto_patch=False) # WHEN capture_lambda_handler decorator is used - # and the handler response is empty + # with capture_response set to False @tracer.capture_lambda_handler(capture_response=False) def handler(event, context): return "response" @@ -519,7 +521,7 @@ def handler(event, context): assert in_subsegment_mock.put_metadata.call_count == 0 -def test_tracer_method_does_not_add_response_as_metadata(mocker, provider_stub, in_subsegment_mock): +def test_tracer_method_override_response_as_metadata(provider_stub, in_subsegment_mock): # GIVEN tracer is initialized provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment) tracer = Tracer(provider=provider, auto_patch=False) From cfc38df85b00d38fabbb1189e72e68d91b1820bd Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 13 Jan 2021 14:52:49 +0100 Subject: [PATCH 3/5] docs: update env vars --- docs/content/index.mdx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/content/index.mdx b/docs/content/index.mdx index 6af7d601862..30f4bd9c0dd 100644 --- a/docs/content/index.mdx +++ b/docs/content/index.mdx @@ -118,15 +118,16 @@ Utility | Description **Environment variables** used across suite of utilities. -Environment variable | Description | Utility -------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- -**POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All -**POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) -**POWERTOOLS_TRACE_DISABLED** | Disables tracing | [Tracing](./core/tracer) -**POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory) -**POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger) -**POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger) -**LOG_LEVEL** | Sets logging level | [Logging](./core/logger) +Environment variable | Description | Utility | Default +------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- +**POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | `"service_undefined"` +**POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | `None` +**POWERTOOLS_TRACE_DISABLED** | Disables tracing | [Tracing](./core/tracer) | `false` +**POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Overrides tracer from auto-capturing response as metadata | [Tracing](./core/tracer) | `true` +**POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory) | `false` +**POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger) | `false` +**POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger) | `0` +**LOG_LEVEL** | Sets logging level | [Logging](./core/logger) | `INFO` ## Debug mode From aeabcb699899a055e4bedada1af9415364bf3a51 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 13 Jan 2021 16:39:26 +0100 Subject: [PATCH 4/5] improv: address Nicolas feedback; improve docs --- docs/content/core/tracer.mdx | 25 ++++++++++++++++++++++- docs/content/index.mdx | 7 ++++++- tests/functional/test_shared_functions.py | 10 ++++----- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/docs/content/core/tracer.mdx b/docs/content/core/tracer.mdx index 62559ac9fe2..f2fa219adec 100644 --- a/docs/content/core/tracer.mdx +++ b/docs/content/core/tracer.mdx @@ -65,12 +65,16 @@ def handler(event, context): ... ``` +### disabling response auto-capture + +> New in 1.9.0 + Returning sensitive information from your Lambda handler or functions, where Tracer is used?

- You can disable Tracer from capturing their responses as tracing metadata with capture_response=False parameter in both capture_lambda_handler and capture_method decorators.

+You can disable Tracer from capturing their responses as tracing metadata with capture_response=False parameter in both capture_lambda_handler and capture_method decorators. ```python:title=do_not_capture_response_as_metadata.py # Disables Tracer from capturing response and adding as metadata @@ -80,6 +84,25 @@ def handler(event, context): return "sensitive_information" ``` +### disabling exception auto-capture + +> New in 1.10.0 + + + Can exceptions contain sensitive information from your Lambda handler or functions, where Tracer is used? +

+

+ +You can disable Tracer from capturing their exceptions as tracing metadata with capture_error=False parameter in both capture_lambda_handler and capture_method decorators. + +```python:title=do_not_capture_response_as_metadata.py +# Disables Tracer from capturing response and adding as metadata +# Useful when dealing with sensitive data +@tracer.capture_lambda_handler(capture_error=False) # highlight-line +def handler(event, context): + raise ValueError("some sensitive info in the stack trace...") +``` + ### Annotations Annotations are key-values indexed by AWS X-Ray on a per trace basis. You can use them to filter traces as well as to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/). diff --git a/docs/content/index.mdx b/docs/content/index.mdx index 30f4bd9c0dd..6f1a0ea05bc 100644 --- a/docs/content/index.mdx +++ b/docs/content/index.mdx @@ -116,6 +116,10 @@ Utility | Description ## Environment variables + + Explicit parameters take precedence over environment variables.

+
+ **Environment variables** used across suite of utilities. Environment variable | Description | Utility | Default @@ -123,7 +127,8 @@ Environment variable | Description | Utility | Default **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | `"service_undefined"` **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | `None` **POWERTOOLS_TRACE_DISABLED** | Disables tracing | [Tracing](./core/tracer) | `false` -**POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Overrides tracer from auto-capturing response as metadata | [Tracing](./core/tracer) | `true` +**POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Captures Lambda or method return as metadata. | [Tracing](./core/tracer) | `true` +**POWERTOOLS_TRACER_CAPTURE_ERROR** | Captures Lambda or method exception as metadata. | [Tracing](./core/tracer) | `true` **POWERTOOLS_TRACE_MIDDLEWARES** | Creates sub-segment for each custom middleware | [Middleware factory](./utilities/middleware_factory) | `false` **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | [Logging](./core/logger) | `false` **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logger) | `0` diff --git a/tests/functional/test_shared_functions.py b/tests/functional/test_shared_functions.py index 3c13ebd5f5b..ac05babb753 100644 --- a/tests/functional/test_shared_functions.py +++ b/tests/functional/test_shared_functions.py @@ -1,11 +1,9 @@ -import os - from aws_lambda_powertools.shared.functions import resolve_env_var_choice -def test_explicit_wins_over_env_var(): - choice_env = os.getenv("CHOICE", True) +def test_resolve_env_var_choice_explicit_wins_over_env_var(): + assert resolve_env_var_choice(env="true", choice=False) is False - choice = resolve_env_var_choice(env=choice_env, choice=False) - assert choice is False +def test_resolve_env_var_choice_env_wins_over_absent_explicit(): + assert resolve_env_var_choice(env="true") == 1 From 97fdaae032a6985e23d7d37b85de82867b463294 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 13 Jan 2021 16:40:59 +0100 Subject: [PATCH 5/5] docs: fix wording on disable exception example --- docs/content/core/tracer.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/core/tracer.mdx b/docs/content/core/tracer.mdx index f2fa219adec..2e36f4b7d0b 100644 --- a/docs/content/core/tracer.mdx +++ b/docs/content/core/tracer.mdx @@ -95,8 +95,8 @@ def handler(event, context): You can disable Tracer from capturing their exceptions as tracing metadata with capture_error=False parameter in both capture_lambda_handler and capture_method decorators. -```python:title=do_not_capture_response_as_metadata.py -# Disables Tracer from capturing response and adding as metadata +```python:title=do_not_capture_exception_as_metadata.py +# Disables Tracer from capturing exception and adding as metadata # Useful when dealing with sensitive data @tracer.capture_lambda_handler(capture_error=False) # highlight-line def handler(event, context):