Skip to content

Commit 44e35c4

Browse files
feat: add exception logging function, add tests (#344)
1 parent ef8cddc commit 44e35c4

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

solnlib/log.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import logging
2020
import logging.handlers
2121
import os.path as op
22+
import traceback
2223
from threading import Lock
2324
from typing import Dict, Any
2425

@@ -263,3 +264,25 @@ def events_ingested(
263264
"n_events": n_events,
264265
},
265266
)
267+
268+
269+
def log_exception(
270+
logger: logging.Logger,
271+
e: Exception,
272+
full_msg: bool = True,
273+
msg_before: str = None,
274+
msg_after: str = None,
275+
log_level: int = logging.ERROR,
276+
):
277+
"""General function to log exceptions."""
278+
exc_type, exc_value, exc_traceback = type(e), e, e.__traceback__
279+
if full_msg:
280+
error = traceback.format_exception(exc_type, exc_value, exc_traceback)
281+
else:
282+
error = traceback.format_exception_only(exc_type, exc_value)
283+
284+
msg_start = msg_before if msg_before is not None else ""
285+
msg_mid = "".join(error)
286+
msg_end = msg_after if msg_after is not None else ""
287+
msg = f"{msg_start}\n{msg_mid}\n{msg_end}"
288+
logger.log(log_level, msg)

tests/unit/test_log.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
#
1616

1717
import logging
18+
import json
1819
import multiprocessing
1920
import os
2021
import shutil
2122
import threading
23+
import traceback
2224
import time
2325
from unittest import mock
2426

@@ -197,3 +199,34 @@ def test_events_ingested():
197199
logging.INFO,
198200
"action=events_ingested modular_input_name=modular_input_name sourcetype_ingested=sourcetype n_events=5",
199201
)
202+
203+
204+
def test_log_exceptions_full_msg():
205+
start_msg = "some msg before exception"
206+
with mock.patch("logging.Logger") as mock_logger:
207+
try:
208+
test_jsons = "{'a': 'aa'"
209+
json.loads(test_jsons)
210+
except Exception as e:
211+
log.log_exception(mock_logger, e, msg_before=start_msg)
212+
mock_logger.log.assert_called_with(
213+
logging.ERROR, f"{start_msg}\n{traceback.format_exc()}\n"
214+
)
215+
216+
217+
def test_log_exceptions_partial_msg():
218+
start_msg = "some msg before exception"
219+
end_msg = "some msg after exception"
220+
with mock.patch("logging.Logger") as mock_logger:
221+
try:
222+
test_jsons = "{'a': 'aa'"
223+
json.loads(test_jsons)
224+
except Exception as e:
225+
log.log_exception(
226+
mock_logger, e, full_msg=False, msg_before=start_msg, msg_after=end_msg
227+
)
228+
mock_logger.log.assert_called_with(
229+
logging.ERROR,
230+
"some msg before exception\njson.decoder.JSONDecodeError: Expecting property name enclosed in double "
231+
"quotes: line 1 column 2 (char 1)\n\nsome msg after exception",
232+
)

0 commit comments

Comments
 (0)