source file: /Library/Python/2.3/site-packages/CherryPy-3.0.1-py2.3.egg/cherrypy/_cplogging.py
file stats: 146 lines, 92 executed: 63.0% covered
   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)