1818
1919import awslambdaric .bootstrap as bootstrap
2020from awslambdaric .lambda_runtime_exception import FaultException
21- from awslambdaric .lambda_runtime_log_utils import LogFormat , _get_log_level_from_env_var
21+ from awslambdaric .lambda_runtime_log_utils import (
22+ LogFormat ,
23+ _get_log_level_from_env_var ,
24+ JsonFormatter ,
25+ )
2226from awslambdaric .lambda_runtime_marshaller import LambdaMarshaller
2327from awslambdaric .lambda_literals import (
2428 lambda_unhandled_exception_warning_message ,
@@ -61,6 +65,14 @@ def setUp(self):
6165 self .event_body = '"event_body"'
6266 self .working_directory = os .getcwd ()
6367
68+ logging .getLogger ().handlers .clear ()
69+
70+ def tearDown (self ) -> None :
71+ logging .getLogger ().handlers .clear ()
72+ logging .getLogger ().level = logging .NOTSET
73+
74+ return super ().tearDown ()
75+
6476 @staticmethod
6577 def dummy_handler (json_input , lambda_context ):
6678 return {"input" : json_input , "aws_request_id" : lambda_context .aws_request_id }
@@ -451,6 +463,8 @@ def raise_exception_handler(json_input, lambda_context):
451463 ),
452464 )
453465
466+ logging .getLogger ().addHandler (logging .StreamHandler (mock_stdout ))
467+
454468 bootstrap .handle_event_request (
455469 self .lambda_runtime ,
456470 raise_exception_handler ,
@@ -467,6 +481,7 @@ def raise_exception_handler(json_input, lambda_context):
467481 # NOTE: Indentation characters are NO-BREAK SPACE (U+00A0) not SPACE (U+0020)
468482 error_logs = (
469483 lambda_unhandled_exception_warning_message
484+ + "\n "
470485 + "[ERROR] FaultExceptionType: Fault exception msg\r "
471486 )
472487 error_logs += "Traceback (most recent call last):\r "
@@ -487,6 +502,8 @@ def raise_exception_handler(json_input, lambda_context):
487502 "FaultExceptionType" , "Fault exception msg" , None
488503 )
489504
505+ logging .getLogger ().addHandler (logging .StreamHandler (mock_stdout ))
506+
490507 bootstrap .handle_event_request (
491508 self .lambda_runtime ,
492509 raise_exception_handler ,
@@ -501,6 +518,7 @@ def raise_exception_handler(json_input, lambda_context):
501518 )
502519 error_logs = (
503520 lambda_unhandled_exception_warning_message
521+ + "\n "
504522 + "[ERROR] FaultExceptionType: Fault exception msg\r Traceback (most recent call last):\n "
505523 )
506524
@@ -516,6 +534,8 @@ def raise_exception_handler(json_input, lambda_context):
516534 except ImportError :
517535 raise bootstrap .FaultException ("FaultExceptionType" , None , None )
518536
537+ logging .getLogger ().addHandler (logging .StreamHandler (mock_stdout ))
538+
519539 bootstrap .handle_event_request (
520540 self .lambda_runtime ,
521541 raise_exception_handler ,
@@ -530,6 +550,7 @@ def raise_exception_handler(json_input, lambda_context):
530550 )
531551 error_logs = (
532552 lambda_unhandled_exception_warning_message
553+ + "\n "
533554 + "[ERROR] FaultExceptionType\r Traceback (most recent call last):\n "
534555 )
535556
@@ -545,6 +566,8 @@ def raise_exception_handler(json_input, lambda_context):
545566 except ImportError :
546567 raise bootstrap .FaultException (None , "Fault exception msg" , None )
547568
569+ logging .getLogger ().addHandler (logging .StreamHandler (mock_stdout ))
570+
548571 bootstrap .handle_event_request (
549572 self .lambda_runtime ,
550573 raise_exception_handler ,
@@ -559,6 +582,7 @@ def raise_exception_handler(json_input, lambda_context):
559582 )
560583 error_logs = (
561584 lambda_unhandled_exception_warning_message
585+ + "\n "
562586 + "[ERROR] Fault exception msg\r Traceback (most recent call last):\n "
563587 )
564588
@@ -583,6 +607,8 @@ def raise_exception_handler(json_input, lambda_context):
583607 ),
584608 )
585609
610+ logging .getLogger ().addHandler (logging .StreamHandler (mock_stdout ))
611+
586612 bootstrap .handle_event_request (
587613 self .lambda_runtime ,
588614 raise_exception_handler ,
@@ -595,7 +621,7 @@ def raise_exception_handler(json_input, lambda_context):
595621 0 ,
596622 bootstrap .StandardLogSink (),
597623 )
598- error_logs = lambda_unhandled_exception_warning_message + "[ERROR]\r "
624+ error_logs = lambda_unhandled_exception_warning_message + "\n [ERROR]\r "
599625 error_logs += "Traceback (most recent call last):\r "
600626 error_logs += ' File "spam.py", line 3, in <module>\r '
601627 error_logs += " spam.eggs()\r "
@@ -604,6 +630,48 @@ def raise_exception_handler(json_input, lambda_context):
604630
605631 self .assertEqual (mock_stdout .getvalue (), error_logs )
606632
633+ @patch ("sys.stdout" , new_callable = StringIO )
634+ def test_handle_event_request_fault_exception_logging_in_json (self , mock_stdout ):
635+ def raise_exception_handler (json_input , lambda_context ):
636+ try :
637+ import invalid_module # noqa: F401
638+ except ImportError :
639+ raise bootstrap .FaultException ("FaultExceptionType" , None , None )
640+
641+ logging_handler = logging .StreamHandler (mock_stdout )
642+ logging_handler .setFormatter (JsonFormatter ())
643+ logging .getLogger ().addHandler (logging_handler )
644+
645+ bootstrap .handle_event_request (
646+ self .lambda_runtime ,
647+ raise_exception_handler ,
648+ "invoke_id" ,
649+ self .event_body ,
650+ "application/json" ,
651+ {},
652+ {},
653+ "invoked_function_arn" ,
654+ 0 ,
655+ bootstrap .StandardLogSink (),
656+ )
657+
658+ stdout_value = mock_stdout .getvalue ()
659+ received_warning = stdout_value .split ("\n " )[0 ]
660+ received_rest = stdout_value [len (received_warning ) + 1 :]
661+
662+ warning = json .loads (received_warning )
663+ self .assertEqual (warning ["level" ], "WARNING" )
664+ self .assertEqual (warning ["message" ], lambda_unhandled_exception_warning_message )
665+ self .assertEqual (warning ["logger" ], "root" )
666+ self .assertIn ("timestamp" , warning )
667+
668+ # this line is not in json because of the way the test runtime is bootstrapped
669+ error_logs = (
670+ "\n [ERROR] FaultExceptionType\r Traceback (most recent call last):\n "
671+ )
672+
673+ self .assertEqual (received_rest , error_logs )
674+
607675
608676class TestXrayFault (unittest .TestCase ):
609677 def test_make_xray (self ):
0 commit comments