[Zodb-checkins] CVS: ZODB3/zLOG - BaseLogger.py:1.2.14.1 EventLogger.py:1.4.2.1 LogHandlers.py:1.3.6.1 __init__.py:1.8.40.2 FormatException.py:NONE MinimalLogger.py:NONE

Fred L. Drake, Jr. fred@zope.com
Tue, 17 Dec 2002 14:32:41 -0500


Update of /cvs-repository/ZODB3/zLOG
In directory cvs.zope.org:/tmp/cvs-serv6789

Modified Files:
      Tag: ZODB3-fast-restart-branch
	__init__.py 
Added Files:
      Tag: ZODB3-fast-restart-branch
	BaseLogger.py EventLogger.py LogHandlers.py 
Removed Files:
      Tag: ZODB3-fast-restart-branch
	FormatException.py MinimalLogger.py 
Log Message:
Backport the logging package integration from the Zope 2 trunk.

=== Added File ZODB3/zLOG/BaseLogger.py ===
##############################################################################
#
# Copyright (c) 2001, 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
#
##############################################################################
"""
An abstract logger meant to provide features to the access logger,
the event logger, and the debug logger.
"""

class BaseLogger:
    def reopen(self):
        for handler in self.logger.handlers:
            if hasattr(handler, 'reopen') and callable(handler.reopen):
                handler.reopen()



=== Added File ZODB3/zLOG/EventLogger.py ===
##############################################################################
#
# Copyright (c) 2001, 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
#
##############################################################################
"""
A logging module which handles event messages.

This uses Vinay Sajip's PEP 282 logging module.
"""

__version__='$Revision$'[11:-2]

import os, time
try:
    import textwrap
except ImportError:
    textwrap = None
import logging
from BaseLogger import BaseLogger
from LogHandlers import FileHandler, NullHandler, SysLogHandler
from logging import StreamHandler, Formatter

class EventLogger(BaseLogger):
    logger = logging.getLogger('event')
    logger.addHandler(NullHandler())
    log_format = '%(sev)s %(subsys)s %(summary)s%(detail)s'

    def log(self, subsystem, severity, summary, detail, error):
        if error:
            kw = {'exc_info':1}
        else:
            kw = {}

        if detail:
            detail = '\n' + detail
        else:
            detail = ''

        msg = self.log_format % {
            'sev' : severity_string(severity),
            'subsys' : subsystem,
            'summary': summary,
            'detail' : detail,
            }

        if textwrap and len(msg) > 80:
            msg = '\n'.join(textwrap.wrap(
                msg, width=79, subsequent_indent=" "*20,
                break_long_words=0))

        severity = zlog_to_pep282_severity(severity)
        self.logger.log(severity, msg, **kw)

event_logger = EventLogger()

log_write = event_logger.log

def severity_string(severity, mapping={
    -300: 'TRACE',
    -200: 'DEBUG',
    -100: 'BLATHER',
       0: 'INFO',
     100: 'PROBLEM',
     200: 'ERROR',
     300: 'PANIC',
    }):
    """Convert a severity code to a string."""
    s = mapping.get(int(severity), '')
    return "%s(%s)" % (s, severity)

def zlog_to_pep282_severity(zlog_severity):
    """
    We map zLOG severities to PEP282 severities here.
    This is how they are mapped:

    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)
    """
    sev = zlog_severity
    if sev >= 300:
        return logging.CRITICAL
    if sev >= 100:
        return logging.ERROR
    if sev >= 0:
        return logging.WARN
    if sev >= -100:
        return logging.INFO
    else:
        return logging.DEBUG

def log_time():
    """Return a simple time string without spaces suitable for logging."""
    return ("%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d"
            % time.localtime()[:6])

def get_env_severity_info():
    # EVENT_LOG_SEVERITY is the preferred envvar, but we accept
    # STUPID_LOG_SEVERITY also
    eget = os.environ.get
    severity = eget('EVENT_LOG_SEVERITY') or eget('STUPID_LOG_SEVERITY')
    if severity:
        severity = int(severity)
    else:
        severity = 0 # INFO
    return severity

def get_env_syslog_info():
    eget = os.environ.get
    addr = None
    port = None
    path = eget('ZSYSLOG')
    facility = eget('ZSYSLOG_FACILITY', 'user')
    server = eget('ZSYSLOG_SERVER')
    if server:
        addr, port = server.split(':')
        port = int(port)
    if addr:
        return (facility, (addr, port))
    else:
        return (facility, path)

def get_env_file_info():
    eget = os.environ.get
    # EVENT_LOG_FILE is the preferred envvar, but we accept
    # STUPID_LOG_FILE also
    path = eget('EVENT_LOG_FILE')
    if path is None:
        path = eget('STUPID_LOG_FILE')
    if path is None:
        dest = None
    else:
        dest = path
    return dest

formatters = {
    'file':    Formatter(fmt='------\n%(asctime)s %(message)s',
                         datefmt='%Y-%m-%dT%H:%M:%S'),
    'syslog':  Formatter(fmt='%(message)s'),
    }

def initialize_from_environment():
    """ Reinitialize the event logger from the environment """
    # clear the current handlers from the event logger
    event_logger.logger.handlers = []

    handlers = []

    # set up syslog handler if necessary
    facility, syslogdest = get_env_syslog_info()
    if syslogdest:
        handler = SysLogHandler(syslogdest, facility)
        handler.setFormatter(formatters['syslog'])
        handlers.append(handler)

    # set up file handler if necessary
    filedest = get_env_file_info()
    if filedest:
        handler = FileHandler(filedest)
        handler.setFormatter(formatters['file'])
        handlers.append(handler)
    elif filedest == '':
        # if dest is an empty string, log to standard error
        handler = StreamHandler()
        handler.setFormatter(formatters['file'])
        handlers.append(handler)
    else:
        # log to nowhere, but install a 'null' handler in order to
        # prevent error messages from emanating due to a missing handler
        handlers.append(NullHandler())

    severity = get_env_severity_info()
    severity = zlog_to_pep282_severity(severity)
    event_logger.logger.setLevel(severity)

    for handler in handlers:
        event_logger.logger.addHandler(handler)


=== Added File ZODB3/zLOG/LogHandlers.py ===
##############################################################################
#
# Copyright (c) 2001 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
#
##############################################################################
"""Handlers which can plug into a PEP 282 logger."""

import sys

from logging import Handler, StreamHandler
from logging.handlers import SysLogHandler

class FileHandler(StreamHandler):
    """
    A file handler which allows for reopening of logs in favor of the
    'rollover' features of the standard PEP282 FileHandler.
    """
    def __init__(self, filename, mode="a+"):
        StreamHandler.__init__(self, open(filename, mode))
        self.baseFilename = filename
        self.mode = mode

    def close(self):
        self.stream.close()

    def reopen(self):
        self.close()
        self.stream = open(self.baseFilename, self.mode)

class NullHandler(Handler):
    """
    A null handler.  Does nothing.
    """
    def emit(self, record):
        pass

    def handle(self, record):
        pass

class StartupHandler(Handler):
    """
    A handler which outputs messages to a stream but also buffers them until
    they can be flushed to a target handler.  Useful at startup before we can
    know that we can safely write to a config-specified handler.
    """
    def __init__(self, stream=None):
        Handler.__init__(self)
        if not stream:
            stream = sys.stderr
        self.stream = stream
        self.buffer = []

    def emit(self, record):
        try:
            self.buffer.append(record)
            msg = self.format(record)
            self.stream.write("%s\n" % msg)
            self.flush()
        except:
            self.handleError()

    def flush(self):
        self.stream.flush()

    def flushBufferTo(self, target):
        for record in self.buffer:
            target.handle(record)
        self.buffer = []
        
        
        
        
    


=== ZODB3/zLOG/__init__.py 1.8.40.1 => 1.8.40.2 ===
--- ZODB3/zLOG/__init__.py:1.8.40.1	Tue Dec 17 11:26:43 2002
+++ ZODB3/zLOG/__init__.py	Tue Dec 17 14:32:40 2002
@@ -8,7 +8,7 @@
 # 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
+# FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
 
@@ -47,7 +47,7 @@
 
   PANIC=300    -- We're dead!
 
-Also, looging facilities will normally ignore negative severities.
+Also, logging facilities will normally ignore negative severities.
 
 To plug in a log handler, simply replace the log_write function
 with a callable object that takes 5 arguments:
@@ -89,9 +89,9 @@
 """
 __version__='$Revision$'[11:-2]
 
-from MinimalLogger import log_write, log_time, severity_string, \
-     _set_log_dest, initialize
-from FormatException import format_exception
+from EventLogger import log_write, log_time, severity_string, \
+     initialize_from_environment
+from traceback import format_exception
 
 # Standard severities
 TRACE   = -300
@@ -103,6 +103,14 @@
 ERROR   =  200
 PANIC   =  300
 
+# Flag indicating whether LOG() should call initialize()
+_call_initialize = 1
+
+def initialize():
+    global _call_initialize
+    _call_initialize = 0
+    initialize_from_environment()
+
 def LOG(subsystem, severity, summary, detail='', error=None, reraise=None):
     """Log some information
 
@@ -128,6 +136,8 @@
                  error is reraised.
 
     """
+    if _call_initialize:
+        initialize()
     log_write(subsystem, severity, summary, detail, error)
     if reraise and error:
         raise error[0], error[1], error[2]

=== Removed File ZODB3/zLOG/FormatException.py ===

=== Removed File ZODB3/zLOG/MinimalLogger.py ===