diff --git a/synapse/logging/_terse_json.py b/synapse/logging/_terse_json.py index b78d6e17c93c..0abde2fb50dc 100644 --- a/synapse/logging/_terse_json.py +++ b/synapse/logging/_terse_json.py @@ -17,6 +17,7 @@ """ import json import logging +import traceback _encoder = json.JSONEncoder(ensure_ascii=False, separators=(",", ":")) @@ -49,6 +50,22 @@ } +def _extract_exc_info(record: logging.LogRecord) -> dict: + exc_info = {} + + exc_type, exc_value, exc_tb = record.exc_info + + if exc_type: + exc_info["exc_type"] = f"{exc_type.__name__}" + exc_info["exc_value"] = f"{exc_value}" + + frame_summary = traceback.extract_tb(exc_tb, limit=1)[0] + exc_info["exc_filename"] = frame_summary.filename + exc_info["exc_lineno"] = frame_summary.lineno + + return exc_info + + class JsonFormatter(logging.Formatter): def format(self, record: logging.LogRecord) -> str: event = { @@ -66,10 +83,7 @@ def _format(self, record: logging.LogRecord, event: dict) -> str: event[key] = value if record.exc_info: - exc_type, exc_value, _ = record.exc_info - if exc_type: - event["exc_type"] = f"{exc_type.__name__}" - event["exc_value"] = f"{exc_value}" + event.update(_extract_exc_info(record)) return _encoder.encode(event) diff --git a/tests/logging/test_terse_json.py b/tests/logging/test_terse_json.py index 96f399b7abf4..0cf83eae7ccc 100644 --- a/tests/logging/test_terse_json.py +++ b/tests/logging/test_terse_json.py @@ -221,6 +221,8 @@ def test_with_exception(self): "namespace", "exc_type", "exc_value", + "exc_filename", + "exc_lineno", ] self.assertCountEqual(log.keys(), expected_log_keys) self.assertEqual(log["log"], "Hello there, wally!")