diff --git a/src/dockerflow/logging.py b/src/dockerflow/logging.py index 2f70071..d4e260b 100644 --- a/src/dockerflow/logging.py +++ b/src/dockerflow/logging.py @@ -123,7 +123,7 @@ def convert_record(self, record): fields["msg"] = message # If there is an error, format it for nice output. - if record.exc_info is not None: + if record.exc_info: fields["error"] = repr(record.exc_info[1]) fields["traceback"] = safer_format_traceback(*record.exc_info) diff --git a/tests/core/test_logging.py b/tests/core/test_logging.py index 60a0fc1..d0c9638 100644 --- a/tests/core/test_logging.py +++ b/tests/core/test_logging.py @@ -5,9 +5,11 @@ import logging import logging.config import os +import sys import textwrap import jsonschema +import pytest from dockerflow.logging import JsonLogFormatter logger_name = "tests" @@ -116,6 +118,41 @@ def test_logging_error_tracebacks(caplog): assert "ValueError" in details["Fields"]["traceback"] +@pytest.mark.skipif(sys.version_info < (3, 5), reason="Requires python >= 3.5") +def test_logging_exc_info_false_3x(caplog): + """Ensure log formatter does not fail and does not include exception + traceback information when exc_info is False under Python 3.x""" + try: + raise ValueError("\n") + except Exception: + logging.exception("there was an error", exc_info=False) + details = assert_records(caplog.records) + + assert details["Severity"] == 3 + assert details["Fields"]["msg"] == "there was an error" + assert "error" not in details["Fields"] + assert "traceback" not in details["Fields"] + + +@pytest.mark.skipif(sys.version_info >= (3,), reason="Requires python 2") +def test_logging_exc_info_false_2x(caplog): + """Ensure log formatter does not fail *but* still includes exception + traceback information when exc_info is False under Python 2.x""" + try: + raise ValueError("\n") + except Exception: + logging.exception("there was an error", exc_info=False) + details = assert_records(caplog.records) + + assert details["Severity"] == 3 + assert details["Fields"]["msg"] == "there was an error" + # In Python 2, when exc_info=False is passed, we still see a tuple in the + # formatter, so we still include the error and traceback keys. + assert details["Fields"]["error"].startswith("ValueError('\\n'") + assert details["Fields"]["traceback"].startswith("Uncaught exception:") + assert "ValueError" in details["Fields"]["traceback"] + + def test_ignore_json_message(caplog): """Ensure log formatter ignores messages that are JSON already""" try: