From 364c537e565f15a256612c96939e973c52f54673 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 10:45:20 +0200 Subject: [PATCH 1/6] feat(logger): set package logger to debug mode when POWERTOOLS_DEV is set --- aws_lambda_powertools/package_logger.py | 12 ++++++++++++ aws_lambda_powertools/shared/constants.py | 2 ++ aws_lambda_powertools/shared/functions.py | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/aws_lambda_powertools/package_logger.py b/aws_lambda_powertools/package_logger.py index c1adb67ade8..ad81431cf6f 100644 --- a/aws_lambda_powertools/package_logger.py +++ b/aws_lambda_powertools/package_logger.py @@ -1,7 +1,19 @@ import logging +from aws_lambda_powertools.logging.logger import set_package_logger +from aws_lambda_powertools.shared.functions import powertools_debug_is_set + def set_package_logger_handler(): + """Sets up Lambda Powertools package logging. + + By default, we discard any output to not interfere with customers logging. + + When POWERTOOLS_DEBUG env var is set, we setup `aws_lambda_powertools` logger in DEBUG level. + """ + if powertools_debug_is_set(): + return set_package_logger() + logger = logging.getLogger("aws_lambda_powertools") logger.addHandler(logging.NullHandler()) logger.propagate = False diff --git a/aws_lambda_powertools/shared/constants.py b/aws_lambda_powertools/shared/constants.py index 5db9ec08a56..86a6c2ac41b 100644 --- a/aws_lambda_powertools/shared/constants.py +++ b/aws_lambda_powertools/shared/constants.py @@ -36,4 +36,6 @@ # JSON indentation level PRETTY_INDENT: int = 4 COMPACT_INDENT = None + POWERTOOLS_DEV_ENV: str = "POWERTOOLS_DEV" +POWERTOOLS_DEBUG_ENV: str = "POWERTOOLS_DEBUG" diff --git a/aws_lambda_powertools/shared/functions.py b/aws_lambda_powertools/shared/functions.py index a25a3e7631e..c2fd0adb819 100644 --- a/aws_lambda_powertools/shared/functions.py +++ b/aws_lambda_powertools/shared/functions.py @@ -91,3 +91,12 @@ def powertools_dev_is_set() -> bool: return True return False + + +def powertools_debug_is_set() -> bool: + is_on = strtobool(os.getenv(constants.POWERTOOLS_DEBUG_ENV, "0")) + if is_on: + warnings.warn("POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG") + return True + + return False From 9cb7a16f8f8726f3537f45aef101c9dd954ad3c9 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 11:19:59 +0200 Subject: [PATCH 2/6] docs(homepage): update debug mode to use new POWERTOOLS_DEBUG env var --- docs/index.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/index.md b/docs/index.md index 10f46566e1d..44a2c5d16da 100644 --- a/docs/index.md +++ b/docs/index.md @@ -454,15 +454,9 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai ## Debug mode -As a best practice, AWS Lambda Powertools module logging statements are suppressed. If necessary, you can enable debugging using `set_package_logger` for additional information on every internal operation: +As a best practice for libraries, AWS Lambda Powertools module logging statements are suppressed. -```python title="Powertools debug mode example" -from aws_lambda_powertools.logging.logger import set_package_logger - -set_package_logger() # (1) -``` - -1. :information_source: this will configure our `aws_lambda_powertools` logger with debug. +When necessary, you can use `POWERTOOLS_DEBUG` environment variable to enable debugging. This will provide additional information on every internal operation. ## Tenets From 4085e37bc9b2376364a2230cf17a82a1ac3939c9 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 11:52:09 +0200 Subject: [PATCH 3/6] refactor(strtobool): optimize for common value 1st Signed-off-by: heitorlessa --- aws_lambda_powertools/shared/functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/functions.py b/aws_lambda_powertools/shared/functions.py index c2fd0adb819..82d82a5d20c 100644 --- a/aws_lambda_powertools/shared/functions.py +++ b/aws_lambda_powertools/shared/functions.py @@ -20,9 +20,9 @@ def strtobool(value: str) -> bool: > note:: Copied from distutils.util. """ value = value.lower() - if value in ("y", "yes", "t", "true", "on", "1"): + if value in ("1", "y", "yes", "t", "true", "on"): return True - if value in ("n", "no", "f", "false", "off", "0"): + if value in ("0", "n", "no", "f", "false", "off"): return False raise ValueError(f"invalid truth value {value!r}") From 93ca6c0d5caf807569bd7f560a0aa2e3ad616a72 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 11:53:07 +0200 Subject: [PATCH 4/6] chore(tests): powertools_debug effect and warning Signed-off-by: heitorlessa --- aws_lambda_powertools/package_logger.py | 10 +++++-- tests/functional/test_logger.py | 38 +++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/aws_lambda_powertools/package_logger.py b/aws_lambda_powertools/package_logger.py index ad81431cf6f..e6c58ba9549 100644 --- a/aws_lambda_powertools/package_logger.py +++ b/aws_lambda_powertools/package_logger.py @@ -4,15 +4,21 @@ from aws_lambda_powertools.shared.functions import powertools_debug_is_set -def set_package_logger_handler(): +def set_package_logger_handler(stream=None): """Sets up Lambda Powertools package logging. By default, we discard any output to not interfere with customers logging. When POWERTOOLS_DEBUG env var is set, we setup `aws_lambda_powertools` logger in DEBUG level. + + Parameters + ---------- + stream: sys.stdout + log stream, stdout by default """ + if powertools_debug_is_set(): - return set_package_logger() + return set_package_logger(stream=stream) logger = logging.getLogger("aws_lambda_powertools") logger.addHandler(logging.NullHandler()) diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index c8b3dc61755..e5b24200722 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -5,6 +5,7 @@ import random import re import string +import warnings from ast import Dict from collections import namedtuple from datetime import datetime, timezone @@ -12,10 +13,13 @@ import pytest -from aws_lambda_powertools import Logger, Tracer +from aws_lambda_powertools import Logger, Tracer, set_package_logger_handler from aws_lambda_powertools.logging import correlation_paths from aws_lambda_powertools.logging.exceptions import InvalidLoggerSamplingRateError -from aws_lambda_powertools.logging.formatter import BasePowertoolsFormatter, LambdaPowertoolsFormatter +from aws_lambda_powertools.logging.formatter import ( + BasePowertoolsFormatter, + LambdaPowertoolsFormatter, +) from aws_lambda_powertools.logging.logger import set_package_logger from aws_lambda_powertools.shared import constants from aws_lambda_powertools.utilities.data_classes import S3Event, event_source @@ -824,3 +828,33 @@ def handler(event, context, planet, str_end="."): log = capture_logging_output(stdout) assert log["message"] == "Hello World!" + + +def test_set_package_logger_handler_with_powertools_debug_env_var(stdout, monkeypatch: pytest.MonkeyPatch): + # GIVEN POWERTOOLS_DEBUG is set + monkeypatch.setenv(constants.POWERTOOLS_DEBUG_ENV, "1") + logger = logging.getLogger("aws_lambda_powertools") + + # WHEN set_package_logger is used at initialization + # and any Powertools operation is used (e.g., Tracer) + set_package_logger_handler(stream=stdout) + Tracer(disabled=True) + + # THEN Tracer debug log statement should be logged + output = stdout.getvalue() + assert "Tracing has been disabled" in output + assert logger.level == logging.DEBUG + + +def test_powertools_debug_env_var_warning(monkeypatch: pytest.MonkeyPatch): + # GIVEN POWERTOOLS_DEBUG is set + monkeypatch.setenv(constants.POWERTOOLS_DEBUG_ENV, "1") + warning_message = "POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG" + + # WHEN set_package_logger is used at initialization + # THEN a warning should be emitted + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("default") + set_package_logger_handler() + assert len(w) == 1 + assert str(w[0].message) == warning_message From 7ee03ed32167153b0ecda0bc93ec092473d8f4ef Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 12:00:32 +0200 Subject: [PATCH 5/6] chore(tests): tests powertools_dev and powertools_debug warning --- aws_lambda_powertools/shared/functions.py | 2 +- tests/functional/test_shared_functions.py | 39 ++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/shared/functions.py b/aws_lambda_powertools/shared/functions.py index 82d82a5d20c..2212eb77e18 100644 --- a/aws_lambda_powertools/shared/functions.py +++ b/aws_lambda_powertools/shared/functions.py @@ -96,7 +96,7 @@ def powertools_dev_is_set() -> bool: def powertools_debug_is_set() -> bool: is_on = strtobool(os.getenv(constants.POWERTOOLS_DEBUG_ENV, "0")) if is_on: - warnings.warn("POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG") + warnings.warn("POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG.") return True return False diff --git a/tests/functional/test_shared_functions.py b/tests/functional/test_shared_functions.py index c71b7239739..a8e1755bdd5 100644 --- a/tests/functional/test_shared_functions.py +++ b/tests/functional/test_shared_functions.py @@ -1,6 +1,15 @@ +import warnings + import pytest -from aws_lambda_powertools.shared.functions import resolve_env_var_choice, resolve_truthy_env_var_choice, strtobool +from aws_lambda_powertools.shared import constants +from aws_lambda_powertools.shared.functions import ( + powertools_debug_is_set, + powertools_dev_is_set, + resolve_env_var_choice, + resolve_truthy_env_var_choice, + strtobool, +) def test_resolve_env_var_choice_explicit_wins_over_env_var(): @@ -27,3 +36,31 @@ def test_strtobool_value_error(): with pytest.raises(ValueError) as exp: strtobool("fail") assert str(exp.value) == "invalid truth value 'fail'" + + +def test_powertools_dev_warning(monkeypatch: pytest.MonkeyPatch): + # GIVEN POWERTOOLS_DEBUG is set + monkeypatch.setenv(constants.POWERTOOLS_DEV_ENV, "1") + warning_message = "POWERTOOLS_DEV environment variable is enabled. Increasing verbosity across utilities." + + # WHEN set_package_logger is used at initialization + # THEN a warning should be emitted + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("default") + powertools_dev_is_set() + assert len(w) == 1 + assert str(w[0].message) == warning_message + + +def test_powertools_debug_warning(monkeypatch: pytest.MonkeyPatch): + # GIVEN POWERTOOLS_DEBUG is set + monkeypatch.setenv(constants.POWERTOOLS_DEBUG_ENV, "1") + warning_message = "POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG." + + # WHEN set_package_logger is used at initialization + # THEN a warning should be emitted + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("default") + powertools_debug_is_set() + assert len(w) == 1 + assert str(w[0].message) == warning_message From 40c348d13ba4e02a78713b5648706413f9cbd3c2 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Wed, 5 Oct 2022 12:36:24 +0200 Subject: [PATCH 6/6] chore(tests): updated warning message --- tests/functional/test_logger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index e5b24200722..7eb3018ef64 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -849,7 +849,7 @@ def test_set_package_logger_handler_with_powertools_debug_env_var(stdout, monkey def test_powertools_debug_env_var_warning(monkeypatch: pytest.MonkeyPatch): # GIVEN POWERTOOLS_DEBUG is set monkeypatch.setenv(constants.POWERTOOLS_DEBUG_ENV, "1") - warning_message = "POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG" + warning_message = "POWERTOOLS_DEBUG environment variable is enabled. Setting logging level to DEBUG." # WHEN set_package_logger is used at initialization # THEN a warning should be emitted