diff --git a/CHANGELOG.md b/CHANGELOG.md index 34100fc4a1a..d2476c2a53a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - **Docs**: Clarify confusion on Tracer reuse and `auto_patch=False` statement +- **Logger**: Autocomplete for log statements in PyCharm ## [1.1.1] - 2020-08-14 ### Fixed diff --git a/aws_lambda_powertools/logging/logger.py b/aws_lambda_powertools/logging/logger.py index b248055aacf..54c21e88528 100644 --- a/aws_lambda_powertools/logging/logger.py +++ b/aws_lambda_powertools/logging/logger.py @@ -34,7 +34,11 @@ def _is_cold_start() -> bool: return cold_start -class Logger: +# PyCharm does not support autocomplete via getattr +# so we need to return to subclassing removed in #97 +# All methods/properties continue to be proxied to inner logger +# https://github.com/awslabs/aws-lambda-powertools-python/issues/107 +class Logger(logging.Logger): # lgtm [py/missing-call-to-init] """Creates and setups a logger to format statements in JSON. Includes service name and any additional key=value into logs @@ -187,7 +191,8 @@ def _configure_sampling(self): self.log_level = logging.DEBUG except ValueError: raise InvalidLoggerSamplingRateError( - f"Expected a float value ranging 0 to 1, but received {self.sampling_rate} instead. Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable." # noqa E501 + f"Expected a float value ranging 0 to 1, but received {self.sampling_rate} instead." + f"Please review POWERTOOLS_LOGGER_SAMPLE_RATE environment variable." ) def inject_lambda_context(self, lambda_handler: Callable[[Dict, Any], Any] = None, log_event: bool = False): diff --git a/tests/functional/test_logger.py b/tests/functional/test_logger.py index 083220ccf8c..7b0c870ee07 100644 --- a/tests/functional/test_logger.py +++ b/tests/functional/test_logger.py @@ -1,3 +1,4 @@ +import inspect import io import json import logging @@ -295,7 +296,7 @@ def test_logger_children_propagate_changes(stdout): assert child.parent.name == "order" -def test_logger_child_not_set_returns_same_logger(stdout): +def test_logger_child_not_set_returns_same_logger(): # GIVEN two Loggers are initialized with the same service name # WHEN child param isn't set logger_one = Logger(service="something") @@ -308,7 +309,7 @@ def test_logger_child_not_set_returns_same_logger(stdout): assert logger_one.name is logger_two.name -def test_logger_level_case_insensitive(stdout): +def test_logger_level_case_insensitive(): # GIVEN a Loggers is initialized # WHEN log level is set as "info" instead of "INFO" logger = Logger(level="info") @@ -344,3 +345,17 @@ def test_logger_level_env_var_as_int(monkeypatch): monkeypatch.setenv("LOG_LEVEL", 50) with pytest.raises(ValueError, match="Unknown level: '50'"): Logger() + + +def test_logger_record_caller_location(stdout): + # GIVEN Logger is initialized + logger = Logger(stream=stdout) + + # WHEN log statement is run + logger.info("log") + + # THEN 'location' field should have + # the correct caller resolution + caller_fn_name = inspect.currentframe().f_code.co_name + log = capture_logging_output(stdout) + assert caller_fn_name in log["location"]