From e0e66ee2e209c4658f8725e2762c359b89509239 Mon Sep 17 00:00:00 2001 From: Sean O Brien Date: Fri, 13 Oct 2023 09:52:05 +0000 Subject: [PATCH 1/4] Log warning on unhandled exception. --- awslambdaric/bootstrap.py | 5 +++++ awslambdaric/lambda_literals.py | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 awslambdaric/lambda_literals.py diff --git a/awslambdaric/bootstrap.py b/awslambdaric/bootstrap.py index a3da58c..32b17b9 100644 --- a/awslambdaric/bootstrap.py +++ b/awslambdaric/bootstrap.py @@ -113,6 +113,7 @@ def replace_line_indentation(line, indent_char, new_indent_char): if _AWS_LAMBDA_LOG_FORMAT == LogFormat.JSON: _ERROR_FRAME_TYPE = _JSON_FRAME_TYPES[logging.ERROR] + _WARNING_FRAME_TYPE = _JSON_FRAME_TYPES[logging.WARNING] def log_error(error_result, log_sink): error_result = { @@ -128,6 +129,7 @@ def log_error(error_result, log_sink): else: _ERROR_FRAME_TYPE = _TEXT_FRAME_TYPES[logging.ERROR] + _WARNING_FRAME_TYPE = _TEXT_FRAME_TYPES[logging.WARNING] def log_error(error_result, log_sink): error_description = "[ERROR]" @@ -210,6 +212,9 @@ def handle_event_request( ) if error_result is not None: + from .lambda_literals import lambda_unhandled_exception_warning_message + + log_sink.log(lambda_unhandled_exception_warning_message, _WARNING_FRAME_TYPE) log_error(error_result, log_sink) lambda_runtime_client.post_invocation_error( invoke_id, to_json(error_result), to_json(xray_fault) diff --git a/awslambdaric/lambda_literals.py b/awslambdaric/lambda_literals.py new file mode 100644 index 0000000..3b71c08 --- /dev/null +++ b/awslambdaric/lambda_literals.py @@ -0,0 +1,15 @@ +""" +Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Holds warning message that is emitted when an unhandled exception is raised during function invocation. +""" +lambda_warning = "LAMBDA_WARNING" +lambda_unhandled_exception_warning_message = str( + f"{lambda_warning}: " + "Unhandled exception. " + "The most likely cause is an issue in the function code. " + "However, in rare cases, a Lambda runtime update can cause unexpected function behavior. " + "For functions using managed runtimes, runtime updates can be triggered by a function change, or can be applied automatically. " + "To determine if the runtime has been updated, check the runtime version in the INIT_START log entry. " + "If this error correlates with a change in the runtime version, you may be able to mitigate this error by temporarily rolling back to the previous runtime version. " + "For more information, see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html" +) From aa0a8b8f0e6360ad178effd7259536137e72a9de Mon Sep 17 00:00:00 2001 From: Sean O Brien Date: Fri, 13 Oct 2023 12:17:39 +0000 Subject: [PATCH 2/4] Update tests. --- tests/test_bootstrap.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index ca367fd..f501453 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -20,6 +20,9 @@ from awslambdaric.lambda_runtime_exception import FaultException from awslambdaric.lambda_runtime_log_utils import LogFormat, _get_log_level_from_env_var from awslambdaric.lambda_runtime_marshaller import LambdaMarshaller +from awslambdaric.lambda_literals import ( + lambda_unhandled_exception_warning_message, +) class TestUpdateXrayEnv(unittest.TestCase): @@ -461,7 +464,10 @@ def raise_exception_handler(json_input, lambda_context): ) # NOTE: Indentation characters are NO-BREAK SPACE (U+00A0) not SPACE (U+0020) - error_logs = "[ERROR] FaultExceptionType: Fault exception msg\r" + error_logs = ( + lambda_unhandled_exception_warning_message + + "[ERROR] FaultExceptionType: Fault exception msg\r" + ) error_logs += "Traceback (most recent call last):\r" error_logs += '  File "spam.py", line 3, in \r' error_logs += "    spam.eggs()\r" @@ -492,7 +498,10 @@ def raise_exception_handler(json_input, lambda_context): 0, bootstrap.StandardLogSink(), ) - error_logs = "[ERROR] FaultExceptionType: Fault exception msg\rTraceback (most recent call last):\n" + error_logs = ( + lambda_unhandled_exception_warning_message + + "[ERROR] FaultExceptionType: Fault exception msg\rTraceback (most recent call last):\n" + ) self.assertEqual(mock_stdout.getvalue(), error_logs) @@ -518,7 +527,10 @@ def raise_exception_handler(json_input, lambda_context): 0, bootstrap.StandardLogSink(), ) - error_logs = "[ERROR] FaultExceptionType\rTraceback (most recent call last):\n" + error_logs = ( + lambda_unhandled_exception_warning_message + + "[ERROR] FaultExceptionType\rTraceback (most recent call last):\n" + ) self.assertEqual(mock_stdout.getvalue(), error_logs) @@ -544,7 +556,10 @@ def raise_exception_handler(json_input, lambda_context): 0, bootstrap.StandardLogSink(), ) - error_logs = "[ERROR] Fault exception msg\rTraceback (most recent call last):\n" + error_logs = ( + lambda_unhandled_exception_warning_message + + "[ERROR] Fault exception msg\rTraceback (most recent call last):\n" + ) self.assertEqual(mock_stdout.getvalue(), error_logs) @@ -579,8 +594,7 @@ def raise_exception_handler(json_input, lambda_context): 0, bootstrap.StandardLogSink(), ) - - error_logs = "[ERROR]\r" + error_logs = lambda_unhandled_exception_warning_message + "[ERROR]\r" error_logs += "Traceback (most recent call last):\r" error_logs += '  File "spam.py", line 3, in \r' error_logs += "    spam.eggs()\r" @@ -615,8 +629,10 @@ def test_handle_event_request_fault_exception_logging_syntax_error( 0, bootstrap.StandardLogSink(), ) - - error_logs = f"[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'a': {syntax_error}\r" + error_logs = ( + lambda_unhandled_exception_warning_message + + f"[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'a': {syntax_error}\r" + ) error_logs += "Traceback (most recent call last):\r" error_logs += '  File "" Line 1\r' error_logs += "    -\n" From ea88aecef791bef2e01dfa35ba10b8eab2947e54 Mon Sep 17 00:00:00 2001 From: Sean O Brien Date: Thu, 1 Feb 2024 14:14:43 +0000 Subject: [PATCH 3/4] Fix formatting. --- awslambdaric/lambda_runtime_client.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/awslambdaric/lambda_runtime_client.py b/awslambdaric/lambda_runtime_client.py index ba85902..07243fc 100644 --- a/awslambdaric/lambda_runtime_client.py +++ b/awslambdaric/lambda_runtime_client.py @@ -108,9 +108,11 @@ def post_invocation_result( ): runtime_client.post_invocation_result( invoke_id, - result_data - if isinstance(result_data, bytes) - else result_data.encode("utf-8"), + ( + result_data + if isinstance(result_data, bytes) + else result_data.encode("utf-8") + ), content_type, ) From 1c8426fb102c014ed4942b14d1e7dcc7a8e7b093 Mon Sep 17 00:00:00 2001 From: Sean O Brien Date: Thu, 1 Feb 2024 14:15:23 +0000 Subject: [PATCH 4/4] Move comment in Lambda Literals. --- awslambdaric/lambda_literals.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/awslambdaric/lambda_literals.py b/awslambdaric/lambda_literals.py index 3b71c08..82560c5 100644 --- a/awslambdaric/lambda_literals.py +++ b/awslambdaric/lambda_literals.py @@ -1,8 +1,10 @@ """ Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. -Holds warning message that is emitted when an unhandled exception is raised during function invocation. """ + lambda_warning = "LAMBDA_WARNING" + +# Holds warning message that is emitted when an unhandled exception is raised during function invocation. lambda_unhandled_exception_warning_message = str( f"{lambda_warning}: " "Unhandled exception. "