This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author dvarrazzo
Recipients
Date 2006-01-22.13:47:54
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
The Python logging.Logger class is supposed being
extensible by overriding the makeRecord() method. 

This is not completely true because the public logging
method (log(), debug(), info()...) call the less public
_log(), which in turn call makeRecord(). While the
public methods have a signature such:

    def info(self, msg, *args, **kwargs):
        ...
        apply(self._log, (INFO, msg, args), kwargs)

thus leaving room for expansion, the _log() method is
not so much flexible:

    def _log(self, level, msg, args, exc_info=None):
        # ...interesting stuff here...
        record = self.makeRecord(self.name, level, fn,
lno, msg, args, exc_info)
        self.handle(record)

The makeRecord signature is:

    def makeRecord(self, name, level, fn, lno, msg,
args, exc_info):

So if anybody wants to add a keyword to makeRecord, he
also needs to re-implement the "interesting stuff" in
the supposed private _log (finding the source row,
reading the stack trace...).

The attached patch should leave the _log behavior
unchanged but all unknown keyword arguments are passed
to makeRecord.

If a wrong parameter is passed to any public method,
the logger as before raises an exception, which is
raised on the makeRecord() call instead of _log()'s.

With the patch on, use case for an user that want to
log extra keywords is:

    import logging
    
    # Logger customization

    class MyLogRecord(logging.LogRecord):
        """Add a foo to a log record."""
        def __init__(self, name, level, pathname, 
                     lineno, msg, args, exc_info, foo):
            logging.LogRecord.__init__(self, name,
level, pathname,
                                       lineno, msg,
args, exc_info)
            self.foo = foo
    
    class MyLogger(logging.Logger):
        """Can log foos too."""
        def makeRecord(self, name, level, fn, 
                       lno, msg, args, exc_info, foo):
            return MyLogRecord(name, level, fn, 
                               lno, msg, args,
exc_info, foo)
    
    class MyHandler(logging.Handler):
        """Can handle foo records."""
        def emit(self, record):
            if isinstance(record, MyLogRecord):
                print self.format(record), record.foo
    
    # Logger configuration

    logging.setLoggerClass(MyLogger)
    logger = logging.getLogger('test')
    logger.setLevel(logging.INFO)
    
    hndl = MyHandler(level=logging.INFO)
    hndl.setFormatter(
        logging.Formatter("%(message)s at line
#%(lineno)d"))
    logger.addHandler(hndl)
    
    # Logger usage

    logger.info("Message", foo='pippo')
    # prints something like "Message at line #40 pippo"
History
Date User Action Args
2007-08-23 15:45:28adminlinkissue1412054 messages
2007-08-23 15:45:28admincreate