Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/branches/cherrypy-3.0.x/cherrypy/_cplogging.py

Revision 1981 (checked in by fumanchu, 3 months ago)

Backport of [1717]. See #727.

  • Property svn:eol-style set to native
Line 
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         inheaders = request.headers
54         remote = request.remote
55         response = cherrypy.response
56         outheaders = response.headers
57         tmpl = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
58         s = tmpl % {'h': remote.name or remote.ip,
59                     'l': '-',
60                     'u': getattr(request, "login", None) or "-",
61                     't': self.time(),
62                     'r': request.request_line,
63                     's': response.status.split(" ", 1)[0],
64                     'b': outheaders.get('Content-Length', '') or "-",
65                     'f': inheaders.get('Referer', ''),
66                     'a': inheaders.get('User-Agent', ''),
67                     }
68         try:
69             self.access_log.log(logging.INFO, s)
70         except:
71             self(traceback=True)
72    
73     def time(self):
74         """Return now() in Apache Common Log Format (no timezone)."""
75         now = datetime.datetime.now()
76         month = rfc822._monthnames[now.month - 1].capitalize()
77         return ('[%02d/%s/%04d:%02d:%02d:%02d]' %
78                 (now.day, month, now.year, now.hour, now.minute, now.second))
79    
80     def _get_builtin_handler(self, log, key):
81         for h in log.handlers:
82             if getattr(h, "_cpbuiltin", None) == key:
83                 return h
84    
85    
86     # ------------------------- Screen handlers ------------------------- #
87    
88     def _set_screen_handler(self, log, enable):
89         h = self._get_builtin_handler(log, "screen")
90         if enable:
91             if not h:
92                 h = logging.StreamHandler(sys.stdout)
93                 h.setLevel(logging.DEBUG)
94                 h.setFormatter(logfmt)
95                 h._cpbuiltin = "screen"
96                 log.addHandler(h)
97         elif h:
98             log.handlers.remove(h)
99    
100     def _get_screen(self):
101         h = self._get_builtin_handler
102         has_h = h(self.error_log, "screen") or h(self.access_log, "screen")
103         return bool(has_h)
104    
105     def _set_screen(self, newvalue):
106         self._set_screen_handler(self.error_log, newvalue)
107         self._set_screen_handler(self.access_log, newvalue)
108     screen = property(_get_screen, _set_screen,
109                       doc="If True, error and access will print to stdout.")
110    
111    
112     # -------------------------- File handlers -------------------------- #
113    
114     def _add_builtin_file_handler(self, log, fname):
115         h = logging.FileHandler(fname)
116         h.setLevel(logging.DEBUG)
117         h.setFormatter(logfmt)
118         h._cpbuiltin = "file"
119         log.addHandler(h)
120    
121     def _set_file_handler(self, log, filename):
122         h = self._get_builtin_handler(log, "file")
123         if filename:
124             if h:
125                 if h.baseFilename != os.path.abspath(filename):
126                     h.close()
127                     log.handlers.remove(h)
128                     self._add_builtin_file_handler(log, filename)
129             else:
130                 self._add_builtin_file_handler(log, filename)
131         else:
132             if h:
133                 h.close()
134                 log.handlers.remove(h)
135    
136     def _get_error_file(self):
137         h = self._get_builtin_handler(self.error_log, "file")
138         if h:
139             return h.baseFilename
140         return ''
141     def _set_error_file(self, newvalue):
142         self._set_file_handler(self.error_log, newvalue)
143     error_file = property(_get_error_file, _set_error_file,
144                           doc="The filename for self.error_log.")
145    
146     def _get_access_file(self):
147         h = self._get_builtin_handler(self.access_log, "file")
148         if h:
149             return h.baseFilename
150         return ''
151     def _set_access_file(self, newvalue):
152         self._set_file_handler(self.access_log, newvalue)
153     access_file = property(_get_access_file, _set_access_file,
154                            doc="The filename for self.access_log.")
155    
156    
157     # ------------------------- WSGI handlers ------------------------- #
158    
159     def _set_wsgi_handler(self, log, enable):
160         h = self._get_builtin_handler(log, "wsgi")
161         if enable:
162             if not h:
163                 h = WSGIErrorHandler()
164                 h.setLevel(logging.DEBUG)
165                 h.setFormatter(logfmt)
166                 h._cpbuiltin = "wsgi"
167                 log.addHandler(h)
168         elif h:
169             log.handlers.remove(h)
170    
171     def _get_wsgi(self):
172         return bool(self._get_builtin_handler(self.error_log, "wsgi"))
173    
174     def _set_wsgi(self, newvalue):
175         self._set_wsgi_handler(self.error_log, newvalue)
176     wsgi = property(_get_wsgi, _set_wsgi,
177                       doc="If True, error messages will be sent to wsgi.errors.")
178
179
180 class WSGIErrorHandler(logging.Handler):
181     "A handler class which writes logging records to environ['wsgi.errors']."
182    
183     def flush(self):
184         """Flushes the stream."""
185         try:
186             stream = cherrypy.request.wsgi_environ.get('wsgi.errors')
187         except AttributeError, KeyError:
188             pass
189         else:
190             stream.flush()
191    
192     def emit(self, record):
193         """Emit a record."""
194         try:
195             stream = cherrypy.request.wsgi_environ.get('wsgi.errors')
196         except AttributeError, KeyError:
197             pass
198         else:
199             try:
200                 msg = self.format(record)
201                 fs = "%s\n"
202                 import types
203                 if not hasattr(types, "UnicodeType"): #if no unicode support...
204                     stream.write(fs % msg)
205                 else:
206                     try:
207                         stream.write(fs % msg)
208                     except UnicodeError:
209                         stream.write(fs % msg.encode("UTF-8"))
210                 self.flush()
211             except:
212                 self.handleError(record)
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets