Commit 58bb3b81e76cfa6f46eaa57e686a7bac625c0f48
1 parent
7f315674
log_helper: Test and improve error-handling
If there is an error in log-handling (e.g. wrong args to logger call) do not fail or raise but produce something helpful
Showing
3 changed files
with
28 additions
and
5 deletions
oletools/common/log_helper/_json_formatter.py
| ... | ... | @@ -32,15 +32,25 @@ class JsonFormatter(logging.Formatter): |
| 32 | 32 | :py:class:`oletools.common.log_helper.OletoolsLoggerAdapter` or added here |
| 33 | 33 | (for input from e.g. captured warnings, third-party libraries) |
| 34 | 34 | """ |
| 35 | - msg = self.msg_formatter.format(record) | |
| 36 | - json_dict = dict(msg=msg.replace('\n', ' '), level=record.levelname) | |
| 35 | + json_dict = dict(msg='', level='', type='') | |
| 37 | 36 | try: |
| 37 | + msg = self.msg_formatter.format(record) | |
| 38 | + json_dict['msg'] = msg.replace('\n', ' ') | |
| 39 | + json_dict['level'] = record.levelname | |
| 38 | 40 | json_dict['type'] = record.type |
| 39 | - except AttributeError: | |
| 40 | - if record.name == 'py.warnings': # this is the name of the logger | |
| 41 | + except AttributeError: # most probably: record has no "type" field | |
| 42 | + if record.name == 'py.warnings': # this is from python's warning-capture logger | |
| 41 | 43 | json_dict['type'] = 'warning' |
| 42 | 44 | else: |
| 43 | - json_dict['type'] = 'msg' | |
| 45 | + json_dict['type'] = 'msg' # message of unknown origin | |
| 46 | + except Exception as exc: | |
| 47 | + try: | |
| 48 | + json_dict['msg'] = "Ignore {0} when formatting '{1}': {2}".format(type(exc), record.msg, exc) | |
| 49 | + except Exception as exc2: | |
| 50 | + json_dict['msg'] = 'Caught {0} in logging'.format(str(exc2)) | |
| 51 | + json_dict['type'] = 'log-warning' | |
| 52 | + json_dict['level'] = 'warning' | |
| 53 | + | |
| 44 | 54 | formatted_message = ' ' + json.dumps(json_dict) |
| 45 | 55 | |
| 46 | 56 | if self._is_first_line: | ... | ... |
tests/common/log_helper/log_helper_test_main.py
| ... | ... | @@ -50,6 +50,7 @@ def main(args): |
| 50 | 50 | percent_autoformat = '%-autoformat' in args |
| 51 | 51 | warn = 'warn' in args |
| 52 | 52 | exc_info = 'exc-info' in args |
| 53 | + wrong_log_args = 'wrong-log-args' in args | |
| 53 | 54 | |
| 54 | 55 | log_helper_test_imported.logger.setLevel(logging.ERROR) |
| 55 | 56 | |
| ... | ... | @@ -71,6 +72,12 @@ def main(args): |
| 71 | 72 | except Exception: |
| 72 | 73 | logger.exception('Caught exception') # has exc_info=True |
| 73 | 74 | |
| 75 | + if wrong_log_args: | |
| 76 | + logger.info('Opening file /dangerous/file/with-%s-in-name') | |
| 77 | + logger.info('The result is %f') | |
| 78 | + logger.info('No result', 1.23) | |
| 79 | + logger.info('The result is %f', 'bla') | |
| 80 | + | |
| 74 | 81 | log_helper.end_logging() |
| 75 | 82 | |
| 76 | 83 | ... | ... |
tests/common/log_helper/test_log_helper.py
| ... | ... | @@ -224,6 +224,12 @@ class TestLogHelper(unittest.TestCase): |
| 224 | 224 | self.assertIn('Traceback (most recent call last)', output) # start of trace |
| 225 | 225 | self.assertIn(TEST_FILE, output) # part of trace |
| 226 | 226 | |
| 227 | + def test_json_wrong_args(self): | |
| 228 | + """Test that too many or missing args do not raise exceptions inside logger""" | |
| 229 | + output = self._run_test(['enable', 'as-json', 'wrong-log-args', 'info']) | |
| 230 | + json.loads(output) # check that this does not raise, so json is valid | |
| 231 | + # do not care about actual contents of output | |
| 232 | + | |
| 227 | 233 | def _assert_json_messages(self, output, messages): |
| 228 | 234 | try: |
| 229 | 235 | json_data = json.loads(output) | ... | ... |