mirror of https://github.com/python/cpython
gh-76913: Add "merge extras" feature to LoggerAdapter (GH-107292)
This commit is contained in:
parent
580f357c66
commit
a482e5bf00
|
@ -1002,10 +1002,14 @@ LoggerAdapter Objects
|
||||||
information into logging calls. For a usage example, see the section on
|
information into logging calls. For a usage example, see the section on
|
||||||
:ref:`adding contextual information to your logging output <context-info>`.
|
:ref:`adding contextual information to your logging output <context-info>`.
|
||||||
|
|
||||||
.. class:: LoggerAdapter(logger, extra)
|
.. class:: LoggerAdapter(logger, extra, merge_extra=False)
|
||||||
|
|
||||||
Returns an instance of :class:`LoggerAdapter` initialized with an
|
Returns an instance of :class:`LoggerAdapter` initialized with an
|
||||||
underlying :class:`Logger` instance and a dict-like object.
|
underlying :class:`Logger` instance, a dict-like object (*extra*), and a
|
||||||
|
boolean (*merge_extra*) indicating whether or not the *extra* argument of
|
||||||
|
individual log calls should be merged with the :class:`LoggerAdapter` extra.
|
||||||
|
The default behavior is to ignore the *extra* argument of individual log
|
||||||
|
calls and only use the one of the :class:`LoggerAdapter` instance
|
||||||
|
|
||||||
.. method:: process(msg, kwargs)
|
.. method:: process(msg, kwargs)
|
||||||
|
|
||||||
|
@ -1037,6 +1041,9 @@ interchangeably.
|
||||||
Remove the undocumented ``warn()`` method which was an alias to the
|
Remove the undocumented ``warn()`` method which was an alias to the
|
||||||
``warning()`` method.
|
``warning()`` method.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.13
|
||||||
|
The *merge_extra* argument was added.
|
||||||
|
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -1879,7 +1879,7 @@ class LoggerAdapter(object):
|
||||||
information in logging output.
|
information in logging output.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, logger, extra=None):
|
def __init__(self, logger, extra=None, merge_extra=False):
|
||||||
"""
|
"""
|
||||||
Initialize the adapter with a logger and a dict-like object which
|
Initialize the adapter with a logger and a dict-like object which
|
||||||
provides contextual information. This constructor signature allows
|
provides contextual information. This constructor signature allows
|
||||||
|
@ -1889,9 +1889,20 @@ class LoggerAdapter(object):
|
||||||
following example:
|
following example:
|
||||||
|
|
||||||
adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
|
adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
|
||||||
|
|
||||||
|
By default, LoggerAdapter objects will drop the "extra" argument
|
||||||
|
passed on the individual log calls to use its own instead.
|
||||||
|
|
||||||
|
Initializing it with merge_extra=True will instead merge both
|
||||||
|
maps when logging, the individual call extra taking precedence
|
||||||
|
over the LoggerAdapter instance extra
|
||||||
|
|
||||||
|
.. versionchanged:: 3.13
|
||||||
|
The *merge_extra* argument was added.
|
||||||
"""
|
"""
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.extra = extra
|
self.extra = extra
|
||||||
|
self.merge_extra = merge_extra
|
||||||
|
|
||||||
def process(self, msg, kwargs):
|
def process(self, msg, kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1903,7 +1914,10 @@ class LoggerAdapter(object):
|
||||||
Normally, you'll only need to override this one method in a
|
Normally, you'll only need to override this one method in a
|
||||||
LoggerAdapter subclass for your specific needs.
|
LoggerAdapter subclass for your specific needs.
|
||||||
"""
|
"""
|
||||||
kwargs["extra"] = self.extra
|
if self.merge_extra and "extra" in kwargs:
|
||||||
|
kwargs["extra"] = {**self.extra, **kwargs["extra"]}
|
||||||
|
else:
|
||||||
|
kwargs["extra"] = self.extra
|
||||||
return msg, kwargs
|
return msg, kwargs
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -5433,6 +5433,46 @@ class LoggerAdapterTest(unittest.TestCase):
|
||||||
self.assertIs(adapter.manager, orig_manager)
|
self.assertIs(adapter.manager, orig_manager)
|
||||||
self.assertIs(self.logger.manager, orig_manager)
|
self.assertIs(self.logger.manager, orig_manager)
|
||||||
|
|
||||||
|
def test_extra_in_records(self):
|
||||||
|
self.adapter = logging.LoggerAdapter(logger=self.logger,
|
||||||
|
extra={'foo': '1'})
|
||||||
|
|
||||||
|
self.adapter.critical('foo should be here')
|
||||||
|
self.assertEqual(len(self.recording.records), 1)
|
||||||
|
record = self.recording.records[0]
|
||||||
|
self.assertTrue(hasattr(record, 'foo'))
|
||||||
|
self.assertEqual(record.foo, '1')
|
||||||
|
|
||||||
|
def test_extra_not_merged_by_default(self):
|
||||||
|
self.adapter.critical('foo should NOT be here', extra={'foo': 'nope'})
|
||||||
|
self.assertEqual(len(self.recording.records), 1)
|
||||||
|
record = self.recording.records[0]
|
||||||
|
self.assertFalse(hasattr(record, 'foo'))
|
||||||
|
|
||||||
|
def test_extra_merged(self):
|
||||||
|
self.adapter = logging.LoggerAdapter(logger=self.logger,
|
||||||
|
extra={'foo': '1'},
|
||||||
|
merge_extra=True)
|
||||||
|
|
||||||
|
self.adapter.critical('foo and bar should be here', extra={'bar': '2'})
|
||||||
|
self.assertEqual(len(self.recording.records), 1)
|
||||||
|
record = self.recording.records[0]
|
||||||
|
self.assertTrue(hasattr(record, 'foo'))
|
||||||
|
self.assertTrue(hasattr(record, 'bar'))
|
||||||
|
self.assertEqual(record.foo, '1')
|
||||||
|
self.assertEqual(record.bar, '2')
|
||||||
|
|
||||||
|
def test_extra_merged_log_call_has_precedence(self):
|
||||||
|
self.adapter = logging.LoggerAdapter(logger=self.logger,
|
||||||
|
extra={'foo': '1'},
|
||||||
|
merge_extra=True)
|
||||||
|
|
||||||
|
self.adapter.critical('foo shall be min', extra={'foo': '2'})
|
||||||
|
self.assertEqual(len(self.recording.records), 1)
|
||||||
|
record = self.recording.records[0]
|
||||||
|
self.assertTrue(hasattr(record, 'foo'))
|
||||||
|
self.assertEqual(record.foo, '2')
|
||||||
|
|
||||||
|
|
||||||
class LoggerTest(BaseTest, AssertErrorMessage):
|
class LoggerTest(BaseTest, AssertErrorMessage):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add *merge_extra* parameter/feature to :class:`logging.LoggerAdapter`
|
Loading…
Reference in New Issue