diff --git a/awslambdaric/bootstrap.py b/awslambdaric/bootstrap.py index d8053fe..a43078e 100644 --- a/awslambdaric/bootstrap.py +++ b/awslambdaric/bootstrap.py @@ -73,10 +73,11 @@ def result(*args): return result -def make_error(error_message, error_type, stack_trace): +def make_error(error_message, error_type, stack_trace, invoke_id=None): result = { "errorMessage": error_message if error_message else "", "errorType": error_type if error_type else "", + "requestId": invoke_id if invoke_id is not None else "", "stackTrace": stack_trace if stack_trace else [], } return result @@ -151,7 +152,7 @@ def handle_event_request( ) except FaultException as e: xray_fault = make_xray_fault("LambdaValidationError", e.msg, os.getcwd(), []) - error_result = make_error(e.msg, e.exception_type, e.trace) + error_result = make_error(e.msg, e.exception_type, e.trace, invoke_id) except Exception: etype, value, tb = sys.exc_info() @@ -163,7 +164,7 @@ def handle_event_request( xray_fault = make_xray_fault(etype.__name__, str(value), os.getcwd(), tb_tuples) error_result = make_error( - str(value), etype.__name__, traceback.format_list(tb_tuples) + str(value), etype.__name__, traceback.format_list(tb_tuples), invoke_id ) if error_result is not None: diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index d28260b..15ed6f7 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -392,6 +392,7 @@ def raise_exception_handler(json_input, lambda_context): expected_response = { "errorType": "FaultExceptionType", "errorMessage": "Fault exception msg", + "requestId": "invoke_id", "stackTrace": ["trace_line1\ntrace_line2", "trace_line3\ntrace_line4"], } bootstrap.handle_event_request( @@ -988,6 +989,35 @@ def test_log_error_empty_stacktrace_line_framed_log_sink(self): actual_message = content[8:].decode() self.assertEqual(actual_message, expected_logged_error) + # Just to ensure we are not logging the requestId from error response, just sending in the response + def test_log_error_invokeId_line_framed_log_sink(self): + with NamedTemporaryFile() as temp_file: + with bootstrap.FramedTelemetryLogSink(temp_file.name) as log_sink: + err_to_log = bootstrap.make_error( + "Error message", + "ErrorType", + ["line1", "", "line2"], + "testrequestId", + ) + bootstrap.log_error(err_to_log, log_sink) + + expected_logged_error = ( + "[ERROR] ErrorType: Error message\nTraceback " + "(most recent call last):\nline1\n\nline2" + ) + + with open(temp_file.name, "rb") as f: + content = f.read() + + frame_type = int.from_bytes(content[:4], "big") + self.assertEqual(frame_type, 0xA55A0001) + + length = int.from_bytes(content[4:8], "big") + self.assertEqual(length, len(expected_logged_error)) + + actual_message = content[8:].decode() + self.assertEqual(actual_message, expected_logged_error) + class TestUnbuffered(unittest.TestCase): def test_write(self):