You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

227 lines
6.7 KiB

  1. # Copyright (c) 2003, The Regents of the University of California,
  2. # through Lawrence Berkeley National Laboratory (subject to receipt of
  3. # any required approvals from the U.S. Dept. of Energy). All rights
  4. # reserved.
  5. #
  6. """Logging"""
  7. ident = "$Id$"
  8. import sys
  9. WARN = 1
  10. DEBUG = 2
  11. class ILogger:
  12. '''Logger interface, by default this class
  13. will be used and logging calls are no-ops.
  14. '''
  15. level = 0
  16. def __init__(self, msg):
  17. return
  18. def warning(self, *args):
  19. return
  20. def debug(self, *args):
  21. return
  22. def error(self, *args):
  23. return
  24. def setLevel(cls, level):
  25. cls.level = level
  26. setLevel = classmethod(setLevel)
  27. debugOn = lambda self: self.level >= DEBUG
  28. warnOn = lambda self: self.level >= WARN
  29. class BasicLogger(ILogger):
  30. last = ''
  31. def __init__(self, msg, out=sys.stdout):
  32. self.msg, self.out = msg, out
  33. def warning(self, msg, *args):
  34. if self.warnOn() is False: return
  35. if BasicLogger.last != self.msg:
  36. BasicLogger.last = self.msg
  37. print >>self, "---- ", self.msg, " ----"
  38. print >>self, " %s " %BasicLogger.WARN,
  39. print >>self, msg %args
  40. WARN = '[WARN]'
  41. def debug(self, msg, *args):
  42. if self.debugOn() is False: return
  43. if BasicLogger.last != self.msg:
  44. BasicLogger.last = self.msg
  45. print >>self, "---- ", self.msg, " ----"
  46. print >>self, " %s " %BasicLogger.DEBUG,
  47. print >>self, msg %args
  48. DEBUG = '[DEBUG]'
  49. def error(self, msg, *args):
  50. if BasicLogger.last != self.msg:
  51. BasicLogger.last = self.msg
  52. print >>self, "---- ", self.msg, " ----"
  53. print >>self, " %s " %BasicLogger.ERROR,
  54. print >>self, msg %args
  55. ERROR = '[ERROR]'
  56. def write(self, *args):
  57. '''Write convenience function; writes strings.
  58. '''
  59. for s in args: self.out.write(s)
  60. _LoggerClass = BasicLogger
  61. class GLRecord(dict):
  62. """Grid Logging Best Practices Record, Distributed Logging Utilities
  63. The following names are reserved:
  64. event -- log event name
  65. Below is EBNF for the event name part of a log message.
  66. name = <nodot> ( "." <name> )?
  67. nodot = {RFC3896-chars except "."}
  68. Suffixes:
  69. start: Immediately before the first action in a task.
  70. end: Immediately after the last action in a task (that succeeded).
  71. error: an error condition that does not correspond to an end event.
  72. date -- timestamp
  73. level -- logging level (see levels below)
  74. status -- integer status code
  75. gid -- global grid identifier
  76. gid, cgid -- parent/child identifiers
  77. prog -- program name
  78. More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python
  79. reserved -- list of reserved names,
  80. omitname -- list of reserved names, output only values
  81. levels -- dict of levels and description
  82. """
  83. reserved = ('date', 'event', 'level', 'status', 'gid', 'prog')
  84. omitname = ('date', 'event',)
  85. levels = dict(FATAL='Component cannot continue, or system is unusable.',
  86. ALERT='Action must be taken immediately.',
  87. CRITICAL='Critical conditions (on the system).',
  88. ERROR='Errors in the component; not errors from elsewhere.',
  89. WARNING='Problems that are recovered from, usually.',
  90. NOTICE='Normal but significant condition.',
  91. INFO='Informational messages that would be useful to a deployer or administrator.',
  92. DEBUG='Lower level information concerning program logic decisions, internal state, etc.',
  93. TRACE='Finest granularity, similar to "stepping through" the component or system.',
  94. )
  95. def __init__(self, date=None, **kw):
  96. kw['date'] = date or self.GLDate()
  97. dict.__init__(self, kw)
  98. def __str__(self):
  99. """
  100. """
  101. from cStringIO import StringIO
  102. s = StringIO(); n = " "
  103. reserved = self.reserved; omitname = self.omitname; levels = self.levels
  104. for k in ( list(filter(lambda i: self.has_key(i), reserved)) +
  105. list(filter(lambda i: i not in reserved, self.keys()))
  106. ):
  107. v = self[k]
  108. if k in omitname:
  109. s.write( "%s " %self.format[type(v)](v) )
  110. continue
  111. if k == reserved[2] and v not in levels:
  112. pass
  113. s.write( "%s=%s " %(k, self.format[type(v)](v) ) )
  114. s.write("\n")
  115. return s.getvalue()
  116. class GLDate(str):
  117. """Grid logging Date Format
  118. all timestamps should all be in the same time zone (UTC).
  119. Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]:
  120. YYYY-MM-DDTHH:MM:SS.SSSSSSZ
  121. """
  122. def __new__(self, args=None):
  123. """args -- datetime (year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
  124. """
  125. import datetime
  126. args = args or datetime.datetime.utcnow()
  127. l = (args.year, args.month, args.day, args.hour, args.minute, args.second,
  128. args.microsecond, args.tzinfo or 'Z')
  129. return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l)
  130. format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x,
  131. unicode:str, GLDate:str, }
  132. def sendGridLog(**kw):
  133. """Send GLRecord, Distributed Logging Utilities
  134. """
  135. import os
  136. from socket import socket, AF_INET, SOCK_DGRAM
  137. if not bool(os.environ.get('GRIDLOG_ON', False)):
  138. return
  139. url = os.environ.get('GRIDLOG_DEST')
  140. if url is None:
  141. return
  142. try:
  143. idx1 = url.find('://') + 3
  144. idx2 = url.find('/', idx1)
  145. if idx2 < idx1: idx2 = len(url)
  146. netloc = url[idx1:idx2]
  147. host,port = (netloc.split(':')+[80])[0:2]
  148. socket(AF_INET, SOCK_DGRAM).sendto( str(GLRecord(**kw)),
  149. (host,int(port)),)
  150. except Exception, ex:
  151. print >>sys.stderr, "*** gridlog failed -- %s" %(str(kw))
  152. def setBasicLogger():
  153. '''Use Basic Logger.
  154. '''
  155. setLoggerClass(BasicLogger)
  156. BasicLogger.setLevel(0)
  157. def setBasicLoggerWARN():
  158. '''Use Basic Logger.
  159. '''
  160. setLoggerClass(BasicLogger)
  161. BasicLogger.setLevel(WARN)
  162. def setBasicLoggerDEBUG():
  163. '''Use Basic Logger.
  164. '''
  165. setLoggerClass(BasicLogger)
  166. BasicLogger.setLevel(DEBUG)
  167. def setLoggerClass(loggingClass):
  168. '''Set Logging Class.
  169. '''
  170. assert issubclass(loggingClass, ILogger), 'loggingClass must subclass ILogger'
  171. global _LoggerClass
  172. _LoggerClass = loggingClass
  173. def setLevel(level=0):
  174. '''Set Global Logging Level.
  175. '''
  176. ILogger.level = level
  177. def getLevel():
  178. return ILogger.level
  179. def getLogger(msg):
  180. '''Return instance of Logging class.
  181. '''
  182. return _LoggerClass(msg)