summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--changelog.d/11028.feature1
-rw-r--r--synapse/logging/_terse_json.py6
-rw-r--r--tests/logging/test_terse_json.py28
3 files changed, 35 insertions, 0 deletions
diff --git a/changelog.d/11028.feature b/changelog.d/11028.feature
new file mode 100644
index 0000000000..48798356b7
--- /dev/null
+++ b/changelog.d/11028.feature
@@ -0,0 +1 @@
+Include exception information in JSON logging output. Contributed by @Fizzadar at Beeper.
diff --git a/synapse/logging/_terse_json.py b/synapse/logging/_terse_json.py
index 6e82f7c7f1..b78d6e17c9 100644
--- a/synapse/logging/_terse_json.py
+++ b/synapse/logging/_terse_json.py
@@ -65,6 +65,12 @@ class JsonFormatter(logging.Formatter):
             if key not in _IGNORED_LOG_RECORD_ATTRIBUTES:
                 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}"
+
         return _encoder.encode(event)
 
 
diff --git a/tests/logging/test_terse_json.py b/tests/logging/test_terse_json.py
index f73fcd684e..96f399b7ab 100644
--- a/tests/logging/test_terse_json.py
+++ b/tests/logging/test_terse_json.py
@@ -198,3 +198,31 @@ class TerseJsonTestCase(LoggerCleanupMixin, TestCase):
         self.assertEqual(log["url"], "/_matrix/client/versions")
         self.assertEqual(log["protocol"], "1.1")
         self.assertEqual(log["user_agent"], "")
+
+    def test_with_exception(self):
+        """
+        The logging exception type & value should be added to the JSON response.
+        """
+        handler = logging.StreamHandler(self.output)
+        handler.setFormatter(JsonFormatter())
+        logger = self.get_logger(handler)
+
+        try:
+            raise ValueError("That's wrong, you wally!")
+        except ValueError:
+            logger.exception("Hello there, %s!", "wally")
+
+        log = self.get_log_line()
+
+        # The terse logger should give us these keys.
+        expected_log_keys = [
+            "log",
+            "level",
+            "namespace",
+            "exc_type",
+            "exc_value",
+        ]
+        self.assertCountEqual(log.keys(), expected_log_keys)
+        self.assertEqual(log["log"], "Hello there, wally!")
+        self.assertEqual(log["exc_type"], "ValueError")
+        self.assertEqual(log["exc_value"], "That's wrong, you wally!")