[Zodb-checkins] CVS: Zope/lib/python/zLOG - component.xml:1.7.2.1 datatypes.py:1.10.2.1 factory.py:1.3.2.1 EventLogger.py:1.1.2.7 __init__.py:1.8.4.6

Fred L. Drake, Jr. fred@zope.com
Thu, 23 Jan 2003 17:05:16 -0500


Update of /cvs-repository/Zope/lib/python/zLOG
In directory cvs.zope.org:/tmp/cvs-serv708

Modified Files:
      Tag: chrism-install-branch
	EventLogger.py __init__.py 
Added Files:
      Tag: chrism-install-branch
	component.xml datatypes.py factory.py 
Log Message:
Merge from the zLOG trunk.

=== Added File Zope/lib/python/zLOG/component.xml ===
<component prefix="zLOG.datatypes">

  <abstracttype name="loghandler"/>

  <sectiontype name="base-log-handler">
    <description>
      Base type for most log handlers.  This is cannot be used as a
      loghandler directly since it doesn't implement the loghandler
      abstract section type.
    </description>
    <key name="dateformat" default="%Y-%m-%dT%H:%M:%S"/>
    <key name="level" default="notset" datatype=".logging_level"/>
  </sectiontype>

  <sectiontype name="logfile" datatype=".FileHandlerFactory"
               implements="loghandler" extends="base-log-handler">
    <key name="path" required="yes"/>
    <key name="format" default="------\n%(asctime)s %(message)s"
         datatype=".log_format"/>
  </sectiontype>

  <sectiontype name="syslog" datatype=".SyslogHandlerFactory"
               implements="loghandler" extends="base-log-handler">
    <key name="facility" default="user" datatype=".syslog_facility"/>
    <key name="address" datatype="socket-address" default="localhost:514"/>
    <key name="format" default="%(message)s"
         datatype=".log_format"/>
  </sectiontype>

  <sectiontype name="win32-eventlog" datatype=".Win32EventLogFactory"
               implements="loghandler" extends="base-log-handler">
    <key name="appname" default="Zope"/>
    <key name="format" default="%(message)s"
         datatype=".log_format"/>
  </sectiontype>

  <sectiontype name="http-logger" datatype=".HTTPHandlerFactory"
               implements="loghandler" extends="base-log-handler">
    <key name="url" default="http://localhost/" datatype=".http_handler_url"/>
    <key name="method" default="GET" datatype=".get_or_post"/>
    <key name="format" default="%(asctime)s %(message)s"
         datatype=".log_format"/>
  </sectiontype>

  <sectiontype name="email-notifier" datatype=".SMTPHandlerFactory"
               implements="loghandler" extends="base-log-handler">
    <key name="from" required="yes" attribute="fromaddr"/>
    <multikey name="to" required="yes" attribute="toaddrs"/>
    <key name="subject" default="Message from Zope"/>
    <key name="smtp-server" default="localhost" datatype="inet-address"/>
    <key name="format" default="%(asctime)s %(message)s"
         datatype=".log_format"/>
  </sectiontype>


  <sectiontype name="eventlog" datatype=".EventLogFactory">
     <key name="level" datatype=".logging_level" default="info"/>
     <multisection type="loghandler" attribute="handlers" name="*"/>
  </sectiontype>

</component>


=== Added File Zope/lib/python/zLOG/datatypes.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################

"""ZConfig datatypes for logging support."""

import sys

from zLOG.factory import Factory

# log-related datatypes

_logging_levels = {
    "critical": 50,
    "fatal": 50,
    "error": 40,
    "warn": 30,
    "warning": 30,
    "info": 20,
    "blather": 15,
    "debug": 10,
    "trace": 5,
    "all": 1,
    "notset": 0,
    }

def logging_level(value):
    s = str(value).lower()
    if _logging_levels.has_key(s):
        return _logging_levels[s]
    else:
        v = int(s)
        if v < 0 or v > 50:
            raise ValueError("log level not in range: " + `v`)
        return v

_log_format_variables = {
    'name': '',
    'levelno': '3',
    'levelname': 'DEBUG',
    'pathname': 'apath',
    'filename': 'afile',
    'module': 'amodule',
    'lineno': 1,
    'created': 1.1,
    'asctime': 'atime',
    'msecs': 1,
    'relativeCreated': 1,
    'thread': 1,
    'message': 'amessage',
    }

def log_format(value):
    value = ctrl_char_insert(value)
    try:
        # Make sure the format string uses only names that will be
        # provided, and has reasonable type flags for each, and does
        # not expect positional args.
        value % _log_format_variables
    except (ValueError, KeyError):
        raise ValueError, 'Invalid log format string %s' % value
    return value

_control_char_rewrites = {r'\n': '\n', r'\t': '\t', r'\b': '\b',
                          r'\f': '\f', r'\r': '\r'}.items()

def ctrl_char_insert(value):
    for pattern, replacement in _control_char_rewrites:
        value = value.replace(pattern, replacement)
    return value


class HandlerFactory(Factory):
    def __init__(self, section):
        Factory.__init__(self)
        self.section = section

    def create_loghandler(self):
        raise NotImplementedError(
            "subclasses must override create_loghandler()")

    def create(self):
        import logging
        logger = self.create_loghandler()
        logger.setFormatter(logging.Formatter(self.section.format,
                                              self.section.dateformat))
        logger.setLevel(self.section.level)
        return logger

class FileHandlerFactory(HandlerFactory):
    def create_loghandler(self):
        from zLOG.LogHandlers import StreamHandler, FileHandler
        path = self.section.path
        if path == "STDERR":
            return StreamHandler(sys.stderr)
        if path == "STDOUT":
            return StreamHandler(sys.stdout)
        return FileHandler(path)

_syslog_facilities = {
    "auth": 1,
    "authpriv": 1,
    "cron": 1,
    "daemon": 1,
    "kern": 1,
    "lpr": 1,
    "mail": 1,
    "news": 1,
    "security": 1,
    "syslog": 1,
    "user": 1,
    "uucp": 1,
    "local0": 1,
    "local1": 1,
    "local2": 1,
    "local3": 1,
    "local4": 1,
    "local5": 1,
    "local6": 1,
    "local7": 1,
    }

def syslog_facility(value):
    value = value.lower()
    if not _syslog_facilities.has_key(value):
        L = _syslog_facilities.keys()
        L.sort()
        raise ValueError("Syslog facility must be one of " + ", ".join(L))
    return value

class SyslogHandlerFactory(HandlerFactory):
    def create_loghandler(self):
        from zLOG.LogHandlers import SysLogHandler
        return SysLogHandler(self.section.address.address,
                             self.section.facility)

class Win32EventLogFactory(HandlerFactory):
    def create_loghandler(self):
        from zLOG.LogHandlers import Win32EventLogHandler
        return Win32EventLogHandler(self.section.appname)

def http_handler_url(value):
    import urlparse
    scheme, netloc, path, param, query, fragment = urlparse.urlparse(value)
    if scheme != 'http':
        raise ValueError, 'url must be an http url'
    if not netloc:
        raise ValueError, 'url must specify a location'
    if not path:
        raise ValueError, 'url must specify a path'
    q = []
    if param:
        q.append(';')
        q.append(param)
    if query:
        q.append('?')
        q.append(query)
    if fragment:
        q.append('#')
        q.append(fragment)
    return (netloc, path + ''.join(q))

def get_or_post(value):
    value = value.upper()
    if value not in ('GET', 'POST'):
        raise ValueError('method must be "GET" or "POST", instead received: '
                         + repr(value))
    return value

class HTTPHandlerFactory(HandlerFactory):
    def create_loghandler(self):
        from zLOG.LogHandlers import HTTPHandler
        host, selector = self.section.url
        return HTTPHandler(host, selector, self.section.method)

class SMTPHandlerFactory(HandlerFactory):
    def create_loghandler(self):
        from zLOG.LogHandlers import SMTPHandler
        host, port = self.section.smtp_server
        if not port:
            mailhost = host
        else:
            mailhost = host, port
        return SMTPHandler(mailhost, self.section.fromaddr,
                           self.section.toaddrs, self.section.subject)


class EventLogFactory(Factory):
    """
    A wrapper used to create loggers while delaying actual logger
    instance construction.  We need to do this because we may
    want to reference a logger before actually instantiating it (for example,
    to allow the app time to set an effective user).
    An instance of this wrapper is a callable which, when called, returns a
    logger object.
    """
    def __init__(self, section):
        Factory.__init__(self)
        self.level = section.level
        self.handler_factories = section.handlers

    def create(self):
        # set the logger up
        import logging
        logger = logging.getLogger("event")
        logger.handlers = []
        logger.propagate = 0
        logger.setLevel(self.level)
        if self.handler_factories:
            for handler_factory in self.handler_factories:
                handler = handler_factory()
                logger.addHandler(handler)
        else:
            from zLOG.LogHandlers import NullHandler
            logger.addHandler(NullHandler())
        return logger


=== Added File Zope/lib/python/zLOG/factory.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################

_marker = []

class Factory:
    """Generic wrapper for instance construction.

    Calling the factory causes the instance to be created if it hasn't
    already been created, and returns the object.  Calling the factory
    multiple times returns the same object.

    The instance is created using the factory's create() method, which
    must be overriden by subclasses.
    """
    def __init__(self):
        self.instance = _marker

    def __call__(self):
        if self.instance is _marker:
            self.instance = self.create()
        return self.instance

    def create(self):
        raise NotImplementedError("subclasses need to override create()")


=== Zope/lib/python/zLOG/EventLogger.py 1.1.2.6 => 1.1.2.7 ===
--- Zope/lib/python/zLOG/EventLogger.py:1.1.2.6	Fri Jan  3 01:47:00 2003
+++ Zope/lib/python/zLOG/EventLogger.py	Thu Jan 23 17:04:42 2003
@@ -29,6 +29,12 @@
 from LogHandlers import FileHandler, NullHandler, SysLogHandler
 from logging import StreamHandler, Formatter
 
+# Custom logging levels
+CUSTOM_BLATHER = 15 # Mapping for zLOG.BLATHER
+CUSTOM_TRACE = 5 # Mapping for zLOG.TRACE
+logging.addLevelName("BLATHER", CUSTOM_BLATHER)
+logging.addLevelName("TRACE", CUSTOM_TRACE)
+
 class EventLogger(BaseLogger):
     logger = logging.getLogger('event')
     log_format = '%(sev)s %(subsys)s %(summary)s%(detail)s'
@@ -85,23 +91,30 @@
 
     zLOG severity                      PEP282 severity
     -------------                      ---------------
-    PANIC (300)                        critical (50)
-    ERROR (200), PROBLEM (100)         error (40)
-    INFO (0)                           warn (30)
-    BLATHER (-100)                     info (20)
-    DEBUG (-200), TRACE (-300)         debug (10)
+    PANIC (300)                        FATAL, CRITICAL (50)
+    ERROR (200)                        ERROR (40)
+    WARNING, PROBLEM (100)             WARN (30)
+    INFO (0)                           INFO (20)
+    BLATHER (-100)                     BLATHER (15) [*]
+    DEBUG (-200)                       DEBUG (10)
+    TRACE (-300)                       TRACE (5) [*]
+
+    [*] BLATHER and TRACE are custom logging levels.
     """
     sev = zlog_severity
     if sev >= 300:
-        return logging.CRITICAL
-    if sev >= 100:
+        return logging.FATAL
+    if sev >= 200:
         return logging.ERROR
-    if sev >= 0:
+    if sev >= 100:
         return logging.WARN
-    if sev >= -100:
+    if sev >= 0:
         return logging.INFO
-    else:
+    if sev >= -100:
+        return CUSTOM_BLATHER
+    if sev >= -200:
         return logging.DEBUG
+    return CUSTOM_TRACE
 
 def log_time():
     """Return a simple time string without spaces suitable for logging."""
@@ -156,7 +169,8 @@
 def initialize_from_environment():
     """ Reinitialize the event logger from the environment """
     # clear the current handlers from the event logger
-    event_logger.logger.handlers = []
+    for h in event_logger.logger.handlers[:]:
+        event_logger.logger.removeHandler(h)
 
     handlers = []
 


=== Zope/lib/python/zLOG/__init__.py 1.8.4.5 => 1.8.4.6 ===
--- Zope/lib/python/zLOG/__init__.py:1.8.4.5	Fri Jan  3 01:47:00 2003
+++ Zope/lib/python/zLOG/__init__.py	Thu Jan 23 17:04:42 2003
@@ -25,7 +25,8 @@
 programs will replace this method with a method more suited to their needs.
 
 The module provides a register_subsystem method that does nothing, but
-provides a hook that logging management systems could use to collect information about subsystems being used.
+provides a hook that logging management systems could use to collect
+information about subsystems being used.
 
 The module defines several standard severities:
 
@@ -68,10 +69,6 @@
                traceback.  If provided, then a summary of the error
                is added to the detail.
 
-The callable object can provide a reinitialize method that may be
-called with no arguments to reopen the log files (if any) as part of a
-log-rotation facility.
-
 There is a default event logging facility that:
 
   - swallows logging information by default,
@@ -105,10 +102,26 @@
 # Flag indicating whether LOG() should call initialize()
 _call_initialize = 1
 
+# Function called to (re-)initialize the logger we're using
+_initializer = initialize_from_environment
+
 def initialize():
     global _call_initialize
     _call_initialize = 0
-    initialize_from_environment()
+    _initializer()
+
+def set_initializer(func):
+    """Set the function used to re-initialize the logs.
+
+    This should be called when initialize_from_environment() is not
+    appropiate.
+
+    This does not ensure that the new function gets called; the caller
+    should do that separately.
+    """
+    global _initializer
+    _initializer = func
+
 
 def LOG(subsystem, severity, summary, detail='', error=None, reraise=None):
     """Log some information