logging: Added getLogRecordFactory/setLogRecordFactory with docs and tests.
This commit is contained in:
parent
97cbb76ee3
commit
615615291f
@ -750,6 +750,19 @@ functions.
|
|||||||
# ... override behaviour here
|
# ... override behaviour here
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: getLogRecordFactory()
|
||||||
|
|
||||||
|
Return a callable which is used to create a :class:`LogRecord`.
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
This function has been provided, along with :func:`setLogRecordFactory`,
|
||||||
|
to allow developers more control over how the :class:`LogRecord`
|
||||||
|
representing a logging event is constructed.
|
||||||
|
|
||||||
|
See :func:`setLogRecordFactory` for more information about the how the
|
||||||
|
factory is called.
|
||||||
|
|
||||||
.. function:: debug(msg, *args, **kwargs)
|
.. function:: debug(msg, *args, **kwargs)
|
||||||
|
|
||||||
Logs a message with level :const:`DEBUG` on the root logger. The *msg* is the
|
Logs a message with level :const:`DEBUG` on the root logger. The *msg* is the
|
||||||
@ -973,6 +986,34 @@ functions.
|
|||||||
function is typically called before any loggers are instantiated by applications
|
function is typically called before any loggers are instantiated by applications
|
||||||
which need to use custom logger behavior.
|
which need to use custom logger behavior.
|
||||||
|
|
||||||
|
.. function:: setLogRecordFactory(factory)
|
||||||
|
|
||||||
|
Set a callable which is used to create a :class:`LogRecord`.
|
||||||
|
|
||||||
|
:param factory: The factory callable to be used to instantiate a log record.
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
This function has been provided, along with :func:`getLogRecordFactory`, to
|
||||||
|
allow developers more control over how the :class:`LogRecord` representing
|
||||||
|
a logging event is constructed.
|
||||||
|
|
||||||
|
The factory has the following signature.
|
||||||
|
|
||||||
|
factory(name, level, fn, lno, msg, args, exc_info, func=None, sinfo=None, \*\*kwargs)
|
||||||
|
|
||||||
|
:name: The logger name.
|
||||||
|
:level: The logging level (numeric).
|
||||||
|
:fn: The full pathname of the file where the logging call was made.
|
||||||
|
:lno: The line number in the file where the logging call was made.
|
||||||
|
:msg: The logging message.
|
||||||
|
:args: The arguments for the logging message.
|
||||||
|
:exc_info: An exception tuple, or None.
|
||||||
|
:func: The name of the function or method which invoked the logging
|
||||||
|
call.
|
||||||
|
:sinfo: A stack traceback such as is provided by
|
||||||
|
:func:`traceback.print_stack`, showing the call hierarchy.
|
||||||
|
:kwargs: Additional keyword arguments.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
@ -3244,6 +3285,29 @@ wire).
|
|||||||
messages, whose ``__str__`` method can return the actual format string to
|
messages, whose ``__str__`` method can return the actual format string to
|
||||||
be used.
|
be used.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
The creation of a ``LogRecord`` has been made more configurable by
|
||||||
|
providing a factory which is used to create the record. The factory can be
|
||||||
|
set using :func:`getLogRecordFactory` and :func:`setLogRecordFactory`
|
||||||
|
(see this for the factory's signature).
|
||||||
|
|
||||||
|
This functionality can be used to inject your own values into a
|
||||||
|
LogRecord at creation time. You can use the following pattern::
|
||||||
|
|
||||||
|
old_factory = logging.getLogRecordFactory()
|
||||||
|
|
||||||
|
def record_factory(*args, **kwargs):
|
||||||
|
record = old_factory(*args, **kwargs)
|
||||||
|
record.custom_attribute = 0xdecafbad
|
||||||
|
return record
|
||||||
|
|
||||||
|
logging.setLogRecordFactory(record_factory)
|
||||||
|
|
||||||
|
With this pattern, multiple factories could be chained, and as long
|
||||||
|
as they don't overwrite each other's attributes or unintentionally
|
||||||
|
overwrite the standard attributes listed above, there should be no
|
||||||
|
surprises.
|
||||||
|
|
||||||
.. _logger-adapter:
|
.. _logger-adapter:
|
||||||
|
|
||||||
LoggerAdapter Objects
|
LoggerAdapter Objects
|
||||||
|
@ -33,7 +33,7 @@ __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
|
|||||||
'captureWarnings', 'critical', 'debug', 'disable', 'error',
|
'captureWarnings', 'critical', 'debug', 'disable', 'error',
|
||||||
'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
|
'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
|
||||||
'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning',
|
'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning',
|
||||||
'getLogRecordClass', 'setLogRecordClass']
|
'getLogRecordFactory', 'setLogRecordFactory']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import codecs
|
import codecs
|
||||||
@ -238,7 +238,7 @@ class LogRecord(object):
|
|||||||
information to be logged.
|
information to be logged.
|
||||||
"""
|
"""
|
||||||
def __init__(self, name, level, pathname, lineno,
|
def __init__(self, name, level, pathname, lineno,
|
||||||
msg, args, exc_info, func=None, sinfo=None):
|
msg, args, exc_info, func=None, sinfo=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Initialize a logging record with interesting information.
|
Initialize a logging record with interesting information.
|
||||||
"""
|
"""
|
||||||
@ -322,21 +322,24 @@ class LogRecord(object):
|
|||||||
#
|
#
|
||||||
# Determine which class to use when instantiating log records.
|
# Determine which class to use when instantiating log records.
|
||||||
#
|
#
|
||||||
_logRecordClass = LogRecord
|
_logRecordFactory = LogRecord
|
||||||
|
|
||||||
def setLogRecordClass(cls):
|
def setLogRecordFactory(factory):
|
||||||
"""
|
"""
|
||||||
Set the class to be used when instantiating a log record.
|
Set the class to be used when instantiating a log record.
|
||||||
"""
|
|
||||||
global _logRecordClass
|
|
||||||
_logRecordClass = cls
|
|
||||||
|
|
||||||
def getLogRecordClass():
|
:param factory: A callable which will be called to instantiate
|
||||||
|
a log record.
|
||||||
|
"""
|
||||||
|
global _logRecordFactory
|
||||||
|
_logRecordFactory = factory
|
||||||
|
|
||||||
|
def getLogRecordFactory():
|
||||||
"""
|
"""
|
||||||
Return the class to be used when instantiating a log record.
|
Return the class to be used when instantiating a log record.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return _logRecordClass
|
return _logRecordFactory
|
||||||
|
|
||||||
def makeLogRecord(dict):
|
def makeLogRecord(dict):
|
||||||
"""
|
"""
|
||||||
@ -345,7 +348,7 @@ def makeLogRecord(dict):
|
|||||||
a socket connection (which is sent as a dictionary) into a LogRecord
|
a socket connection (which is sent as a dictionary) into a LogRecord
|
||||||
instance.
|
instance.
|
||||||
"""
|
"""
|
||||||
rv = _logRecordClass(None, None, "", 0, "", (), None, None)
|
rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
|
||||||
rv.__dict__.update(dict)
|
rv.__dict__.update(dict)
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
@ -1056,7 +1059,7 @@ class Manager(object):
|
|||||||
self.emittedNoHandlerWarning = 0
|
self.emittedNoHandlerWarning = 0
|
||||||
self.loggerDict = {}
|
self.loggerDict = {}
|
||||||
self.loggerClass = None
|
self.loggerClass = None
|
||||||
self.logRecordClass = None
|
self.logRecordFactory = None
|
||||||
|
|
||||||
def getLogger(self, name):
|
def getLogger(self, name):
|
||||||
"""
|
"""
|
||||||
@ -1100,12 +1103,12 @@ class Manager(object):
|
|||||||
+ klass.__name__)
|
+ klass.__name__)
|
||||||
self.loggerClass = klass
|
self.loggerClass = klass
|
||||||
|
|
||||||
def setLogRecordClass(self, cls):
|
def setLogRecordFactory(self, factory):
|
||||||
"""
|
"""
|
||||||
Set the class to be used when instantiating a log record with this
|
Set the class to be used when instantiating a log record with this
|
||||||
Manager.
|
Manager.
|
||||||
"""
|
"""
|
||||||
self.logRecordClass = cls
|
self.logRecordFactory = factory
|
||||||
|
|
||||||
def _fixupParents(self, alogger):
|
def _fixupParents(self, alogger):
|
||||||
"""
|
"""
|
||||||
@ -1305,7 +1308,7 @@ class Logger(Filterer):
|
|||||||
A factory method which can be overridden in subclasses to create
|
A factory method which can be overridden in subclasses to create
|
||||||
specialized LogRecords.
|
specialized LogRecords.
|
||||||
"""
|
"""
|
||||||
rv = _logRecordClass(name, level, fn, lno, msg, args, exc_info, func,
|
rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
|
||||||
sinfo)
|
sinfo)
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
for key in extra:
|
for key in extra:
|
||||||
|
@ -1799,7 +1799,7 @@ class ChildLoggerTest(BaseTest):
|
|||||||
class DerivedLogRecord(logging.LogRecord):
|
class DerivedLogRecord(logging.LogRecord):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class LogRecordClassTest(BaseTest):
|
class LogRecordFactoryTest(BaseTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
class CheckingFilter(logging.Filter):
|
class CheckingFilter(logging.Filter):
|
||||||
@ -1817,17 +1817,17 @@ class LogRecordClassTest(BaseTest):
|
|||||||
BaseTest.setUp(self)
|
BaseTest.setUp(self)
|
||||||
self.filter = CheckingFilter(DerivedLogRecord)
|
self.filter = CheckingFilter(DerivedLogRecord)
|
||||||
self.root_logger.addFilter(self.filter)
|
self.root_logger.addFilter(self.filter)
|
||||||
self.orig_cls = logging.getLogRecordClass()
|
self.orig_factory = logging.getLogRecordFactory()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.root_logger.removeFilter(self.filter)
|
self.root_logger.removeFilter(self.filter)
|
||||||
BaseTest.tearDown(self)
|
BaseTest.tearDown(self)
|
||||||
logging.setLogRecordClass(self.orig_cls)
|
logging.setLogRecordFactory(self.orig_factory)
|
||||||
|
|
||||||
def test_logrecord_class(self):
|
def test_logrecord_class(self):
|
||||||
self.assertRaises(TypeError, self.root_logger.warning,
|
self.assertRaises(TypeError, self.root_logger.warning,
|
||||||
self.next_message())
|
self.next_message())
|
||||||
logging.setLogRecordClass(DerivedLogRecord)
|
logging.setLogRecordFactory(DerivedLogRecord)
|
||||||
self.root_logger.error(self.next_message())
|
self.root_logger.error(self.next_message())
|
||||||
self.assert_log_lines([
|
self.assert_log_lines([
|
||||||
('root', 'ERROR', '2'),
|
('root', 'ERROR', '2'),
|
||||||
@ -2015,7 +2015,7 @@ def test_main():
|
|||||||
ConfigFileTest, SocketHandlerTest, MemoryTest,
|
ConfigFileTest, SocketHandlerTest, MemoryTest,
|
||||||
EncodingTest, WarningsTest, ConfigDictTest, ManagerTest,
|
EncodingTest, WarningsTest, ConfigDictTest, ManagerTest,
|
||||||
FormatterTest,
|
FormatterTest,
|
||||||
LogRecordClassTest, ChildLoggerTest, QueueHandlerTest,
|
LogRecordFactoryTest, ChildLoggerTest, QueueHandlerTest,
|
||||||
RotatingFileHandlerTest,
|
RotatingFileHandlerTest,
|
||||||
#TimedRotatingFileHandlerTest
|
#TimedRotatingFileHandlerTest
|
||||||
)
|
)
|
||||||
|
@ -33,6 +33,8 @@ Core and Builtins
|
|||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- logging: Added getLogRecordFactory/setLogRecordFactory with docs and tests.
|
||||||
|
|
||||||
- Issue #10549: Fix pydoc traceback when text-documenting certain classes.
|
- Issue #10549: Fix pydoc traceback when text-documenting certain classes.
|
||||||
|
|
||||||
- Issue #2001: New HTML server with enhanced Web page features. Patch by Ron
|
- Issue #2001: New HTML server with enhanced Web page features. Patch by Ron
|
||||||
|
Loading…
x
Reference in New Issue
Block a user