mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Merge pull request #2753 from avaris/log-dict
Fix dictionary logging in formatter
This commit is contained in:
commit
ca1c58e201
3 changed files with 108 additions and 43 deletions
|
|
@ -2,6 +2,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from collections.abc import Mapping
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'init'
|
'init'
|
||||||
|
|
@ -18,9 +19,10 @@ class BaseFormatter(logging.Formatter):
|
||||||
record.__dict__['customlevelname'] = customlevel
|
record.__dict__['customlevelname'] = customlevel
|
||||||
# format multiline messages 'nicely' to make it clear they are together
|
# format multiline messages 'nicely' to make it clear they are together
|
||||||
record.msg = record.msg.replace('\n', '\n | ')
|
record.msg = record.msg.replace('\n', '\n | ')
|
||||||
record.args = tuple(arg.replace('\n', '\n | ') if
|
if not isinstance(record.args, Mapping):
|
||||||
isinstance(arg, str) else
|
record.args = tuple(arg.replace('\n', '\n | ') if
|
||||||
arg for arg in record.args)
|
isinstance(arg, str) else
|
||||||
|
arg for arg in record.args)
|
||||||
return super().format(record)
|
return super().format(record)
|
||||||
|
|
||||||
def formatException(self, ei):
|
def formatException(self, ei):
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,15 @@ class LogCountHandler(BufferingHandler):
|
||||||
(level is None or l.levelno == level)
|
(level is None or l.levelno == level)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def count_formatted_logs(self, msg=None, level=None):
|
||||||
|
return len([
|
||||||
|
l
|
||||||
|
for l
|
||||||
|
in self.buffer
|
||||||
|
if (msg is None or re.search(msg, self.format(l))) and
|
||||||
|
(level is None or l.levelno == level)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class LoggedTestCase(unittest.TestCase):
|
class LoggedTestCase(unittest.TestCase):
|
||||||
"""A test case that captures log messages."""
|
"""A test case that captures log messages."""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import unittest
|
import unittest
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from pelican import log
|
from pelican import log
|
||||||
from pelican.tests.support import LogCountHandler
|
from pelican.tests.support import LogCountHandler
|
||||||
|
|
@ -11,6 +12,7 @@ class TestLog(unittest.TestCase):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.handler = LogCountHandler()
|
self.handler = LogCountHandler()
|
||||||
|
self.handler.setFormatter(log.get_formatter())
|
||||||
self.logger.addHandler(self.handler)
|
self.logger.addHandler(self.handler)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
|
@ -24,55 +26,107 @@ class TestLog(unittest.TestCase):
|
||||||
log.LimitFilter._threshold = 5
|
log.LimitFilter._threshold = 5
|
||||||
log.LimitFilter._group_count = defaultdict(int)
|
log.LimitFilter._group_count = defaultdict(int)
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def reset_logger(self):
|
||||||
|
try:
|
||||||
|
yield None
|
||||||
|
finally:
|
||||||
|
self._reset_limit_filter()
|
||||||
|
self.handler.flush()
|
||||||
|
|
||||||
|
def test_log_formatter(self):
|
||||||
|
counter = self.handler.count_formatted_logs
|
||||||
|
with self.reset_logger():
|
||||||
|
# log simple case
|
||||||
|
self.logger.warning('Log %s', 'test')
|
||||||
|
self.assertEqual(
|
||||||
|
counter('Log test', logging.WARNING),
|
||||||
|
1)
|
||||||
|
|
||||||
|
with self.reset_logger():
|
||||||
|
# log multiline message
|
||||||
|
self.logger.warning('Log\n%s', 'test')
|
||||||
|
# Log
|
||||||
|
# | test
|
||||||
|
self.assertEqual(
|
||||||
|
counter('Log', logging.WARNING),
|
||||||
|
1)
|
||||||
|
self.assertEqual(
|
||||||
|
counter(' | test', logging.WARNING),
|
||||||
|
1)
|
||||||
|
|
||||||
|
with self.reset_logger():
|
||||||
|
# log multiline argument
|
||||||
|
self.logger.warning('Log %s', 'test1\ntest2')
|
||||||
|
# Log test1
|
||||||
|
# | test2
|
||||||
|
self.assertEqual(
|
||||||
|
counter('Log test1', logging.WARNING),
|
||||||
|
1)
|
||||||
|
self.assertEqual(
|
||||||
|
counter(' | test2', logging.WARNING),
|
||||||
|
1)
|
||||||
|
|
||||||
|
with self.reset_logger():
|
||||||
|
# log single list
|
||||||
|
self.logger.warning('Log %s', ['foo', 'bar'])
|
||||||
|
self.assertEqual(
|
||||||
|
counter(r"Log \['foo', 'bar'\]", logging.WARNING),
|
||||||
|
1)
|
||||||
|
|
||||||
|
with self.reset_logger():
|
||||||
|
# log single dict
|
||||||
|
self.logger.warning('Log %s', {'foo': 1, 'bar': 2})
|
||||||
|
self.assertEqual(
|
||||||
|
# dict order is not guaranteed
|
||||||
|
counter(r"Log {'.*': \d, '.*': \d}", logging.WARNING),
|
||||||
|
1)
|
||||||
|
|
||||||
def test_log_filter(self):
|
def test_log_filter(self):
|
||||||
def do_logging():
|
def do_logging():
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
self.logger.warning('Log %s', i)
|
self.logger.warning('Log %s', i)
|
||||||
self.logger.warning('Another log %s', i)
|
self.logger.warning('Another log %s', i)
|
||||||
# no filter
|
# no filter
|
||||||
do_logging()
|
with self.reset_logger():
|
||||||
self.assertEqual(
|
do_logging()
|
||||||
self.handler.count_logs('Log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
5)
|
self.handler.count_logs('Log \\d', logging.WARNING),
|
||||||
self.assertEqual(
|
5)
|
||||||
self.handler.count_logs('Another log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
5)
|
self.handler.count_logs('Another log \\d', logging.WARNING),
|
||||||
self.handler.flush()
|
5)
|
||||||
self._reset_limit_filter()
|
|
||||||
|
|
||||||
# filter by template
|
# filter by template
|
||||||
log.LimitFilter._ignore.add((logging.WARNING, 'Log %s'))
|
with self.reset_logger():
|
||||||
do_logging()
|
log.LimitFilter._ignore.add((logging.WARNING, 'Log %s'))
|
||||||
self.assertEqual(
|
do_logging()
|
||||||
self.handler.count_logs('Log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
0)
|
self.handler.count_logs('Log \\d', logging.WARNING),
|
||||||
self.assertEqual(
|
0)
|
||||||
self.handler.count_logs('Another log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
5)
|
self.handler.count_logs('Another log \\d', logging.WARNING),
|
||||||
self.handler.flush()
|
5)
|
||||||
self._reset_limit_filter()
|
|
||||||
|
|
||||||
# filter by exact message
|
# filter by exact message
|
||||||
log.LimitFilter._ignore.add((logging.WARNING, 'Log 3'))
|
with self.reset_logger():
|
||||||
do_logging()
|
log.LimitFilter._ignore.add((logging.WARNING, 'Log 3'))
|
||||||
self.assertEqual(
|
do_logging()
|
||||||
self.handler.count_logs('Log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
4)
|
self.handler.count_logs('Log \\d', logging.WARNING),
|
||||||
self.assertEqual(
|
4)
|
||||||
self.handler.count_logs('Another log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
5)
|
self.handler.count_logs('Another log \\d', logging.WARNING),
|
||||||
self.handler.flush()
|
5)
|
||||||
self._reset_limit_filter()
|
|
||||||
|
|
||||||
# filter by both
|
# filter by both
|
||||||
log.LimitFilter._ignore.add((logging.WARNING, 'Log 3'))
|
with self.reset_logger():
|
||||||
log.LimitFilter._ignore.add((logging.WARNING, 'Another log %s'))
|
log.LimitFilter._ignore.add((logging.WARNING, 'Log 3'))
|
||||||
do_logging()
|
log.LimitFilter._ignore.add((logging.WARNING, 'Another log %s'))
|
||||||
self.assertEqual(
|
do_logging()
|
||||||
self.handler.count_logs('Log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
4)
|
self.handler.count_logs('Log \\d', logging.WARNING),
|
||||||
self.assertEqual(
|
4)
|
||||||
self.handler.count_logs('Another log \\d', logging.WARNING),
|
self.assertEqual(
|
||||||
0)
|
self.handler.count_logs('Another log \\d', logging.WARNING),
|
||||||
self.handler.flush()
|
0)
|
||||||
self._reset_limit_filter()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue