11# frozen_string_literal: true
22
33require_relative '../../lib/aws_lambda_ric/lambda_log_formatter'
4+ require 'json'
45require 'logger'
56require 'securerandom'
7+ require 'time'
68require 'minitest/autorun'
79
810class LambdaLogFormatterTest < Minitest ::Test
9-
1011 def test_formatter
1112 $_global_aws_request_id = SecureRandom . uuid
1213 time = Time . now
@@ -16,6 +17,93 @@ def test_formatter
1617
1718 actual = under_test . call ( 'INFO' , time , progname , msg )
1819
19- assert_equal "I, [#{ time . strftime ( "%Y-%m-%dT%H:%M:%S.%6N" ) } ##{ $$} ] INFO #{ $_global_aws_request_id} -- #{ progname } : #{ msg } " , actual
20+ assert_equal "I, [#{ time . strftime ( "%Y-%m-%dT%H:%M:%S.%6N" ) } ##{ $$} ] INFO #{ $_global_aws_request_id} -- #{ progname } : #{ msg } \n " , actual
21+ end
22+ end
23+
24+ class JsonLogFormatterTest < Minitest ::Test
25+ def test_formats_standard_log_message
26+ $_global_aws_request_id = 'request-id-1'
27+ formatter = JsonLogFormatter . new
28+
29+ output = formatter . call ( 'INFO' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , 'app' , 'hello' )
30+ parsed = JSON . parse ( output )
31+
32+ assert_equal '2026-02-23T16:29:01.000000Z' , parsed [ 'timestamp' ]
33+ assert_equal 'INFO' , parsed [ 'level' ]
34+ assert_equal 'hello' , parsed [ 'message' ]
35+ assert_equal 'request-id-1' , parsed [ 'requestId' ]
36+ assert_equal 'app' , parsed [ 'logger' ]
37+ end
38+
39+ def test_formats_exception_fields
40+ $_global_aws_request_id = 'request-id-2'
41+ formatter = JsonLogFormatter . new
42+
43+ begin
44+ raise RuntimeError , 'something went wrong'
45+ rescue RuntimeError => e
46+ output = formatter . call ( 'ERROR' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , nil , e )
47+ parsed = JSON . parse ( output )
48+
49+ assert_equal 'ERROR' , parsed [ 'level' ]
50+ assert_equal 'something went wrong' , parsed [ 'message' ]
51+ assert_equal 'RuntimeError' , parsed [ 'errorType' ]
52+ assert_equal 'something went wrong' , parsed [ 'errorMessage' ]
53+ assert_kind_of Array , parsed [ 'stackTrace' ]
54+ refute_empty parsed [ 'stackTrace' ]
55+ assert_match ( /.+:.+:\d +/ , parsed [ 'location' ] )
56+ refute parsed . key? ( 'logger' )
57+ end
58+ end
59+
60+ def test_formats_location_from_backtrace_line
61+ $_global_aws_request_id = 'request-id-location'
62+ formatter = JsonLogFormatter . new
63+ exception = RuntimeError . new ( 'something went wrong' )
64+ exception . set_backtrace ( [ "/var/task/lambda_function.rb:6:in 'Object#lambda_handler'" ] )
65+
66+ output = formatter . call ( 'ERROR' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , nil , exception )
67+ parsed = JSON . parse ( output )
68+
69+ assert_equal '/var/task/lambda_function.rb:Object#lambda_handler:6' , parsed [ 'location' ]
70+ end
71+
72+ def test_coerces_non_string_progname
73+ $_global_aws_request_id = 'request-id-3'
74+ formatter = JsonLogFormatter . new
75+
76+ output = formatter . call ( 'INFO' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , 123 , 'hello' )
77+ parsed = JSON . parse ( output )
78+
79+ assert_equal '123' , parsed [ 'logger' ]
80+ end
81+
82+ def test_sanitizes_invalid_utf8_in_message
83+ $_global_aws_request_id = 'request-id-4'
84+ formatter = JsonLogFormatter . new
85+ invalid_message = [ 72 , 101 , 108 , 108 , 111 , 32 , 255 , 254 , 32 , 87 , 111 , 114 , 108 , 100 ] . pack ( 'C*' ) . force_encoding ( 'UTF-8' )
86+
87+ output = formatter . call ( 'INFO' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , nil , invalid_message )
88+ parsed = JSON . parse ( output )
89+
90+ assert_equal 'Hello �� World' , parsed [ 'message' ]
91+ end
92+
93+ def test_sanitizes_invalid_utf8_in_exception_fields
94+ $_global_aws_request_id = 'request-id-5'
95+ formatter = JsonLogFormatter . new
96+ invalid_message = [ 66 , 111 , 111 , 109 , 32 , 255 , 254 ] . pack ( 'C*' ) . force_encoding ( 'UTF-8' )
97+ invalid_backtrace = "/var/task/lambda_function.rb:6:in 'Object#lambda_hand" + [ 255 ] . pack ( 'C*' ) . force_encoding ( 'UTF-8' ) + "ler'"
98+ exception = RuntimeError . new ( invalid_message )
99+ exception . set_backtrace ( [ invalid_backtrace ] )
100+
101+ output = formatter . call ( 'ERROR' , Time . utc ( 2026 , 2 , 23 , 16 , 29 , 1 ) , nil , exception )
102+ parsed = JSON . parse ( output )
103+
104+ assert_equal 'Boom ��' , parsed [ 'message' ]
105+ assert_equal 'Boom ��' , parsed [ 'errorMessage' ]
106+ assert_equal [ "/var/task/lambda_function.rb:6:in 'Object#lambda_hand�ler'" ] , parsed [ 'stackTrace' ]
107+ assert_equal "/var/task/lambda_function.rb:Object#lambda_hand�ler:6" , parsed [ 'location' ]
20108 end
21- end
109+ end
0 commit comments