[Python-Dev] Re: PEP 282 comments

Vinay Sajip vinay_sajip@red-dove.com
Wed, 20 Mar 2002 22:57:44 -0000


> [Jeremy Hylton wrote]
> > zLOG does have a nice feature for passing an exception info
> > to a log call.  I'd like to see this as a standard feature,
> > e.g.
> >
> > logger.info("A normal exception occurred",
> >     exc_info=sys.exc_info())
> >
> > The idea is the any of the log calls could also include a
> > formatted traceback in the log.
>
> Ideas I am batting around:
>
> MarkH's and Guido's (doesn't allow controlling the level of the message):
>     class Logger:
>         def exception(self, msg, *args):
>             # This is almost identical to error(), but sys.exc_info() is
>             # called, and if available the exception details are appended
to
>             # msg.  As sys.exc_info() is called, this is only useful in an
>             # exception handler.
>
>     logger.exception("Like, Oh My God!")  # cannot log it at 'info' level
>
>
> Jeremy's:
>     class Logger:
>         def info(self, level, msg, *args, **kwargs):
>             # watch for 'exc_info' in kwargs
>
>     logger.info("Like, Oh My God!", exc_info=sys.exc_info())
>
>
> Trent's:
>     class Logger:
>         def exception(self, msg, *args, **kwargs):
>             # watch for 'level' in kwargs
>
>     logger.exception("Like, Oh My God!", level=logging.INFO)
>
>
> Which do you all prefer?
>
I have to declare a preference for Mark's and Guido's approach. The reason
is - what is a "normal" exception? And if it is "normal", why do we need to
see a stack trace for it? In an exception handler, you can do "normal"
logging - via debug(), info(), warn(), error() or fatal(). That would cater
for "normal" exceptions (e.g. due to receiving bad data from external
sources). You are using exception() solely to indicate that you want to send
traceback info to the log. In practice, I haven't seen much value in putting
traceback info in the log unless it's really needed - otherwise it just
makes the log harder to read.

If it's that important to have the level explicitly specified with a
traceback, why not make it a mandatory argument to exception? If you don't
want to clutter every exception call with the level argument, I think an
additional "exception_ex" method (not that name, exactly! but you know what
I mean) could be added for those people who really need it.
...
def exception(self, level, msg, *args):
...

>
> > What's the current status of this PEP?  I like the general
> > outline of stuff, but it feels a little fuzzy.  That is, it
> > seems to present a high-level description and a bunch of
> > options.  I'd like to see the concrete APIs for all of the
> > objects.
>
> The current status is that I have been slowly working on it in private. I
> agree that the current PEP is fuzzy.
>
>
> > I'd also love to get at least a prototype implementation.
> > It would be need to replace the zLOG in Zope3 with a new
> > logging implementation that follows the PEP.
>
> Last week (I think) Vinay Sajip posted on python-list that he had a
prototype
> implementation of PEP 282.
>     http://www.red-dove.com/python_logging.html
> I like what he has and I hope to work with him (merging with what
> implementation scraps I have) to build the eventual proposed patch for the
> PEP. I haven't told him this yet though. :)  Vinay, what do you think?
>
No problem in principle. I'm about to post version 0.4, which has a whole
lot of additional functionality. It now looks pretty close to PEP 282 (bar
things like some method and class names), and I could use your help
pinpointing areas where it doesn't match. What areas do your "implementation
scraps" cover?

Below  is the change history for 0.4. You'll see that most of the previous
"to do"s are history :-)

Regards

Vinay Sajip
--------------------------------------------
Incorporated comments/patches from Ollie Rutherfurd:
-Added level filtering for handlers.
-Return root logger if no name specified in getLogger.
Incorporated comments from Greg Ward:
-Added distutils setup.py script.
Added formatter initialization in Handler.__init__.
Tidied up docstrings.
Added removeHandler to Logger.
Added removeFilter to Logger and Handler.
logrecv.py modified to keep connection alive until client closes it.
SocketHandler modified to not reset connection after each logging event.
Added shutdown function which closes open sockets etc.
Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT.
Added DEFAULT_UDP_LOGGING_PORT.
Added log_test4.py (example of arbitrary levels).
Added addLevelName, changed behaviour of getLevelName.
Fixed bugs in DatagramHandler.
Added SMTPHandler implementation.
Added log_test5.py to test SMTPHandler.
Added SysLogHandler (contribution from Nicolas Untz based on Sam Rushing's
syslog.py).
Modified log_test1.py to add a SysLogHandler.
Added rollover functionality to FileHandler.
Added NTEventLogHandler (based on Win32 extensions).
Added log_test6.py to test NTEventHandler.
Added MemoryHandler implementation.
Added log_test7.py to test MemoryHandler.
Added log_test8.py to test FileHandler rollover.
--------------------------------------------