Back to index

plone3  3.1.7
Log.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 ## CMFPlacefulWorkflow
00003 ## Copyright (C)2006 Ingeniweb
00004 
00005 ## This program is free software; you can redistribute it and/or modify
00006 ## it under the terms of the GNU General Public License as published by
00007 ## the Free Software Foundation; either version 2 of the License, or
00008 ## (at your option) any later version.
00009 
00010 ## This program is distributed in the hope that it will be useful,
00011 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ## GNU General Public License for more details.
00014 
00015 ## You should have received a copy of the GNU General Public License
00016 ## along with this program; see the file COPYING. If not, write to the
00017 ## Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 """
00019 One can override the following variables :
00020 
00021 LOG_LEVEL : The log level, from 0 to 5.
00022 A Log level n implies all logs from 0 to n.
00023 LOG_LEVEL MUST BE OVERRIDEN !!!!!
00024 
00025 
00026 LOG_NONE = 0            => No log output
00027 LOG_CRITICAL = 1        => Critical problems (data consistency, module integrity, ...)
00028 LOG_ERROR = 2           => Error (runtime exceptions, ...)
00029 LOG_WARNING = 3         => Warning (non-blocking exceptions, ...)
00030 LOG_NOTICE = 4          => Notices (Special conditions, ...)
00031 LOG_DEBUG = 5           => Debug (Debugging information)
00032 
00033 
00034 LOG_PROCESSOR : A dictionnary holding, for each key, the data processor.
00035 A data processor is a function that takes only one parameter : the data to print.
00036 Default : LogFile for all keys.
00037 """
00038 __version__ = "$Revision: 36863 $"
00039 # $Source: /cvsroot/ingeniweb/PloneSubscription/SubscriptionTool.py,v $
00040 # $Id: Log.py 36863 2007-02-05 21:30:44Z encolpe $
00041 __docformat__ = 'restructuredtext'
00042 
00043 
00044 
00045 LOG_LEVEL = -1
00046 
00047 LOG_NONE = 0
00048 LOG_CRITICAL = 1
00049 LOG_ERROR = 2
00050 LOG_WARNING = 3
00051 LOG_NOTICE = 4
00052 LOG_DEBUG = 5
00053 
00054 from sys import stderr
00055 import time
00056 import traceback
00057 import os
00058 import pprint
00059 import StringIO
00060 
00061 LOG_STACK_DEPTH = [-2]
00062 
00063 def Log(level, *args, **kw):
00064     """
00065     Log(level, *args, **kw) => Pretty-prints data on the console with additional information.
00066     Use a STACK_OFFSET paramter to lower the stack depth
00067     """
00068     if LOG_LEVEL and level <= LOG_LEVEL:
00069         if not level in LOG_PROCESSOR.keys():
00070             raise ValueError, "Invalid log level :", level
00071 
00072         stack = ""
00073         stackItems = traceback.extract_stack()
00074         for depth in LOG_STACK_DEPTH:
00075             stackItem = stackItems[depth - kw.get('STACK_OFFSET', 0)]
00076             stack = "%s%s:%s:" % (stack, os.path.basename(stackItem[0]), stackItem[1],)
00077 ##        return "%s(%s)"%( os.path.basename(stackItem[0]), stackItem[1] )
00078 ##        pr = "%s %s %010.02f %08d/%02d > " % (LOG_LABEL[level], time.ctime(time.time()), time.clock(), thread.get_ident(), threading.activeCount())
00079         pr = "%8s %s%s: " % (
00080             LOG_LABEL[level],
00081             stack,
00082             time.ctime(time.time()),
00083 ##            thread.get_ident(),
00084 ##            threading.activeCount()
00085             )
00086         for data in args:
00087             try:
00088                 if "\n" in data:
00089                     data = data
00090                 else:
00091                     data = pprint.pformat(data)
00092             except:
00093                 data = pprint.pformat(data)
00094             pr = pr + data + " "
00095 
00096         LOG_PROCESSOR[level](level, LOG_LABEL[level], pr, stackItems)
00097 
00098 
00099 def FormatStack(stack):
00100     """
00101     FormatStack(stack) => string
00102     
00103     Return a 'loggable' version of the stack trace
00104     """
00105     ret = ""
00106     for s in stack:
00107         ret = ret + "%s:%s:%s: %s\n" % (os.path.basename(s[0]), s[1], s[2], s[3])
00108     return ret
00109 
00110 
00111 def LogException():
00112     """
00113     LogException () => None
00114 
00115     Print an exception information on the console
00116     """
00117     s = StringIO.StringIO()
00118     Log(LOG_NOTICE, "EXCEPTION >>>", STACK_OFFSET = 1)
00119     traceback.print_exc(file = s, )
00120     s.seek(0)
00121     Log(LOG_NOTICE, s.read())
00122     Log(LOG_NOTICE, "<<< EXCEPTION", STACK_OFFSET = 1)
00123 
00124 
00125 LOG_OUTPUT = stderr
00126 def LogFile(level, label, data, stack):
00127     """
00128     LogFile : writes data to the LOG_OUTPUT file.
00129     """
00130     LOG_OUTPUT.write(data+'\n')
00131     LOG_OUTPUT.flush()
00132 
00133 
00134 import logging
00135 logger = logging.getLogger('CMFPlacefulWorkflow')
00136 
00137 zLogLevelConverter = {
00138     LOG_NONE: logging.NOTSET,
00139     LOG_CRITICAL: logging.CRITICAL,
00140     LOG_ERROR: logging.ERROR,
00141     LOG_WARNING: logging.WARNING,
00142     LOG_NOTICE: logging.INFO,
00143     LOG_DEBUG: logging.DEBUG,
00144     }
00145 
00146 def LogzLog(level, label, data, stack):
00147     """
00148     LogzLog : writes data though Zope's logging facility
00149     """
00150     logger.log(zLogLevelConverter[level], data)
00151 
00152     
00153 
00154 LOG_PROCESSOR = {
00155     LOG_NONE: LogzLog,
00156     LOG_CRITICAL: LogzLog,
00157     LOG_ERROR: LogzLog,
00158     LOG_WARNING: LogzLog,
00159     LOG_NOTICE: LogzLog,
00160     LOG_DEBUG: LogFile,
00161     }
00162     
00163 
00164 LOG_LABEL = {
00165     LOG_NONE: "",
00166     LOG_CRITICAL: "CRITICAL",
00167     LOG_ERROR:    "ERROR   ",
00168     LOG_WARNING:  "WARNING ",
00169     LOG_NOTICE:   "NOTICE  ",
00170     LOG_DEBUG:    "DEBUG   ",
00171     }
00172