Comment 1 for bug 310774

Revision history for this message
Barry Warsaw (barry) wrote :

Jono, let me understand better what you're thinking about. I have some similar code in Mailman, but I'm trying to think about how to generalize this. In my schema.conf file I have the following:

{{{
[logging.template]
# This defines various log settings. The options available are:
#
# - level -- Overrides the default level; this may be any of the
# standard Python logging levels, case insensitive.
# - format -- Overrides the default format string
# - datefmt -- Overrides the default date format string
# - path -- Overrides the default logger path. This may be a relative
# path name, in which case it is relative to Mailman's LOG_DIR,
# or it may be an absolute path name. You cannot change the
# handler class that will be used.
# - propagate -- Boolean specifying whether to propagate log message from this
# logger to the root "mailman" logger. You cannot override
# settings for the root logger.
#
# In this section, you can define defaults for all loggers, which will be
# prefixed by 'mailman.'. Use subsections to override settings for specific
# loggers. The names of the available loggers are:
#
# - archiver -- All archiver output
# - bounce -- All bounce processing logs go here
# - config -- Configuration issues
# - debug -- Only used for development
# - error -- All exceptions go to this log
# - fromusenet -- Information related to the Usenet to Mailman gateway
# - http -- Internal wsgi-based web interface
# - locks -- Lock state changes
# - mischief -- Various types of hostile activity
# - post -- Information about messages posted to mailing lists
# - qrunner -- qrunner start/stops
# - smtp -- Successful SMTP activity
# - smtp-failure -- Unsuccessful SMTP activity
# - subscribe -- Information about leaves/joins
# - vette -- Information related to admindb activity
format: %(asctime)s (%(process)d) %(message)s
datefmt: %b %d %H:%M:%S %Y
propagate: no
level: info
path: mailman

[logging.root]

[logging.archiver]

[logging.bounce]
path: bounce

[logging.config]

[logging.debug]
path: debug
level: debug

[logging.error]

[logging.fromusenet]

[logging.http]

[logging.locks]

[logging.mischief]

[logging.qrunner]

[logging.smtp]
path: smtp

[logging.subscribe]

[logging.vette]
}}}

then in my logger initialize code, I've got something like this:

{{{
    # First, find the root logger and configure the logging subsystem.
    # Initialize the root logger, then create a formatter for all the sublogs.
    logging.basicConfig(format=config.logging.root.format,
                        datefmt=config.logging.root.datefmt,
                        level=as_log_level(config.logging.root.level))
    # Create the subloggers
    for logger_config in config.logger_configs:
        logger_name = 'mailman.' + logger_config.name.split('.')[-1]
        log = logging.getLogger(logger_name)
        # Get settings from log configuration file (or defaults).
        log_format = logger_config.format
        log_datefmt = logger_config.datefmt
        # Propagation to the root logger is how we handle logging to stderr
        # when the qrunners are not run as a subprocess of mailmanctl.
        log.propagate = as_boolean(logger_config.propagate)
        # Set the logger's level.
        log.setLevel(as_log_level(logger_config.level))
        # Create a formatter for this logger, then a handler, and link the
        # formatter to the handler.
        formatter = logging.Formatter(fmt=log_format, datefmt=log_datefmt)
        path_str = logger_config.path
        path_abs = os.path.normpath(os.path.join(config.LOG_DIR, path_str))
        handler = ReopenableFileHandler(path_abs)
        _handlers.append(handler)
        handler.setFormatter(formatter)
        log.addHandler(handler)
}}}

The way I'm thinking about generalizing this depends on bug 310619 which allows you to set a .master section that can be extended in the config file. You'd then define the .master section in your schema file like so.

{{{
[logging.master]
format: %(asctime)s (%(process)d) %(message)s
datefmt: %b %d %H:%M:%S %Y
propagate: no
level: info
path: /var/log/log.log
formatter: logging.Formatter
handler: logging.Handler
}}}

There are some tricky bits, such as how do you define the arguments to pass to the handler?

Anyway, what do you think?