Skip to content

Commit dad28e8

Browse files
committed
tests: Add a test case that verifies behavior when the log record factory is modified
The test currently fails with the following error: $ PYTHONPATH=$(pwd)/tests:$PYTHONPATH python3 -m unittest -v log_handler_test ... test_logrecordfactory (log_handler_test.LogRecordFactoryTest.test_logrecordfactory) ... --- Logging error --- Traceback (most recent call last): File "/usr/lib/python3.12/logging/__init__.py", line 464, in format return self._format(record) ^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 460, in _format return self._fmt % values ~~~~~~~~~~^~~~~~~~ KeyError: 'custom_attribute' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3.12/logging/__init__.py", line 1160, in emit msg = self.format(record) ^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 999, in format return fmt.format(record) ^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 999, in format return fmt.format(record) ^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 706, in format s = self.formatMessage(record) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 675, in formatMessage return self._style.format(record) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/logging/__init__.py", line 466, in format raise ValueError('Formatting field not found in record: %s' % e) ValueError: Formatting field not found in record: 'custom_attribute' Signed-off-by: Marc Hartmayer <[email protected]>
1 parent 3c648f7 commit dad28e8

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

tests/log_handler_test.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,28 @@
1414
import mitogen.utils
1515
from mitogen.core import b
1616

17+
PY2 = sys.version_info[0] == 2
18+
if PY2:
19+
20+
def logging_getLogRecordFactory():
21+
return logging.LogRecord
22+
23+
def logging_setLogRecordFactory(factory):
24+
logging.LogRecord = factory
25+
26+
else:
27+
logging_getLogRecordFactory = logging.getLogRecordFactory
28+
logging_setLogRecordFactory = logging.setLogRecordFactory
29+
1730

1831
def ping():
1932
pass
2033

2134

35+
def log_test():
36+
logging.getLogger(__name__).info("This is a test")
37+
38+
2239
class BufferingTest(testlib.TestCase):
2340
klass = mitogen.core.LogHandler
2441

@@ -89,6 +106,36 @@ def test_earliest_messages_logged_via(self):
89106
expect = 'Parent is context %s (%s)' % (c1.context_id, 'parent')
90107
self.assertIn(expect, logs)
91108

109+
110+
class LogRecordFactoryTest(testlib.RouterMixin, testlib.TestCase):
111+
def setUp(self):
112+
super(LogRecordFactoryTest, self).setUp()
113+
self.original_factory = logging_getLogRecordFactory()
114+
115+
def tearDown(self):
116+
logging_setLogRecordFactory(self.original_factory)
117+
super(LogRecordFactoryTest, self).tearDown()
118+
119+
def test_logrecordfactory(self):
120+
# Change logging factory and add a custom attribute
121+
old_factory = logging_getLogRecordFactory()
122+
123+
def record_factory(*args, **kwargs):
124+
record = old_factory(*args, **kwargs)
125+
record.custom_attribute = 0xDEADBEEF
126+
return record
127+
128+
logging_setLogRecordFactory(record_factory)
129+
c1 = self.router.local(name="c1")
130+
log = testlib.LogCapturer(
131+
__name__, formatter=logging.Formatter("%(custom_attribute)x - %(message)s")
132+
)
133+
log.start()
134+
c1.call(log_test)
135+
logs = log.stop()
136+
self.assertIn("deadbeef - This is a test", logs)
137+
138+
92139
StartupTest = unittest.skipIf(
93140
condition=sys.version_info < (2, 7) or sys.version_info >= (3, 6),
94141
reason="Message log flaky on Python < 2.7 or >= 3.6"

tests/testlib.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,13 @@ def emit(self, msg):
393393

394394

395395
class LogCapturer(object):
396-
def __init__(self, name=None):
396+
def __init__(self, name=None, formatter=None):
397397
self.sio = StringIO()
398398
self.logger = logging.getLogger(name)
399-
self.handler = CaptureStreamHandler(self.sio)
399+
handler = CaptureStreamHandler(self.sio)
400+
if formatter is not None:
401+
handler.setFormatter(formatter)
402+
self.handler = handler
400403
self.old_propagate = self.logger.propagate
401404
self.old_handlers = self.logger.handlers
402405
self.old_level = self.logger.level

0 commit comments

Comments
 (0)