Package cherrypy :: Module _cplogging
[hide private]
[frames] | no frames]

Source Code for Module cherrypy._cplogging

  1  """CherryPy logging.""" 
  2   
  3  import datetime 
  4  import logging 
  5  logfmt = logging.Formatter("%(message)s") 
  6  import os 
  7  import rfc822 
  8  import sys 
  9   
 10  import cherrypy 
 11  from cherrypy import _cperror 
 12   
 13   
14 -class LogManager(object):
15 16 appid = None 17 error_log = None 18 access_log = None 19
20 - def __init__(self, appid=None, logger_root="cherrypy"):
21 self.logger_root = logger_root 22 self.appid = appid 23 if appid is None: 24 self.error_log = logging.getLogger("%s.error" % logger_root) 25 self.access_log = logging.getLogger("%s.access" % logger_root) 26 else: 27 self.error_log = logging.getLogger("%s.error.%s" % (logger_root, appid)) 28 self.access_log = logging.getLogger("%s.access.%s" % (logger_root, appid)) 29 self.error_log.setLevel(logging.DEBUG) 30 self.access_log.setLevel(logging.INFO)
31
32 - def error(self, msg='', context='', severity=logging.DEBUG, traceback=False):
33 """Write to the error log. 34 35 This is not just for errors! Applications may call this at any time 36 to log application-specific information. 37 """ 38 if traceback: 39 msg += _cperror.format_exc() 40 self.error_log.log(severity, ' '.join((self.time(), context, msg)))
41
42 - def __call__(self, *args, **kwargs):
43 """Write to the error log. 44 45 This is not just for errors! Applications may call this at any time 46 to log application-specific information. 47 """ 48 return self.error(*args, **kwargs)
49
50 - def access(self):
51 """Write to the access log.""" 52 request = cherrypy.request 53 remote = request.remote 54 response = cherrypy.response 55 outheaders = response.headers 56 tmpl = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' 57 s = tmpl % {'h': remote.name or remote.ip, 58 'l': '-', 59 'u': getattr(request, "login", None) or "-", 60 't': self.time(), 61 'r': request.request_line, 62 's': response.status.split(" ", 1)[0], 63 'b': outheaders.get('Content-Length', '') or "-", 64 'f': outheaders.get('referer', ''), 65 'a': outheaders.get('user-agent', ''), 66 } 67 try: 68 self.access_log.log(logging.INFO, s) 69 except: 70 self(traceback=True)
71
72 - def time(self):
73 """Return now() in Apache Common Log Format (no timezone).""" 74 now = datetime.datetime.now() 75 month = rfc822._monthnames[now.month - 1].capitalize() 76 return ('[%02d/%s/%04d:%02d:%02d:%02d]' % 77 (now.day, month, now.year, now.hour, now.minute, now.second))
78
79 - def _get_builtin_handler(self, log, key):
80 for h in log.handlers: 81 if getattr(h, "_cpbuiltin", None) == key: 82 return h
83 84 85 # ------------------------- Screen handlers ------------------------- # 86
87 - def _set_screen_handler(self, log, enable):
88 h = self._get_builtin_handler(log, "screen") 89 if enable: 90 if not h: 91 h = logging.StreamHandler(sys.stdout) 92 h.setLevel(logging.DEBUG) 93 h.setFormatter(logfmt) 94 h._cpbuiltin = "screen" 95 log.addHandler(h) 96 elif h: 97 log.handlers.remove(h)
98
99 - def _get_screen(self):
100 h = self._get_builtin_handler 101 has_h = h(self.error_log, "screen") or h(self.access_log, "screen") 102 return bool(has_h)
103
104 - def _set_screen(self, newvalue):
105 self._set_screen_handler(self.error_log, newvalue) 106 self._set_screen_handler(self.access_log, newvalue)
107 screen = property(_get_screen, _set_screen, 108 doc="If True, error and access will print to stdout.") 109 110 111 # -------------------------- File handlers -------------------------- # 112
113 - def _add_builtin_file_handler(self, log, fname):
114 h = logging.FileHandler(fname) 115 h.setLevel(logging.DEBUG) 116 h.setFormatter(logfmt) 117 h._cpbuiltin = "file" 118 log.addHandler(h)
119
120 - def _set_file_handler(self, log, filename):
121 h = self._get_builtin_handler(log, "file") 122 if filename: 123 if h: 124 if h.baseFilename != os.path.abspath(filename): 125 h.close() 126 log.handlers.remove(h) 127 self._add_builtin_file_handler(log, filename) 128 else: 129 self._add_builtin_file_handler(log, filename) 130 else: 131 if h: 132 h.close() 133 log.handlers.remove(h)
134
135 - def _get_error_file(self):
136 h = self._get_builtin_handler(self.error_log, "file") 137 if h: 138 return h.baseFilename 139 return ''
140 - def _set_error_file(self, newvalue):
141 self._set_file_handler(self.error_log, newvalue)
142 error_file = property(_get_error_file, _set_error_file, 143 doc="The filename for self.error_log.") 144
145 - def _get_access_file(self):
146 h = self._get_builtin_handler(self.access_log, "file") 147 if h: 148 return h.baseFilename 149 return ''
150 - def _set_access_file(self, newvalue):
151 self._set_file_handler(self.access_log, newvalue)
152 access_file = property(_get_access_file, _set_access_file, 153 doc="The filename for self.access_log.") 154 155 156 # ------------------------- WSGI handlers ------------------------- # 157
158 - def _set_wsgi_handler(self, log, enable):
159 h = self._get_builtin_handler(log, "wsgi") 160 if enable: 161 if not h: 162 h = WSGIErrorHandler() 163 h.setLevel(logging.DEBUG) 164 h.setFormatter(logfmt) 165 h._cpbuiltin = "wsgi" 166 log.addHandler(h) 167 elif h: 168 log.handlers.remove(h)
169
170 - def _get_wsgi(self):
171 return bool(self._get_builtin_handler(self.error_log, "wsgi"))
172
173 - def _set_wsgi(self, newvalue):
174 self._set_wsgi_handler(self.error_log, newvalue)
175 wsgi = property(_get_wsgi, _set_wsgi, 176 doc="If True, error messages will be sent to wsgi.errors.")
177 178
179 -class WSGIErrorHandler(logging.Handler):
180 "A handler class which writes logging records to environ['wsgi.errors']." 181
182 - def flush(self):
183 """Flushes the stream.""" 184 try: 185 stream = cherrypy.request.wsgi_environ.get('wsgi.errors') 186 except AttributeError, KeyError: 187 pass 188 else: 189 stream.flush()
190
191 - def emit(self, record):
192 """Emit a record.""" 193 try: 194 stream = cherrypy.request.wsgi_environ.get('wsgi.errors') 195 except AttributeError, KeyError: 196 pass 197 else: 198 try: 199 msg = self.format(record) 200 fs = "%s\n" 201 import types 202 if not hasattr(types, "UnicodeType"): #if no unicode support... 203 stream.write(fs % msg) 204 else: 205 try: 206 stream.write(fs % msg) 207 except UnicodeError: 208 stream.write(fs % msg.encode("UTF-8")) 209 self.flush() 210 except: 211 self.handleError(record)
212