I'm planning to check in some changes to the logging package. I'd appreciate comments on the following: 1. A backwards-compatible change to basicConfig(), making simple configuration of logging easier than before. For example, to change the level of the root logger to DEBUG: logging.basicConfig(level=logging.DEBUG) For example, to change the message format: logging.basicConfig(format="%(asctime)s %(levelname)-5s %(message)s") To log to a file in append mode (for write mode, add a filemode="w" argument): logging.basicConfig(filename="/logs/myapp.log") To log to an existing stream: s = open("/logs/myapp.log", "w") ... logging.basicConfig(stream=s) 2. Refactoring of RotatingFileHandler into BaseRotatingHandler and RotatingFileHandler. The reason for this is the addition of a new class, TimedRotatingFileHandler, which rotates files based on time-dependent criteria. (See SF patch #921318 for more details). 3. Logger.log() changed to throw a TypeError if raiseExceptions is set and the level passed in is not an integer. If the changes seem generally acceptable, then I'll also add a section in the docs which describes the above basic use cases under a "Basic use of the logging package" section which appears earlier in the logging docs than it does currently. Except for the documentation changes, I'm planning to commit by 3 July. Thanks, Vinay
(belatedly...) These are good changes, expecially the new basicConfig constructor, but I'd like point out two issues with the logging package that i think can easily be addressed: One is a usability bug: calling fileConfig() disables any logger objects already created that are not explicitly specified in the log config file. Since loggers are often created when a module is imported, it's hard to keep track of the order in which loggers are created, leading to unexpected behavior because an unspecifed logger created after the call to fileConfig behave differently -- it will inherit its settings from its parent logger. Here's an example illustrating the problem: import logging, logging.config import mymodule #this module contains a line like log = logging.getLogger("mymodule") if __name__ == '__main__': loggging.config.fileConfig("log.config") #mymodule.log is now disabled! #this seems like a bad design -- difficult to figure out what's going on #work-around: re-enable the loggers for logger in logging.Logger.manager.loggerDict.itervalues(): logger.disabled = 0 Second, i'd recommend a minor change that would greatly increase the flexibility of the architecture: store the entire keyword dictionary in the LogRecord, not just exc_info -- that way arbitrary objects could be passed to particular handlers or formatters that know how to use them. Some use cases for this: * pass a unique error number. * pass structured information about the message, e.g. for writing to a database table * for a localized message formatter (LogRecord already stores the argument list for string interpolation but this is cumbersome for localization since they depends on the order they appear in the message). thanks, adam On Sun, 27 Jun 2004 23:52:03 +0100, Vinay Sajip <vinay_sajip@red-dove.com> wrote:
I'm planning to check in some changes to the logging package. I'd appreciate comments on the following:
1. A backwards-compatible change to basicConfig(), making simple configuration of logging easier than before. For example, to change the level of the root logger to DEBUG:
logging.basicConfig(level=logging.DEBUG)
For example, to change the message format:
logging.basicConfig(format="%(asctime)s %(levelname)-5s %(message)s")
To log to a file in append mode (for write mode, add a filemode="w" argument):
logging.basicConfig(filename="/logs/myapp.log")
To log to an existing stream:
s = open("/logs/myapp.log", "w") ... logging.basicConfig(stream=s)
2. Refactoring of RotatingFileHandler into BaseRotatingHandler and RotatingFileHandler. The reason for this is the addition of a new class, TimedRotatingFileHandler, which rotates files based on time-dependent criteria. (See SF patch #921318 for more details).
3. Logger.log() changed to throw a TypeError if raiseExceptions is set and the level passed in is not an integer.
If the changes seem generally acceptable, then I'll also add a section in the docs which describes the above basic use cases under a "Basic use of the logging package" section which appears earlier in the logging docs than it does currently. Except for the documentation changes, I'm planning to commit by 3 July.
Thanks,
Vinay
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/adamsz%40gmail.com
One is a usability bug: calling fileConfig() disables any logger objects already created that are not explicitly specified in the log config file. Since loggers are often created when a module is
It's not a bug, it's by design. The semantics of fileConfig() is that it completely replaces the existing configuration (in some scenarios, that's what you want). I'm thinking about a better way to configure the system - incremental rather than all-or-nothing. I will update the docstring to indicate this, as it's perhaps not clear enough.
imported, it's hard to keep track of the order in which loggers are created, leading to unexpected behavior because an unspecifed logger created after the call to fileConfig behave differently -- it will inherit its settings from its parent logger. Here's an example illustrating the problem:
import logging, logging.config import mymodule #this module contains a line like log = logging.getLogger("mymodule")
if __name__ == '__main__': loggging.config.fileConfig("log.config") #mymodule.log is now disabled! #this seems like a bad design -- difficult to figure out what's going on #work-around: re-enable the loggers for logger in logging.Logger.manager.loggerDict.itervalues(): logger.disabled = 0
It'd be easier to comment out the line in config.py which sets disabled to 1, if this is behaviour you want in all your applications.
Second, i'd recommend a minor change that would greatly increase the flexibility of the architecture: store the entire keyword dictionary in the LogRecord, not just exc_info -- that way arbitrary objects could be passed to particular handlers or formatters that know how to use them. Some use cases for this: * pass a unique error number. * pass structured information about the message, e.g. for writing to a database table * for a localized message formatter (LogRecord already stores the argument list for string interpolation but this is cumbersome for localization since they depends on the order they appear in the message).
The whole area of LogRecord construction needs to be made more extensible. I'm in discussions with Fred Drake about this, and hopefully soon will be able to implement a better mechanism. Fred - if you're listening - :-) Thanks for the feedback. Regards, Vinay
On Fri, 16 Jul 2004 07:02:37 +0100, Vinay Sajip <vinay_sajip@red-dove.com> wrote:
One is a usability bug: calling fileConfig() disables any logger objects already created that are not explicitly specified in the log config file. Since loggers are often created when a module is
It's not a bug, it's by design. The semantics of fileConfig() is that it completely replaces the existing configuration (in some scenarios, that's what you want). I'm thinking about a better way to configure the system - incremental rather than all-or-nothing. I will update the docstring to indicate this, as it's perhaps not clear enough.
OK, but a better implementation of these semantics would be to have logging to one of these "replaced" log objects raise an exception instead of continuing to accept log messages but silently have them disappear into the ether -- that's what I mean by a "usability bug". Better still, it seems entirely consistent with these semantics to have the existing log objects reset to their parent settings -- just like unspecified log objects created after the confguration load do. I think this is more consistent, more intuitive, and doesn't require you to figure out what logs may or exist throughout the system when loading a configuration. regards, adam
On Friday 16 July 2004 02:02 am, Vinay Sajip wrote:
The whole area of LogRecord construction needs to be made more extensible. I'm in discussions with Fred Drake about this, and hopefully soon will be able to implement a better mechanism.
Fred - if you're listening - :-)
I've not forgotten; I need to get back to explaining what I've come up with. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org>
participants (3)
-
Adam Souzis
-
Fred L. Drake, Jr.
-
Vinay Sajip