Skip to content

Commit 0ec47dc

Browse files
author
Michael Brewer
authored
feat(logging): Include exception_name (#320)
* feat(logging): Include exception_name * tests(logging): Add test for exception_name * docs(logging): Add note on exception_name
1 parent 73c501d commit 0ec47dc

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

aws_lambda_powertools/logging/formatter.py

+19
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ def _extract_log_exception(self, log_record: logging.LogRecord) -> Optional[str]
126126

127127
return None
128128

129+
def _extract_log_exception_name(self, log_record: logging.LogRecord) -> Optional[str]:
130+
"""Extract the exception name, if available
131+
132+
Parameters
133+
----------
134+
log_record : logging.LogRecord
135+
Log record to extract exception name from
136+
137+
Returns
138+
-------
139+
log_record: Optional[str]
140+
Log record with exception name
141+
"""
142+
if log_record.exc_info:
143+
return log_record.exc_info[0].__name__
144+
145+
return None
146+
129147
def _extract_log_keys(self, log_record: logging.LogRecord) -> Dict:
130148
"""Extract and parse custom and reserved log keys
131149
@@ -164,6 +182,7 @@ def _extract_log_keys(self, log_record: logging.LogRecord) -> Dict:
164182
def format(self, record): # noqa: A003
165183
formatted_log = self._extract_log_keys(log_record=record)
166184
formatted_log["message"] = self._extract_log_message(log_record=record)
185+
formatted_log["exception_name"] = self._extract_log_exception_name(log_record=record)
167186
formatted_log["exception"] = self._extract_log_exception(log_record=record)
168187
formatted_log.update({"xray_trace_id": self._get_latest_trace_id()}) # fetch latest Trace ID, if any
169188

docs/core/logger.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ You can also change the order of the following log record keys via the `log_reco
451451

452452
#### Logging exceptions
453453

454-
When logging exceptions, Logger will add a new key named `exception`, and will serialize the full traceback as a string.
454+
When logging exceptions, Logger will add new keys named `exception_name` and `exception` with the full traceback as a string.
455455

456456
=== "logging_an_exception.py"
457457

@@ -475,6 +475,7 @@ When logging exceptions, Logger will add a new key named `exception`, and will s
475475
"timestamp": "2020-08-28 18:11:38,886",
476476
"service": "service_undefined",
477477
"sampling_rate": 0.0,
478+
"exception_name":"ValueError",
478479
"exception": "Traceback (most recent call last):\n File \"<input>\", line 2, in <module>\nValueError: something went wrong"
479480
}
480481
```

tests/functional/test_logger.py

+15
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,18 @@ def test_logger_log_twice_when_log_filter_isnt_present_and_root_logger_is_setup(
422422
# since child's log records propagated to root logger should be rejected
423423
logs = list(stdout.getvalue().strip().split("\n"))
424424
assert len(logs) == 4
425+
426+
427+
def test_logger_exception_extract_exception_name(stdout, service_name):
428+
# GIVEN Logger is initialized
429+
logger = Logger(service=service_name, stream=stdout)
430+
431+
# WHEN calling a logger.exception with a ValueError
432+
try:
433+
raise ValueError("something went wrong")
434+
except Exception:
435+
logger.exception("Received an exception")
436+
437+
# THEN we expect a "exception_name" to be "ValueError"
438+
log = capture_logging_output(stdout)
439+
assert "ValueError" == log["exception_name"]

0 commit comments

Comments
 (0)