@@ -59,6 +59,56 @@ def test_severity_should_be_error(self, capsys: pytest.CaptureFixture[str]):
5959 log_output = json .loads (raw_log_output )
6060 assert log_output ["severity" ] == "ERROR"
6161
62+ def test_error_should_accept_exception (self , capsys : pytest .CaptureFixture [str ]):
63+ try :
64+ raise ValueError ("boom" )
65+ except ValueError as exception :
66+ logger .error ("failed" , error = exception )
67+
68+ raw_log_output = capsys .readouterr ().err
69+ log_output = json .loads (raw_log_output )
70+
71+ assert log_output ["severity" ] == "ERROR"
72+ assert log_output ["message" ] == "failed"
73+ assert log_output ["error" ]["type" ] == "ValueError"
74+ assert log_output ["error" ]["message" ] == "boom"
75+ assert "stack_trace" in log_output ["error" ]
76+ assert "ValueError: boom" in log_output ["error" ]["stack_trace" ]
77+
78+ def test_error_should_accept_self_referential_exception (self , capsys : pytest .CaptureFixture [str ]):
79+ class SelfArgError (Exception ):
80+ pass
81+
82+ exception = SelfArgError ("boom" )
83+ exception .args = (exception ,)
84+
85+ logger .error ("failed" , error = exception )
86+
87+ raw_log_output = capsys .readouterr ().err
88+ log_output = json .loads (raw_log_output )
89+
90+ assert log_output ["severity" ] == "ERROR"
91+ assert log_output ["message" ] == "failed"
92+ assert log_output ["error" ]["type" ] == "SelfArgError"
93+ assert log_output ["error" ]["args" ] == ["[CIRCULAR]" ]
94+
95+ def test_error_should_accept_exception_with_cyclic_payload (
96+ self , capsys : pytest .CaptureFixture [str ]
97+ ):
98+ payload = {}
99+ payload ["self" ] = payload
100+ exception = ValueError (payload )
101+
102+ logger .error ("failed" , error = exception )
103+
104+ raw_log_output = capsys .readouterr ().err
105+ log_output = json .loads (raw_log_output )
106+
107+ assert log_output ["severity" ] == "ERROR"
108+ assert log_output ["message" ] == "failed"
109+ assert log_output ["error" ]["type" ] == "ValueError"
110+ assert log_output ["error" ]["args" ] == [{"self" : "[CIRCULAR]" }]
111+
62112 def test_log_should_have_message (self , capsys : pytest .CaptureFixture [str ]):
63113 logger .log ("bar" )
64114 raw_log_output = capsys .readouterr ().out
@@ -78,6 +128,20 @@ def test_message_should_be_space_separated(self, capsys: pytest.CaptureFixture[s
78128 log_output = json .loads (raw_log_output )
79129 assert log_output ["message" ] == expected_message
80130
131+ def test_exception_should_include_stack_trace (self , capsys : pytest .CaptureFixture [str ]):
132+ try :
133+ raise ValueError ("boom" )
134+ except ValueError :
135+ logger .exception ("failed" )
136+
137+ raw_log_output = capsys .readouterr ().err
138+ log_output = json .loads (raw_log_output )
139+
140+ assert log_output ["severity" ] == "ERROR"
141+ assert log_output ["message" ] == "failed"
142+ assert "stack_trace" in log_output
143+ assert "ValueError: boom" in log_output ["stack_trace" ]
144+
81145 def test_remove_circular_references (self , capsys : pytest .CaptureFixture [str ]):
82146 # Create an object with a circular reference.
83147 circ = {"b" : "foo" }
0 commit comments