• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/build/lib/ZSI/wstools/logging.py

00001 # Copyright (c) 2003, The Regents of the University of California,
00002 # through Lawrence Berkeley National Laboratory (subject to receipt of
00003 # any required approvals from the U.S. Dept. of Energy).  All rights
00004 # reserved. 
00005 #
00006 """Logging"""
00007 ident = "$Id: logging.py 1395 2007-06-14 06:49:35Z boverhof $"
00008 import os, sys
00009 
00010 WARN = 1
00011 DEBUG = 2
00012 
00013 
00014 class ILogger:
00015     '''Logger interface, by default this class
00016     will be used and logging calls are no-ops.
00017     '''
00018     level = 0
00019     def __init__(self, msg):
00020         return
00021     def warning(self, *args, **kw):
00022         return
00023     def debug(self, *args, **kw):
00024         return
00025     def error(self, *args, **kw):
00026         return
00027     def setLevel(cls, level):
00028         cls.level = level
00029     setLevel = classmethod(setLevel)
00030     
00031     debugOn = lambda self: self.level >= DEBUG
00032     warnOn = lambda self: self.level >= WARN
00033     
00034 
00035 class BasicLogger(ILogger):
00036     last = ''
00037     
00038     def __init__(self, msg, out=sys.stdout):
00039         self.msg, self.out = msg, out
00040 
00041     def warning(self, msg, *args, **kw):
00042         if self.warnOn() is False: return
00043         if BasicLogger.last != self.msg:
00044             BasicLogger.last = self.msg
00045             print >>self, "---- ", self.msg, " ----"
00046         print >>self, "    %s  " %self.WARN,
00047         print >>self, msg %args
00048     WARN = '[WARN]'
00049     def debug(self, msg, *args, **kw):
00050         if self.debugOn() is False: return
00051         if BasicLogger.last != self.msg:
00052             BasicLogger.last = self.msg
00053             print >>self, "---- ", self.msg, " ----"
00054         print >>self, "    %s  " %self.DEBUG,
00055         print >>self, msg %args
00056     DEBUG = '[DEBUG]'
00057     def error(self, msg, *args, **kw):
00058         if BasicLogger.last != self.msg:
00059             BasicLogger.last = self.msg
00060             print >>self, "---- ", self.msg, " ----"
00061         print >>self, "    %s  " %self.ERROR,
00062         print >>self, msg %args
00063     ERROR = '[ERROR]'
00064 
00065     def write(self, *args):
00066         '''Write convenience function; writes strings.
00067         '''
00068         for s in args: self.out.write(s)
00069         event = ''.join(*args)
00070 
00071 
00072 _LoggerClass = BasicLogger
00073 
00074 class GridLogger(ILogger):
00075     def debug(self, msg, *args, **kw):
00076         kw['component'] = self.msg
00077         gridLog(event=msg %args, level='DEBUG', **kw)
00078 
00079     def warning(self, msg, *args, **kw):
00080         kw['component'] = self.msg
00081         gridLog(event=msg %args, level='WARNING', **kw)
00082 
00083     def error(self, msg, *args, **kw):
00084         kw['component'] = self.msg
00085         gridLog(event=msg %args, level='ERROR', **kw)
00086 
00087 
00088 # 
00089 # Registry of send functions for gridLog
00090 # 
00091 GLRegistry = {}
00092 
00093 class GLRecord(dict):
00094     """Grid Logging Best Practices Record, Distributed Logging Utilities
00095 
00096     The following names are reserved:
00097 
00098     event -- log event name
00099         Below is EBNF for the event name part of a log message.
00100             name      = <nodot> ( "." <name> )? 
00101             nodot     = {RFC3896-chars except "."}
00102 
00103         Suffixes:
00104             start: Immediately before the first action in a task.
00105             end: Immediately after the last action in a task (that succeeded).
00106             error: an error condition that does not correspond to an end event.
00107 
00108     ts -- timestamp
00109     level -- logging level (see levels below)
00110     status -- integer status code
00111     gid -- global grid identifier 
00112     gid, cgid -- parent/child identifiers
00113     prog -- program name
00114 
00115 
00116     More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python
00117 
00118     reserved -- list of reserved names, 
00119     omitname -- list of reserved names, output only values ('ts', 'event',)
00120     levels -- dict of levels and description
00121     """
00122     reserved = ('ts', 'event', 'level', 'status', 'gid', 'prog')
00123     omitname = ()
00124     levels = dict(FATAL='Component cannot continue, or system is unusable.',
00125         ALERT='Action must be taken immediately.',
00126         CRITICAL='Critical conditions (on the system).',
00127         ERROR='Errors in the component; not errors from elsewhere.',
00128         WARNING='Problems that are recovered from, usually.',
00129         NOTICE='Normal but significant condition.',
00130         INFO='Informational messages that would be useful to a deployer or administrator.',
00131         DEBUG='Lower level information concerning program logic decisions, internal state, etc.',
00132         TRACE='Finest granularity, similar to "stepping through" the component or system.',
00133     )
00134 
00135     def __init__(self, date=None, **kw):
00136         kw['ts'] = date or self.GLDate()
00137         kw['gid'] = kw.get('gid') or os.getpid()
00138         dict.__init__(self, kw)
00139 
00140     def __str__(self):
00141         """
00142         """
00143         from cStringIO import StringIO
00144         s = StringIO(); n = " "
00145         reserved = self.reserved; omitname = self.omitname; levels = self.levels
00146 
00147         for k in ( list(filter(lambda i: self.has_key(i), reserved)) + 
00148             list(filter(lambda i: i not in reserved, self.keys()))
00149         ):
00150             v = self[k]
00151             if k in omitname: 
00152                 s.write( "%s " %self.format[type(v)](v) )
00153                 continue
00154 
00155             if k == reserved[2] and v not in levels:
00156                 pass
00157 
00158             s.write( "%s=%s " %(k, self.format[type(v)](v) ) )
00159 
00160         s.write("\n")
00161         return s.getvalue()
00162 
00163     class GLDate(str):
00164         """Grid logging Date Format
00165         all timestamps should all be in the same time zone (UTC). 
00166         Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]:
00167 
00168            YYYY-MM-DDTHH:MM:SS.SSSSSSZ 
00169 
00170         """
00171         def __new__(self, args=None):
00172             """args -- datetime (year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
00173             """
00174             import datetime
00175             args = args or datetime.datetime.utcnow()
00176             l = (args.year, args.month, args.day, args.hour, args.minute, args.second, 
00177                  args.microsecond, args.tzinfo or 'Z')
00178 
00179             return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l)
00180 
00181     format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x,
00182         unicode:str, GLDate:str, }
00183 
00184 
00185 def gridLog(**kw):
00186     """Send GLRecord, Distributed Logging Utilities
00187     If the scheme is passed as a keyword parameter
00188     the value is expected to be a callable function
00189     that takes 2 parameters: url, outputStr
00190 
00191     GRIDLOG_ON   -- turn grid logging on
00192     GRIDLOG_DEST -- provide URL destination
00193     """
00194     import os
00195 
00196     if not bool( int(os.environ.get('GRIDLOG_ON', 0)) ):
00197         return
00198 
00199     url = os.environ.get('GRIDLOG_DEST')
00200     if url is None: 
00201         return
00202 
00203     ## NOTE: urlparse problem w/customized schemes 
00204     try:
00205         scheme = url[:url.find('://')]
00206         send = GLRegistry[scheme]
00207         send( url, str(GLRecord(**kw)), )
00208     except Exception, ex:
00209         print >>sys.stderr, "*** gridLog failed -- %s" %(str(kw))
00210 
00211 
00212 def sendUDP(url, outputStr):
00213     from socket import socket, AF_INET, SOCK_DGRAM
00214     idx1 = url.find('://') + 3; idx2 = url.find('/', idx1)
00215     if idx2 < idx1: idx2 = len(url)
00216     netloc = url[idx1:idx2]
00217     host,port = (netloc.split(':')+[80])[0:2]
00218     socket(AF_INET, SOCK_DGRAM).sendto( outputStr, (host,int(port)), )
00219 
00220 def writeToFile(url, outputStr):
00221     print >> open(url.split('://')[1], 'a+'), outputStr
00222 
00223 GLRegistry["gridlog-udp"] = sendUDP
00224 GLRegistry["file"] = writeToFile
00225 
00226 
00227 def setBasicLogger():
00228     '''Use Basic Logger. 
00229     '''
00230     setLoggerClass(BasicLogger)
00231     BasicLogger.setLevel(0)
00232 
00233 def setGridLogger():
00234     '''Use GridLogger for all logging events.
00235     '''
00236     setLoggerClass(GridLogger)
00237 
00238 def setBasicLoggerWARN():
00239     '''Use Basic Logger.
00240     '''
00241     setLoggerClass(BasicLogger)
00242     BasicLogger.setLevel(WARN)
00243 
00244 def setBasicLoggerDEBUG():
00245     '''Use Basic Logger.
00246     '''
00247     setLoggerClass(BasicLogger)
00248     BasicLogger.setLevel(DEBUG)
00249 
00250 def setLoggerClass(loggingClass):
00251     '''Set Logging Class.
00252     '''
00253 
00254 def setLoggerClass(loggingClass):
00255     '''Set Logging Class.
00256     '''
00257     assert issubclass(loggingClass, ILogger), 'loggingClass must subclass ILogger'
00258     global _LoggerClass
00259     _LoggerClass = loggingClass
00260 
00261 def setLevel(level=0):
00262     '''Set Global Logging Level.
00263     '''
00264     ILogger.level = level
00265 
00266 def getLevel():
00267     return ILogger.level
00268 
00269 def getLogger(msg):
00270     '''Return instance of Logging class.
00271     '''
00272     return _LoggerClass(msg)
00273 
00274 

Generated on Wed Oct 20 2010 11:12:16 for APBS by  doxygen 1.7.2