mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
Merged revisions 79279,79284,79293,79373,79376,79379,79876,79888 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r79279 | vinay.sajip | 2010-03-22 07:33:08 -0500 (Mon, 22 Mar 2010) | 1 line Issue #8200: logging: Handle errors when multiprocessing is not fully loaded when logging occurs. ........ r79284 | vinay.sajip | 2010-03-22 08:02:28 -0500 (Mon, 22 Mar 2010) | 1 line Issue #8201: logging: Handle config errors when non-ASCII and Unicode logger names exist at the same time. ........ r79293 | vinay.sajip | 2010-03-22 10:29:01 -0500 (Mon, 22 Mar 2010) | 1 line logging: Added getChild utility method to Logger and added isEnabledFor method to LoggerAdapter. ........ r79373 | vinay.sajip | 2010-03-24 09:31:21 -0500 (Wed, 24 Mar 2010) | 1 line logging: Added LOG_FTP for SysLogHandler and updated documentation. ........ r79376 | vinay.sajip | 2010-03-24 10:10:40 -0500 (Wed, 24 Mar 2010) | 1 line logging: Documentation tweak. ........ r79379 | vinay.sajip | 2010-03-24 12:36:35 -0500 (Wed, 24 Mar 2010) | 1 line logging: Updated SysLogHandler documentation. ........ r79876 | vinay.sajip | 2010-04-06 17:32:37 -0500 (Tue, 06 Apr 2010) | 1 line Issue #8327: logging: Clarification of propagation functionality in documentation. ........ r79888 | vinay.sajip | 2010-04-07 04:40:52 -0500 (Wed, 07 Apr 2010) | 1 line Issue #8331: logging: fixed some grammatical errors in documentation. ........
This commit is contained in:
parent
135e990a75
commit
22005fc5ba
5 changed files with 107 additions and 24 deletions
|
@ -244,16 +244,16 @@ With the logger object configured, the following methods create log messages:
|
||||||
methods listed above, but this is how to log at custom log levels.
|
methods listed above, but this is how to log at custom log levels.
|
||||||
|
|
||||||
:func:`getLogger` returns a reference to a logger instance with the specified
|
:func:`getLogger` returns a reference to a logger instance with the specified
|
||||||
if it it is provided, or ``root`` if not. The names are period-separated
|
if it is provided, or ``root`` if not. The names are period-separated
|
||||||
hierarchical structures. Multiple calls to :func:`getLogger` with the same name
|
hierarchical structures. Multiple calls to :func:`getLogger` with the same name
|
||||||
will return a reference to the same logger object. Loggers that are further
|
will return a reference to the same logger object. Loggers that are further
|
||||||
down in the hierarchical list are children of loggers higher up in the list.
|
down in the hierarchical list are children of loggers higher up in the list.
|
||||||
For example, given a logger with a name of ``foo``, loggers with names of
|
For example, given a logger with a name of ``foo``, loggers with names of
|
||||||
``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all children of ``foo``.
|
``foo.bar``, ``foo.bar.baz``, and ``foo.bam`` are all descendants of ``foo``.
|
||||||
Child loggers propagate messages up to their parent loggers. Because of this,
|
Child loggers propagate messages up to the handlers associated with their
|
||||||
it is unnecessary to define and configure all the loggers an application uses.
|
ancestor loggers. Because of this, it is unnecessary to define and configure
|
||||||
It is sufficient to configure a top-level logger and create child loggers as
|
handlers for all the loggers an application uses. It is sufficient to
|
||||||
needed.
|
configure handlers for a top-level logger and create child loggers as needed.
|
||||||
|
|
||||||
|
|
||||||
Handlers
|
Handlers
|
||||||
|
@ -281,15 +281,16 @@ custom handlers) are the following configuration methods:
|
||||||
are there two :func:`setLevel` methods? The level set in the logger
|
are there two :func:`setLevel` methods? The level set in the logger
|
||||||
determines which severity of messages it will pass to its handlers. The level
|
determines which severity of messages it will pass to its handlers. The level
|
||||||
set in each handler determines which messages that handler will send on.
|
set in each handler determines which messages that handler will send on.
|
||||||
:func:`setFormatter` selects a Formatter object for this handler to use.
|
|
||||||
|
* :func:`setFormatter` selects a Formatter object for this handler to use.
|
||||||
|
|
||||||
* :func:`addFilter` and :func:`removeFilter` respectively configure and
|
* :func:`addFilter` and :func:`removeFilter` respectively configure and
|
||||||
deconfigure filter objects on handlers.
|
deconfigure filter objects on handlers.
|
||||||
|
|
||||||
Application code should not directly instantiate and use handlers. Instead, the
|
Application code should not directly instantiate and use instances of
|
||||||
:class:`Handler` class is a base class that defines the interface that all
|
:class:`Handler`. Instead, the :class:`Handler` class is a base class that
|
||||||
Handlers should have and establishes some default behavior that child classes
|
defines the interface that all handlers should have and establishes some
|
||||||
can use (or override).
|
default behavior that child classes can use (or override).
|
||||||
|
|
||||||
|
|
||||||
Formatters
|
Formatters
|
||||||
|
@ -521,7 +522,9 @@ support desk staff, system administrators, developers). Handlers are passed
|
||||||
can have zero, one or more handlers associated with it (via the
|
can have zero, one or more handlers associated with it (via the
|
||||||
:meth:`addHandler` method of :class:`Logger`). In addition to any handlers
|
:meth:`addHandler` method of :class:`Logger`). In addition to any handlers
|
||||||
directly associated with a logger, *all handlers associated with all ancestors
|
directly associated with a logger, *all handlers associated with all ancestors
|
||||||
of the logger* are called to dispatch the message.
|
of the logger* are called to dispatch the message (unless the *propagate* flag
|
||||||
|
for a logger is set to a false value, at which point the passing to ancestor
|
||||||
|
handlers stops).
|
||||||
|
|
||||||
Just as for loggers, handlers can have levels associated with them. A handler's
|
Just as for loggers, handlers can have levels associated with them. A handler's
|
||||||
level acts as a filter in the same way as a logger's level does. If a handler
|
level acts as a filter in the same way as a logger's level does. If a handler
|
||||||
|
@ -849,8 +852,8 @@ instantiated directly, but always through the module-level function
|
||||||
.. attribute:: Logger.propagate
|
.. attribute:: Logger.propagate
|
||||||
|
|
||||||
If this evaluates to false, logging messages are not passed by this logger or by
|
If this evaluates to false, logging messages are not passed by this logger or by
|
||||||
child loggers to higher level (ancestor) loggers. The constructor sets this
|
its child loggers to the handlers of higher level (ancestor) loggers. The
|
||||||
attribute to 1.
|
constructor sets this attribute to 1.
|
||||||
|
|
||||||
|
|
||||||
.. method:: Logger.setLevel(lvl)
|
.. method:: Logger.setLevel(lvl)
|
||||||
|
@ -889,6 +892,16 @@ instantiated directly, but always through the module-level function
|
||||||
:const:`NOTSET` is found, and that value is returned.
|
:const:`NOTSET` is found, and that value is returned.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: Logger.getChild(suffix)
|
||||||
|
|
||||||
|
Returns a logger which is a descendant to this logger, as determined by the suffix.
|
||||||
|
Thus, ``logging.getLogger('abc').getChild('def.ghi')`` would return the same
|
||||||
|
logger as would be returned by ``logging.getLogger('abc.def.ghi')``. This is a
|
||||||
|
convenience method, useful when the parent logger is named using e.g. ``__name__``
|
||||||
|
rather than a literal string.
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
.. method:: Logger.debug(msg, *args, **kwargs)
|
.. method:: Logger.debug(msg, *args, **kwargs)
|
||||||
|
|
||||||
Logs a message with level :const:`DEBUG` on this logger. The *msg* is the
|
Logs a message with level :const:`DEBUG` on this logger. The *msg* is the
|
||||||
|
@ -2012,8 +2025,11 @@ supports sending logging messages to a remote or local Unix syslog.
|
||||||
or integers - if strings are passed, internal mapping dictionaries are
|
or integers - if strings are passed, internal mapping dictionaries are
|
||||||
used to convert them to integers.
|
used to convert them to integers.
|
||||||
|
|
||||||
**Priorities**
|
The symbolic ``LOG_`` values are defined in :class:`SysLogHandler` and
|
||||||
|
mirror the values defined in the ``sys/syslog.h`` header file.
|
||||||
|
|
||||||
|
+------------------------------------------+
|
||||||
|
| Priorities |
|
||||||
+--------------------------+---------------+
|
+--------------------------+---------------+
|
||||||
| Name (string) | Symbolic value|
|
| Name (string) | Symbolic value|
|
||||||
+==========================+===============+
|
+==========================+===============+
|
||||||
|
@ -2034,8 +2050,8 @@ supports sending logging messages to a remote or local Unix syslog.
|
||||||
| ``warn`` or ``warning`` | LOG_WARNING |
|
| ``warn`` or ``warning`` | LOG_WARNING |
|
||||||
+--------------------------+---------------+
|
+--------------------------+---------------+
|
||||||
|
|
||||||
**Facilities**
|
+-------------------------------+
|
||||||
|
| Facilities |
|
||||||
+---------------+---------------+
|
+---------------+---------------+
|
||||||
| Name (string) | Symbolic value|
|
| Name (string) | Symbolic value|
|
||||||
+===============+===============+
|
+===============+===============+
|
||||||
|
@ -2481,6 +2497,11 @@ methods of :class:`Logger`, i.e. :meth:`debug`, :meth:`info`, :meth:`warning`,
|
||||||
methods have the same signatures as their counterparts in :class:`Logger`, so
|
methods have the same signatures as their counterparts in :class:`Logger`, so
|
||||||
you can use the two types of instances interchangeably.
|
you can use the two types of instances interchangeably.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.7
|
||||||
|
|
||||||
|
The :meth:`isEnabledFor` method was added to :class:`LoggerAdapter`. This method
|
||||||
|
delegates to the underlying logger.
|
||||||
|
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -285,10 +285,18 @@ class LogRecord(object):
|
||||||
self.threadName = None
|
self.threadName = None
|
||||||
if not logMultiprocessing:
|
if not logMultiprocessing:
|
||||||
self.processName = None
|
self.processName = None
|
||||||
elif 'multiprocessing' not in sys.modules:
|
|
||||||
self.processName = 'MainProcess'
|
|
||||||
else:
|
else:
|
||||||
self.processName = sys.modules['multiprocessing'].current_process().name
|
self.processName = 'MainProcess'
|
||||||
|
mp = sys.modules.get('multiprocessing')
|
||||||
|
if mp is not None:
|
||||||
|
# Errors may occur if multiprocessing has not finished loading
|
||||||
|
# yet - e.g. if a custom import hook causes third-party code
|
||||||
|
# to run when multiprocessing calls import. See issue 8200
|
||||||
|
# for an example
|
||||||
|
try:
|
||||||
|
self.processName = mp.current_process().name
|
||||||
|
except StandardError:
|
||||||
|
pass
|
||||||
if logProcesses and hasattr(os, 'getpid'):
|
if logProcesses and hasattr(os, 'getpid'):
|
||||||
self.process = os.getpid()
|
self.process = os.getpid()
|
||||||
else:
|
else:
|
||||||
|
@ -1306,6 +1314,25 @@ class Logger(Filterer):
|
||||||
return 0
|
return 0
|
||||||
return level >= self.getEffectiveLevel()
|
return level >= self.getEffectiveLevel()
|
||||||
|
|
||||||
|
def getChild(self, suffix):
|
||||||
|
"""
|
||||||
|
Get a logger which is a descendant to this one.
|
||||||
|
|
||||||
|
This is a convenience method, such that
|
||||||
|
|
||||||
|
logging.getLogger('abc').getChild('def.ghi')
|
||||||
|
|
||||||
|
is the same as
|
||||||
|
|
||||||
|
logging.getLogger('abc.def.ghi')
|
||||||
|
|
||||||
|
It's useful, for example, when the parent logger is named using
|
||||||
|
__name__ rather than a literal string.
|
||||||
|
"""
|
||||||
|
if self.root is not self:
|
||||||
|
suffix = '.'.join((self.name, suffix))
|
||||||
|
return self.manager.getLogger(suffix)
|
||||||
|
|
||||||
class RootLogger(Logger):
|
class RootLogger(Logger):
|
||||||
"""
|
"""
|
||||||
A root logger is not that different to any other logger, except that
|
A root logger is not that different to any other logger, except that
|
||||||
|
@ -1410,6 +1437,12 @@ class LoggerAdapter(object):
|
||||||
msg, kwargs = self.process(msg, kwargs)
|
msg, kwargs = self.process(msg, kwargs)
|
||||||
self.logger.log(level, msg, *args, **kwargs)
|
self.logger.log(level, msg, *args, **kwargs)
|
||||||
|
|
||||||
|
def isEnabledFor(self, level):
|
||||||
|
"""
|
||||||
|
See if the underlying logger is enabled for the specified level.
|
||||||
|
"""
|
||||||
|
return self.logger.isEnabledFor(level)
|
||||||
|
|
||||||
root = RootLogger(WARNING)
|
root = RootLogger(WARNING)
|
||||||
Logger.root = root
|
Logger.root = root
|
||||||
Logger.manager = Manager(Logger.root)
|
Logger.manager = Manager(Logger.root)
|
||||||
|
|
|
@ -98,6 +98,9 @@ def _resolve(name):
|
||||||
def _strip_spaces(alist):
|
def _strip_spaces(alist):
|
||||||
return map(lambda x: x.strip(), alist)
|
return map(lambda x: x.strip(), alist)
|
||||||
|
|
||||||
|
def _encoded(s):
|
||||||
|
return s if isinstance(s, str) else s.encode('utf-8')
|
||||||
|
|
||||||
def _create_formatters(cp):
|
def _create_formatters(cp):
|
||||||
"""Create and return formatters"""
|
"""Create and return formatters"""
|
||||||
flist = cp.get("formatters", "keys")
|
flist = cp.get("formatters", "keys")
|
||||||
|
@ -208,7 +211,7 @@ def _install_loggers(cp, handlers, disable_existing_loggers):
|
||||||
#avoid disabling child loggers of explicitly
|
#avoid disabling child loggers of explicitly
|
||||||
#named loggers. With a sorted list it is easier
|
#named loggers. With a sorted list it is easier
|
||||||
#to find the child loggers.
|
#to find the child loggers.
|
||||||
existing.sort()
|
existing.sort(key=_encoded)
|
||||||
#We'll keep the list of existing loggers
|
#We'll keep the list of existing loggers
|
||||||
#which are children of named loggers here...
|
#which are children of named loggers here...
|
||||||
child_loggers = []
|
child_loggers = []
|
||||||
|
@ -579,7 +582,7 @@ class DictConfigurator(BaseConfigurator):
|
||||||
#avoid disabling child loggers of explicitly
|
#avoid disabling child loggers of explicitly
|
||||||
#named loggers. With a sorted list it is easier
|
#named loggers. With a sorted list it is easier
|
||||||
#to find the child loggers.
|
#to find the child loggers.
|
||||||
existing.sort()
|
existing.sort(key=_encoded)
|
||||||
#We'll keep the list of existing loggers
|
#We'll keep the list of existing loggers
|
||||||
#which are children of named loggers here...
|
#which are children of named loggers here...
|
||||||
child_loggers = []
|
child_loggers = []
|
||||||
|
|
|
@ -633,7 +633,8 @@ class SysLogHandler(logging.Handler):
|
||||||
LOG_NEWS = 7 # network news subsystem
|
LOG_NEWS = 7 # network news subsystem
|
||||||
LOG_UUCP = 8 # UUCP subsystem
|
LOG_UUCP = 8 # UUCP subsystem
|
||||||
LOG_CRON = 9 # clock daemon
|
LOG_CRON = 9 # clock daemon
|
||||||
LOG_AUTHPRIV = 10 # security/authorization messages (private)
|
LOG_AUTHPRIV = 10 # security/authorization messages (private)
|
||||||
|
LOG_FTP = 11 # FTP daemon
|
||||||
|
|
||||||
# other codes through 15 reserved for system use
|
# other codes through 15 reserved for system use
|
||||||
LOG_LOCAL0 = 16 # reserved for local use
|
LOG_LOCAL0 = 16 # reserved for local use
|
||||||
|
@ -665,6 +666,7 @@ class SysLogHandler(logging.Handler):
|
||||||
"authpriv": LOG_AUTHPRIV,
|
"authpriv": LOG_AUTHPRIV,
|
||||||
"cron": LOG_CRON,
|
"cron": LOG_CRON,
|
||||||
"daemon": LOG_DAEMON,
|
"daemon": LOG_DAEMON,
|
||||||
|
"ftp": LOG_FTP,
|
||||||
"kern": LOG_KERN,
|
"kern": LOG_KERN,
|
||||||
"lpr": LOG_LPR,
|
"lpr": LOG_LPR,
|
||||||
"mail": LOG_MAIL,
|
"mail": LOG_MAIL,
|
||||||
|
|
|
@ -68,6 +68,12 @@ class BaseTest(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
logging._releaseLock()
|
logging._releaseLock()
|
||||||
|
|
||||||
|
# Set two unused loggers: one non-ASCII and one Unicode.
|
||||||
|
# This is to test correct operation when sorting existing
|
||||||
|
# loggers in the configuration code. See issue 8201.
|
||||||
|
logging.getLogger("\xab\xd7\xbb")
|
||||||
|
logging.getLogger("\u013f\u00d6\u0047")
|
||||||
|
|
||||||
self.root_logger = logging.getLogger("")
|
self.root_logger = logging.getLogger("")
|
||||||
self.original_logging_level = self.root_logger.getEffectiveLevel()
|
self.original_logging_level = self.root_logger.getEffectiveLevel()
|
||||||
|
|
||||||
|
@ -1731,6 +1737,23 @@ class ManagerTest(BaseTest):
|
||||||
self.assertEqual(logged, ['should appear in logged'])
|
self.assertEqual(logged, ['should appear in logged'])
|
||||||
|
|
||||||
|
|
||||||
|
class ChildLoggerTest(BaseTest):
|
||||||
|
def test_child_loggers(self):
|
||||||
|
r = logging.getLogger()
|
||||||
|
l1 = logging.getLogger('abc')
|
||||||
|
l2 = logging.getLogger('def.ghi')
|
||||||
|
c1 = r.getChild('xyz')
|
||||||
|
c2 = r.getChild('uvw.xyz')
|
||||||
|
self.assertTrue(c1 is logging.getLogger('xyz'))
|
||||||
|
self.assertTrue(c2 is logging.getLogger('uvw.xyz'))
|
||||||
|
c1 = l1.getChild('def')
|
||||||
|
c2 = c1.getChild('ghi')
|
||||||
|
c3 = l1.getChild('def.ghi')
|
||||||
|
self.assertTrue(c1 is logging.getLogger('abc.def'))
|
||||||
|
self.assertTrue(c2 is logging.getLogger('abc.def.ghi'))
|
||||||
|
self.assertTrue(c2 is c3)
|
||||||
|
|
||||||
|
|
||||||
# Set the locale to the platform-dependent default. I have no idea
|
# Set the locale to the platform-dependent default. I have no idea
|
||||||
# why the test does this, but in any case we save the current locale
|
# why the test does this, but in any case we save the current locale
|
||||||
# first and restore it at the end.
|
# first and restore it at the end.
|
||||||
|
@ -1739,7 +1762,8 @@ def test_main():
|
||||||
run_unittest(BuiltinLevelsTest, BasicFilterTest,
|
run_unittest(BuiltinLevelsTest, BasicFilterTest,
|
||||||
CustomLevelsAndFiltersTest, MemoryHandlerTest,
|
CustomLevelsAndFiltersTest, MemoryHandlerTest,
|
||||||
ConfigFileTest, SocketHandlerTest, MemoryTest,
|
ConfigFileTest, SocketHandlerTest, MemoryTest,
|
||||||
EncodingTest, WarningsTest, ConfigDictTest, ManagerTest)
|
EncodingTest, WarningsTest, ConfigDictTest, ManagerTest,
|
||||||
|
ChildLoggerTest)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
test_main()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue