From 42f789e7050ec3b60596fcd8535c2efd7ab97134 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Fri, 7 May 2021 14:14:29 +1000 Subject: [PATCH] Support .info("foo %s", "bar") formatting in logger This adjusts the default logging formatter (LambdaPowertoolsFormatter) to handle non-structured logs with formatting, like: logger.info("foo %s", "bar") This allows the formatter to be used in more situations, such as the universal formatter for all log messages coming out of a system, even libraries using the normal logging functionality, without explicit support for aws-lambda-powertools. If formatting is performed, this is taken as a hint that the value probably isn't semantically JSON, even if it's syntactically valid as JSON. --- aws_lambda_powertools/logging/formatter.py | 3 +++ .../functional/test_logger_powertools_formatter.py | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/aws_lambda_powertools/logging/formatter.py b/aws_lambda_powertools/logging/formatter.py index 47418063732..7ff9881062a 100644 --- a/aws_lambda_powertools/logging/formatter.py +++ b/aws_lambda_powertools/logging/formatter.py @@ -176,6 +176,9 @@ def _extract_log_message(self, log_record: logging.LogRecord) -> Union[Dict[str, if isinstance(message, dict): return message + if log_record.args: # logger.info("foo %s", "bar") requires formatting + return log_record.getMessage() + if isinstance(message, str): # could be a JSON string try: message = self.json_deserializer(message) diff --git a/tests/functional/test_logger_powertools_formatter.py b/tests/functional/test_logger_powertools_formatter.py index 4b92e6b47b9..c9f970e29a5 100644 --- a/tests/functional/test_logger_powertools_formatter.py +++ b/tests/functional/test_logger_powertools_formatter.py @@ -275,3 +275,16 @@ def test_logging_various_primitives(stdout, service_name, message): # THEN it should raise no serialization/deserialization error logger.info(message) json.loads(stdout.getvalue()) + + +def test_log_formatting(stdout, service_name): + # GIVEN a logger with default settings + logger = Logger(service=service_name, stream=stdout) + + # WHEN logging a message with formatting + logger.info('["foo %s %d %s", null]', "bar", 123, [1, None]) + + log_dict: dict = json.loads(stdout.getvalue()) + + # THEN the formatting should be applied (NB. this is valid json, but hasn't be parsed) + assert log_dict["message"] == '["foo bar 123 [1, None]", null]'