From cf4370e25e1e473fbca2b40099a10e97240242f0 Mon Sep 17 00:00:00 2001 From: Gabe Goodhart Date: Wed, 26 Oct 2022 11:52:10 -0600 Subject: [PATCH 1/2] JsonFormatterSerialization: Perform interpolation of message and args before json.dumps Signed-off-by: Gabe Goodhart --- src/python/alog/alog.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/python/alog/alog.py b/src/python/alog/alog.py index ec13b27..456d22f 100644 --- a/src/python/alog/alog.py +++ b/src/python/alog/alog.py @@ -168,6 +168,15 @@ def format(self, record): if g_thread_id_enabled: log_record['thread_id'] = threading.get_ident() + # Interpolate message and args if present + record_args = log_record.pop('args', None) + if record_args: + message = log_record.get('message') + if message: + log_record['message'] = message % record_args + else: + log_record['message'] = str(record_args) + return json.dumps(log_record, sort_keys=True) class AlogPrettyFormatter(AlogFormatterBase): From 2f7fbe32f197f6eb5e5f1ba96942c622d47845f4 Mon Sep 17 00:00:00 2001 From: Gabe Goodhart Date: Wed, 26 Oct 2022 11:55:07 -0600 Subject: [PATCH 2/2] JsonFormatterSerialization: Add unit tests for an interpolated function Copied from Prashant Gupta's fork https://github.com/IBM/alchemy-logging/pull/239/files#diff-078bcf5f6ff8ff6afc824c75e399912876614b3c3f0f645fa1384f684990ab31R301 https://github.com/IBM/alchemy-logging/issues/238 Signed-off-by: Gabe Goodhart --- src/python/tests/test_alog.py | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/python/tests/test_alog.py b/src/python/tests/test_alog.py index 6dc2def..1ac9eb4 100644 --- a/src/python/tests/test_alog.py +++ b/src/python/tests/test_alog.py @@ -298,6 +298,44 @@ def test_json_json_level_formatting(): assert 'level' in logged_output[0] assert logged_output[0]['level'].lower() == logged_output[0]['level'] +def test_json_with_functions(): + '''Make sure that function arguments are formatted correctly with json''' + + # Configure for log capture + capture_formatter = LogCaptureFormatter('json') + alog.configure(default_level='info', formatter=capture_formatter) + test_channel = alog.use_channel('TEST') + + # Log a message with a function + test_channel.info('Logging a function %s', is_log_msg) + + # Validate that we get a dict back + logged_output = capture_formatter.get_json_records() + assert len(logged_output) == 1 + assert isinstance(logged_output[0], dict) + assert 'level' in logged_output[0] + assert logged_output[0]['level'].lower() == logged_output[0]['level'] + +def test_log_code_json_function(): + '''Test that logging with a log code and the json formatter with a function works as expected. + ''' + # Configure for log capture + capture_formatter = LogCaptureFormatter('json') + alog.configure(default_level='info', formatter=capture_formatter) + test_channel = alog.use_channel('TEST') + + # Log with a code and some functions + test_channel.info(test_code, "Logging 2 functions, %s and %s", is_log_msg, pretty_level_to_name) + logged_output = capture_formatter.get_json_records() + + # Make sure the code and message came through as fields + assert len(logged_output) == 1 + record = logged_output[0] + assert 'log_code' in record + assert record['log_code'] == test_code + assert 'message' in record + assert record['message'] == f"Logging 2 functions, {is_log_msg} and {pretty_level_to_name}" + ## Custom Formatter ############################################################ def test_custom_formatter_pretty_with_args():