Package Ganga :: Package Utility :: Package external :: Package logging :: Module config
[hide private]
[frames] | no frames]

Source Code for Module Ganga.Utility.external.logging.config

  1  # Copyright 2001-2004 by Vinay Sajip. All Rights Reserved. 
  2  # 
  3  # Permission to use, copy, modify, and distribute this software and its 
  4  # documentation for any purpose and without fee is hereby granted, 
  5  # provided that the above copyright notice appear in all copies and that 
  6  # both that copyright notice and this permission notice appear in 
  7  # supporting documentation, and that the name of Vinay Sajip 
  8  # not be used in advertising or publicity pertaining to distribution 
  9  # of the software without specific, written prior permission. 
 10  # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
 11  # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 
 12  # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 
 13  # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 
 14  # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 
 15  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 16   
 17  """ 
 18  Configuration functions for the logging package for Python. The core package 
 19  is based on PEP 282 and comments thereto in comp.lang.python, and influenced 
 20  by Apache's log4j system. 
 21   
 22  Should work under Python versions >= 1.5.2, except that source line 
 23  information is not available unless 'sys._getframe()' is. 
 24   
 25  Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved. 
 26   
 27  To use, simply 'import logging' and log away! 
 28  """ 
 29   
 30  import sys, logging, logging.handlers, string, thread, threading, socket, struct, os 
 31   
 32  from SocketServer import ThreadingTCPServer, StreamRequestHandler 
 33   
 34   
 35  DEFAULT_LOGGING_CONFIG_PORT = 9030 
 36   
 37  if sys.platform == "win32": 
 38      RESET_ERROR = 10054   #WSAECONNRESET 
 39  else: 
 40      RESET_ERROR = 104     #ECONNRESET 
 41   
 42  # 
 43  #   The following code implements a socket listener for on-the-fly 
 44  #   reconfiguration of logging. 
 45  # 
 46  #   _listener holds the server object doing the listening 
 47  _listener = None 
 48   
49 -def fileConfig(fname, defaults=None):
50 """ 51 Read the logging configuration from a ConfigParser-format file. 52 53 This can be called several times from an application, allowing an end user 54 the ability to select from various pre-canned configurations (if the 55 developer provides a mechanism to present the choices and load the chosen 56 configuration). 57 In versions of ConfigParser which have the readfp method [typically 58 shipped in 2.x versions of Python], you can pass in a file-like object 59 rather than a filename, in which case the file-like object will be read 60 using readfp. 61 """ 62 import ConfigParser 63 64 cp = ConfigParser.ConfigParser(defaults) 65 if hasattr(cp, 'readfp') and hasattr(fname, 'readline'): 66 cp.readfp(fname) 67 else: 68 cp.read(fname) 69 #first, do the formatters... 70 flist = cp.get("formatters", "keys") 71 if len(flist): 72 flist = string.split(flist, ",") 73 formatters = {} 74 for form in flist: 75 sectname = "formatter_%s" % form 76 opts = cp.options(sectname) 77 if "format" in opts: 78 fs = cp.get(sectname, "format", 1) 79 else: 80 fs = None 81 if "datefmt" in opts: 82 dfs = cp.get(sectname, "datefmt", 1) 83 else: 84 dfs = None 85 f = logging.Formatter(fs, dfs) 86 formatters[form] = f 87 #next, do the handlers... 88 #critical section... 89 logging._acquireLock() 90 try: 91 try: 92 #first, lose the existing handlers... 93 logging._handlers.clear() 94 #now set up the new ones... 95 hlist = cp.get("handlers", "keys") 96 if len(hlist): 97 hlist = string.split(hlist, ",") 98 handlers = {} 99 fixups = [] #for inter-handler references 100 for hand in hlist: 101 try: 102 sectname = "handler_%s" % hand 103 klass = cp.get(sectname, "class") 104 opts = cp.options(sectname) 105 if "formatter" in opts: 106 fmt = cp.get(sectname, "formatter") 107 else: 108 fmt = "" 109 klass = eval(klass, vars(logging)) 110 args = cp.get(sectname, "args") 111 args = eval(args, vars(logging)) 112 h = apply(klass, args) 113 if "level" in opts: 114 level = cp.get(sectname, "level") 115 h.setLevel(logging._levelNames[level]) 116 if len(fmt): 117 h.setFormatter(formatters[fmt]) 118 #temporary hack for FileHandler and MemoryHandler. 119 if klass == logging.handlers.MemoryHandler: 120 if "target" in opts: 121 target = cp.get(sectname,"target") 122 else: 123 target = "" 124 if len(target): #the target handler may not be loaded yet, so keep for later... 125 fixups.append((h, target)) 126 handlers[hand] = h 127 except: #if an error occurs when instantiating a handler, too bad 128 pass #this could happen e.g. because of lack of privileges 129 #now all handlers are loaded, fixup inter-handler references... 130 for fixup in fixups: 131 h = fixup[0] 132 t = fixup[1] 133 h.setTarget(handlers[t]) 134 #at last, the loggers...first the root... 135 llist = cp.get("loggers", "keys") 136 llist = string.split(llist, ",") 137 llist.remove("root") 138 sectname = "logger_root" 139 root = logging.root 140 log = root 141 opts = cp.options(sectname) 142 if "level" in opts: 143 level = cp.get(sectname, "level") 144 log.setLevel(logging._levelNames[level]) 145 for h in root.handlers[:]: 146 root.removeHandler(h) 147 hlist = cp.get(sectname, "handlers") 148 if len(hlist): 149 hlist = string.split(hlist, ",") 150 for hand in hlist: 151 log.addHandler(handlers[hand]) 152 #and now the others... 153 #we don't want to lose the existing loggers, 154 #since other threads may have pointers to them. 155 #existing is set to contain all existing loggers, 156 #and as we go through the new configuration we 157 #remove any which are configured. At the end, 158 #what's left in existing is the set of loggers 159 #which were in the previous configuration but 160 #which are not in the new configuration. 161 existing = root.manager.loggerDict.keys() 162 #now set up the new ones... 163 for log in llist: 164 sectname = "logger_%s" % log 165 qn = cp.get(sectname, "qualname") 166 opts = cp.options(sectname) 167 if "propagate" in opts: 168 propagate = cp.getint(sectname, "propagate") 169 else: 170 propagate = 1 171 logger = logging.getLogger(qn) 172 if qn in existing: 173 existing.remove(qn) 174 if "level" in opts: 175 level = cp.get(sectname, "level") 176 logger.setLevel(logging._levelNames[level]) 177 for h in logger.handlers[:]: 178 logger.removeHandler(h) 179 logger.propagate = propagate 180 logger.disabled = 0 181 hlist = cp.get(sectname, "handlers") 182 if len(hlist): 183 hlist = string.split(hlist, ",") 184 for hand in hlist: 185 logger.addHandler(handlers[hand]) 186 #Disable any old loggers. There's no point deleting 187 #them as other threads may continue to hold references 188 #and by disabling them, you stop them doing any logging. 189 for log in existing: 190 root.manager.loggerDict[log].disabled = 1 191 except: 192 import traceback 193 ei = sys.exc_info() 194 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) 195 del ei 196 finally: 197 logging._releaseLock()
198
199 -def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
200 """ 201 Start up a socket server on the specified port, and listen for new 202 configurations. 203 204 These will be sent as a file suitable for processing by fileConfig(). 205 Returns a Thread object on which you can call start() to start the server, 206 and which you can join() when appropriate. To stop the server, call 207 stopListening(). 208 """ 209 if not thread: 210 raise NotImplementedError, "listen() needs threading to work" 211 212 class ConfigStreamHandler(StreamRequestHandler): 213 """ 214 Handler for a logging configuration request. 215 216 It expects a completely new logging configuration and uses fileConfig 217 to install it. 218 """ 219 def handle(self): 220 """ 221 Handle a request. 222 223 Each request is expected to be a 4-byte length, 224 followed by the config file. Uses fileConfig() to do the 225 grunt work. 226 """ 227 import tempfile 228 try: 229 conn = self.connection 230 chunk = conn.recv(4) 231 if len(chunk) == 4: 232 slen = struct.unpack(">L", chunk)[0] 233 chunk = self.connection.recv(slen) 234 while len(chunk) < slen: 235 chunk = chunk + conn.recv(slen - len(chunk)) 236 #Apply new configuration. We'd like to be able to 237 #create a StringIO and pass that in, but unfortunately 238 #1.5.2 ConfigParser does not support reading file 239 #objects, only actual files. So we create a temporary 240 #file and remove it later. 241 file = tempfile.mktemp(".ini") 242 f = open(file, "w") 243 f.write(chunk) 244 f.close() 245 fileConfig(file) 246 os.remove(file) 247 except socket.error, e: 248 if type(e.args) != types.TupleType: 249 raise 250 else: 251 errcode = e.args[0] 252 if errcode != RESET_ERROR: 253 raise
254 255 class ConfigSocketReceiver(ThreadingTCPServer): 256 """ 257 A simple TCP socket-based logging config receiver. 258 """ 259 260 allow_reuse_address = 1 261 262 def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT, 263 handler=None): 264 ThreadingTCPServer.__init__(self, (host, port), handler) 265 logging._acquireLock() 266 self.abort = 0 267 logging._releaseLock() 268 self.timeout = 1 269 270 def serve_until_stopped(self): 271 import select 272 abort = 0 273 while not abort: 274 rd, wr, ex = select.select([self.socket.fileno()], 275 [], [], 276 self.timeout) 277 if rd: 278 self.handle_request() 279 logging._acquireLock() 280 abort = self.abort 281 logging._releaseLock() 282 283 def serve(rcvr, hdlr, port): 284 server = rcvr(port=port, handler=hdlr) 285 global _listener 286 logging._acquireLock() 287 _listener = server 288 logging._releaseLock() 289 server.serve_until_stopped() 290 291 return threading.Thread(target=serve, 292 args=(ConfigSocketReceiver, 293 ConfigStreamHandler, port)) 294
295 -def stopListening():
296 """ 297 Stop the listening server which was created with a call to listen(). 298 """ 299 global _listener 300 if _listener: 301 logging._acquireLock() 302 _listener.abort = 1 303 _listener = None 304 logging._releaseLock()
305