Package AccessEngine :: Module AELog
[hide private]
[frames] | no frames]

Source Code for Module AccessEngine.AELog

  1  ''' 
  2  Defines a function for configuring the standard Python logging module, a class 
  3  that redirects print statements through the configured logging system, and 
  4  a class that defines a logging handler using XML-RPC as the transport. 
  5   
  6  @var LOG_FORMAT: Default log output format 
  7  @type LOG_FORMAT: string 
  8   
  9  @author: Peter Parente 
 10  @organization: IBM Corporation 
 11  @copyright: Copyright (c) 2005, 2007 IBM Corporation 
 12  @license: The BSD License 
 13   
 14  @author: Frank Zenker 
 15  @organization: IT Science Center Ruegen gGmbH, Germany 
 16  @copyright: Copyright (c) 2007, 2008 ITSC Ruegen 
 17  @license: The BSD License 
 18   
 19  All rights reserved. This program and the accompanying materials are made  
 20  available under the terms of the BSD license which accompanies 
 21  this distribution, and is available at  
 22  U{http://www.opensource.org/licenses/bsd-license.php} 
 23  ''' 
 24  import logging, logging.config, sys, socket, xmlrpclib 
 25   
 26  # define a default format for log entries 
 27  # see http://docs.python.org/lib/node352.html 
 28  LOG_FORMAT = '[%(name)s %(levelname)s %(asctime)s] %(message)s' 
 29   
30 -class XMLRPCHandler(logging.Handler):
31 ''' 32 Defines an XML-RPC handler for the standard Python logging system. 33 34 @ivar server: Server proxy mirroring methods on the server side 35 @type server: xmlrpclib.ServerProxy 36 '''
37 - def __init__(self, host='127.0.0.1', port=9000):
38 ''' 39 Constructs a proxy to the server. 40 41 @param host: Hostname on which the server is running 42 @type host: string 43 @param port: Port on which the server is listening 44 @type port: integer 45 ''' 46 logging.Handler.__init__(self) 47 self.server = xmlrpclib.ServerProxy('http://%s:%d' % (host, port))
48
49 - def emit(self, record):
50 ''' 51 Writes interpolated string log messages to the server. 52 53 @param record: Record to log 54 @type record: logging.LogRecord 55 ''' 56 if record is not None: 57 msg = self.format(record) 58 if msg is not None: 59 try: 60 self.server.write(msg) 61 except socket.error: 62 # ignore connection exceptions 63 pass
64 65 # hack: the logging.config.fileConfig function only looks in the logging 66 # module name space for handlers; put our handler there 67 logging.XMLRPCHandler = XMLRPCHandler 68
69 -class PrintLogger(object):
70 ''' 71 Provides a dirt-simple interface compatible with stdout and stderr. When 72 assigned to sys.stdout or sys.stderr, an instance of this class redirects 73 print statements to the logging system. This means the result of the 74 print statements can be silenced, sent to a file, etc. using the command 75 line options to SUE. The log level used is defined by the L{LEVEL} constant 76 in this class. 77 78 @cvar LEVEL: Logging level for writes directed through this class, above 79 DEBUG and below INFO 80 @type LEVEL: integer 81 @ivar log: Reference to the Print log channel 82 @type log: logging.Logger 83 ''' 84 LEVEL = 15 85
86 - def __init__(self):
87 ''' 88 Create the logger. 89 ''' 90 self.log = logging.getLogger('print') 91 self.chunks = []
92
93 - def write(self, data):
94 ''' 95 Write the given data at the debug level to the logger. Stores chunks of 96 text until a new line is encountered, then sends to the logger. 97 98 @param data: Any object that can be converted to a string 99 @type data: stringable 100 ''' 101 s = data.encode('utf-8') 102 if s.endswith('\n'): 103 self.chunks.append(s[:-1]) 104 s = ''.join(self.chunks) 105 self.log.log(self.LEVEL, s) 106 self.chunks = [] 107 else: 108 self.chunks.append(s)
109
110 -def configure(log_conf=None, log_level=None, log_channels=None, log_file=None):
111 ''' 112 Configures the logging system based on the setting specified on the command 113 line or Python logging module compatible configuration file. Defaults to 114 logging messages at the INFO level or higher to stdout. Options in the 115 configuration file always override those given on the command line. 116 117 @param log_conf: Filename of a logging module configuration file. See 118 U{http://antonym.org/node/76} and 119 U{http://docs.python.org/lib/logging-config-fileformat.html}. 120 @type log_conf: string 121 @param log_level: Include messages at this level or higher 122 @type log_level: integer 123 @param log_channels: Include messages sent only on these channels, or None 124 meaning all 125 @type log_channels: list of string 126 @param log_file: Log messages in a basic, fixed format to this file. Provided 127 for convenience for users who do not want to write their own logging conf 128 file. 129 @type log_file: string 130 ''' 131 # if a configuration file is provided, use that 132 if log_conf is not None: 133 logging.config.fileConfig(log_conf) 134 else: 135 # otherwise, fall back on a basic config 136 if log_level is None: 137 # default to logging critical messages only 138 log_level = 'info' 139 if log_level == 'print': 140 # set the log level to print statements if specified 141 level = PrintLogger.LEVEL 142 else: 143 # get the logging constant from the logging module by name; it's an 144 # uppercase version of the log_level string provided on the command line 145 level = getattr(logging, log_level.upper()) 146 # get the root logger 147 root = logging.getLogger() 148 # log to a file or to stderr 149 if log_file: 150 handler = logging.FileHandler(log_file) 151 else: 152 handler = logging.StreamHandler(sys.stderr) 153 # set the format and handler for messages 154 formatter = logging.Formatter(LOG_FORMAT) 155 root.addHandler(handler) 156 root.setLevel(level) 157 handler.setFormatter(formatter) 158 # add filters to the root handler 159 if log_channels is not None: 160 for name in log_channels: 161 handler.addFilter(logging.Filter(name)) 162 # create a print log channel, redirect all print statements to the log 163 stdout = sys.stdout 164 sys.stdout = PrintLogger()
165