Skip to content

Commit a0c0e68

Browse files
committed
bpo-32732: Don't override extra keys on LoggerAdapter
1 parent 6dd69f4 commit a0c0e68

File tree

4 files changed

+49
-3
lines changed

4 files changed

+49
-3
lines changed

Doc/howto/logging-cookbook.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,12 @@ and keyword arguments of the logging call, and it passes back (potentially)
593593
modified versions of these to use in the call to the underlying logger. The
594594
default implementation of this method leaves the message alone, but inserts
595595
an 'extra' key in the keyword argument whose value is the dict-like object
596-
passed to the constructor. Of course, if you had passed an 'extra' keyword
597-
argument in the call to the adapter, it will be silently overwritten.
596+
passed to the constructor.
597+
598+
.. versionadded:: 3.11
599+
:meth:`~LoggerAdapter.process` has been changed to not erase any 'extra' keys
600+
provided to :func:`log`. In case of a conlfict of keys, the ones passed to
601+
:func:`log` will take precedence.
598602

599603
The advantage of using 'extra' is that the values in the dict-like object are
600604
merged into the :class:`LogRecord` instance's __dict__, allowing you to use

Doc/library/logging.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,11 @@ interchangeably.
900900
:meth:`~Logger.setLevel` and :meth:`~Logger.hasHandlers` methods were added
901901
to :class:`LoggerAdapter`. These methods delegate to the underlying logger.
902902

903+
.. versionadded:: 3.11
904+
:meth:`~LoggerAdapter.process` has been changed to not erase any 'extra' keys
905+
provided to :func:`log`. In case of a conlfict of keys, the ones passed to
906+
:func:`log` will take precedence.
907+
903908

904909
Thread Safety
905910
-------------

Lib/logging/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1817,7 +1817,7 @@ def process(self, msg, kwargs):
18171817
Normally, you'll only need to override this one method in a
18181818
LoggerAdapter subclass for your specific needs.
18191819
"""
1820-
kwargs["extra"] = self.extra
1820+
kwargs["extra"] = (self.extra or {}) | (kwargs.get("extra") or {})
18211821
return msg, kwargs
18221822

18231823
#

Lib/test/test_logging.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4932,6 +4932,43 @@ def process(self, msg, kwargs):
49324932
self.assertIs(adapter.manager, orig_manager)
49334933
self.assertIs(self.logger.manager, orig_manager)
49344934

4935+
def test_extra(self):
4936+
4937+
# Adapter with empty extra
4938+
adapter = logging.LoggerAdapter(logger=self.logger)
4939+
self.assertEqual(
4940+
adapter.process(
4941+
msg="", kwargs={"extra": {"log_key": "log_value"}}
4942+
),
4943+
("", {"extra": {"log_key": "log_value"}}),
4944+
)
4945+
4946+
# Apend process' extra to Adapter's
4947+
# Reset adapter's extra, as it was changed by previous process call
4948+
adapter.extra = {"adapter_key": "adapter_value"}
4949+
self.assertEqual(
4950+
adapter.process(
4951+
msg="", kwargs={"extra": {"log_key": "log_value"}}
4952+
),
4953+
(
4954+
"",
4955+
{
4956+
"extra": {
4957+
"adapter_key": "adapter_value",
4958+
"log_key": "log_value",
4959+
}
4960+
},
4961+
),
4962+
)
4963+
4964+
# Override adapter value on process'
4965+
self.assertEqual(
4966+
adapter.process(
4967+
msg="", kwargs={"extra": {"adapter_key": "overriden_value"}}
4968+
),
4969+
("", {"extra": {"adapter_key": "overriden_value"}}),
4970+
)
4971+
49354972

49364973
class LoggerTest(BaseTest, AssertErrorMessage):
49374974

0 commit comments

Comments
 (0)