[Zodb-checkins] CVS: Zope/lib/python/zLOG - BaseLogger.py:1.2 EventLogger.py:1.2 LogHandlers.py:1.2 __init__.py:1.13 MinimalLogger.py:NONE

Chris McDonough chrism@zope.com
Sun, 24 Nov 2002 00:24:43 -0500


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

Modified Files:
	__init__.py 
Added Files:
	BaseLogger.py EventLogger.py LogHandlers.py 
Removed Files:
	MinimalLogger.py 
Log Message:
Use PEP282-based logger instead of homegrown.


=== Zope/lib/python/zLOG/BaseLogger.py 1.1 => 1.2 ===
--- /dev/null	Sun Nov 24 00:24:43 2002
+++ Zope/lib/python/zLOG/BaseLogger.py	Sun Nov 24 00:24:43 2002
@@ -0,0 +1,24 @@
+##############################################################################
+#
+# 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()
+


=== Zope/lib/python/zLOG/EventLogger.py 1.1 => 1.2 ===
--- /dev/null	Sun Nov 24 00:24:43 2002
+++ Zope/lib/python/zLOG/EventLogger.py	Sun Nov 24 00:24:43 2002
@@ -0,0 +1,191 @@
+##############################################################################
+#
+# 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, sys, 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)
+
+EventLogger = EventLogger()
+
+log_write = EventLogger.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
+    EventLogger.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)
+    EventLogger.logger.setLevel(severity)
+
+    for handler in handlers:
+        EventLogger.logger.addHandler(handler)
+


=== Zope/lib/python/zLOG/LogHandlers.py 1.1 => 1.2 ===
--- /dev/null	Sun Nov 24 00:24:43 2002
+++ Zope/lib/python/zLOG/LogHandlers.py	Sun Nov 24 00:24:43 2002
@@ -0,0 +1,78 @@
+##############################################################################
+#
+# 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 """
+
+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 = []
+        
+        
+        
+        
+    


=== Zope/lib/python/zLOG/__init__.py 1.12 => 1.13 ===
--- Zope/lib/python/zLOG/__init__.py:1.12	Fri Nov 22 13:17:39 2002
+++ Zope/lib/python/zLOG/__init__.py	Sun Nov 24 00:24:43 2002
@@ -88,8 +88,8 @@
 """
 __version__='$Revision$'[11:-2]
 
-from MinimalLogger import log_write, log_time, severity_string, \
-     _set_log_dest, initialize
+from EventLogger import log_write, log_time, severity_string, \
+     initialize_from_environment as initialize
 from traceback import format_exception
 
 # Standard severities

=== Removed File Zope/lib/python/zLOG/MinimalLogger.py ===