Skip to content

Commit

Permalink
feat(logging): Include exception_name (#320)
Browse files Browse the repository at this point in the history
* feat(logging): Include exception_name

* tests(logging): Add test for exception_name

* docs(logging): Add note on exception_name
  • Loading branch information
Michael Brewer authored Mar 9, 2021
1 parent 73c501d commit 0ec47dc
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
19 changes: 19 additions & 0 deletions aws_lambda_powertools/logging/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ def _extract_log_exception(self, log_record: logging.LogRecord) -> Optional[str]

return None

def _extract_log_exception_name(self, log_record: logging.LogRecord) -> Optional[str]:
"""Extract the exception name, if available
Parameters
----------
log_record : logging.LogRecord
Log record to extract exception name from
Returns
-------
log_record: Optional[str]
Log record with exception name
"""
if log_record.exc_info:
return log_record.exc_info[0].__name__

return None

def _extract_log_keys(self, log_record: logging.LogRecord) -> Dict:
"""Extract and parse custom and reserved log keys
Expand Down Expand Up @@ -164,6 +182,7 @@ def _extract_log_keys(self, log_record: logging.LogRecord) -> Dict:
def format(self, record): # noqa: A003
formatted_log = self._extract_log_keys(log_record=record)
formatted_log["message"] = self._extract_log_message(log_record=record)
formatted_log["exception_name"] = self._extract_log_exception_name(log_record=record)
formatted_log["exception"] = self._extract_log_exception(log_record=record)
formatted_log.update({"xray_trace_id": self._get_latest_trace_id()}) # fetch latest Trace ID, if any

Expand Down
3 changes: 2 additions & 1 deletion docs/core/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ You can also change the order of the following log record keys via the `log_reco

#### Logging exceptions

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

=== "logging_an_exception.py"

Expand All @@ -475,6 +475,7 @@ When logging exceptions, Logger will add a new key named `exception`, and will s
"timestamp": "2020-08-28 18:11:38,886",
"service": "service_undefined",
"sampling_rate": 0.0,
"exception_name":"ValueError",
"exception": "Traceback (most recent call last):\n File \"<input>\", line 2, in <module>\nValueError: something went wrong"
}
```
Expand Down
15 changes: 15 additions & 0 deletions tests/functional/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,18 @@ def test_logger_log_twice_when_log_filter_isnt_present_and_root_logger_is_setup(
# since child's log records propagated to root logger should be rejected
logs = list(stdout.getvalue().strip().split("\n"))
assert len(logs) == 4


def test_logger_exception_extract_exception_name(stdout, service_name):
# GIVEN Logger is initialized
logger = Logger(service=service_name, stream=stdout)

# WHEN calling a logger.exception with a ValueError
try:
raise ValueError("something went wrong")
except Exception:
logger.exception("Received an exception")

# THEN we expect a "exception_name" to be "ValueError"
log = capture_logging_output(stdout)
assert "ValueError" == log["exception_name"]

0 comments on commit 0ec47dc

Please sign in to comment.