From d4b872af3f3167a633dcc3e83b58132981482df7 Mon Sep 17 00:00:00 2001 From: Mathieu Pillard Date: Thu, 30 Mar 2017 17:41:08 +0200 Subject: [PATCH] Ensure log formatter doesn't fail with non json-serializable params --- .gitignore | 1 + src/dockerflow/logging.py | 7 ++++++- tests/test_logging.py | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cdc15aa..3a081d9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ coverage.xml docs/_build build dist +*.pyc diff --git a/src/dockerflow/logging.py b/src/dockerflow/logging.py index b9531f4..fcee912 100644 --- a/src/dockerflow/logging.py +++ b/src/dockerflow/logging.py @@ -8,6 +8,11 @@ import traceback +class SafeJSONEncoder(json.JSONEncoder): + def default(self, o): + return repr(o) + + class JsonLogFormatter(logging.Formatter): """Log formatter that outputs machine-readable json. @@ -85,7 +90,7 @@ def format(self, record): out['Fields'] = fields - return json.dumps(out) + return json.dumps(out, cls=SafeJSONEncoder) def safer_format_traceback(exc_typ, exc_val, exc_tb): diff --git a/tests/test_logging.py b/tests/test_logging.py index 1533e89..cb78ae9 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -48,6 +48,20 @@ def test_custom_paramters(caplog): assert details['Fields']['more'] == 'stuff' +def test_non_json_serializable_parameters_are_converted(caplog): + """Ensure log formatter doesn't fail with non json-serializable params.""" + foo = object() + foo_repr = repr(foo) + logger = logging.getLogger('dockerflow.test.test_logging') + logger.warning('custom test %s', 'hello', extra={'foo': foo}) + details = assert_records(caplog.records) + + assert details['Type'] == 'dockerflow.test.test_logging' + assert details['Severity'] == 4 + assert details['Fields']['message'] == 'custom test hello' + assert details['Fields']['foo'] == foo_repr + + def test_logging_error_tracebacks(caplog): """Ensure log formatter includes exception traceback information""" try: