| Home | Trees | Indices | Help |
|
|---|
|
|
1 """CherryPy logging."""
2
3 import datetime
4 import logging
5 # Silence the no-handlers "warning" (stderr write!) in stdlib logging
6 logging.Logger.manager.emittedNoHandlerWarning = 1
7 logfmt = logging.Formatter("%(message)s")
8 import os
9 import rfc822
10 import sys
11
12 import cherrypy
13 from cherrypy import _cperror
14
15
17
18 appid = None
19 error_log = None
20 access_log = None
21 access_log_format = \
22 '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
23
25 self.logger_root = logger_root
26 self.appid = appid
27 if appid is None:
28 self.error_log = logging.getLogger("%s.error" % logger_root)
29 self.access_log = logging.getLogger("%s.access" % logger_root)
30 else:
31 self.error_log = logging.getLogger("%s.error.%s" % (logger_root, appid))
32 self.access_log = logging.getLogger("%s.access.%s" % (logger_root, appid))
33 self.error_log.setLevel(logging.DEBUG)
34 self.access_log.setLevel(logging.INFO)
35 cherrypy.engine.subscribe('graceful', self.reopen_files)
36
38 """Close and reopen all file handlers."""
39 for log in (self.error_log, self.access_log):
40 for h in log.handlers:
41 if isinstance(h, logging.FileHandler):
42 h.acquire()
43 h.stream.close()
44 h.stream = open(h.baseFilename, h.mode)
45 h.release()
46
48 """Write to the error log.
49
50 This is not just for errors! Applications may call this at any time
51 to log application-specific information.
52 """
53 if traceback:
54 msg += _cperror.format_exc()
55 self.error_log.log(severity, ' '.join((self.time(), context, msg)))
56
58 """Write to the error log.
59
60 This is not just for errors! Applications may call this at any time
61 to log application-specific information.
62 """
63 return self.error(*args, **kwargs)
64
66 """Write to the access log (in Apache/NCSA Combined Log format).
67
68 Like Apache started doing in 2.0.46, non-printable and other special
69 characters in %r (and we expand that to all parts) are escaped using
70 \\xhh sequences, where hh stands for the hexadecimal representation
71 of the raw byte. Exceptions from this rule are " and \\, which are
72 escaped by prepending a backslash, and all whitespace characters,
73 which are written in their C-style notation (\\n, \\t, etc).
74 """
75 request = cherrypy.request
76 remote = request.remote
77 response = cherrypy.response
78 outheaders = response.headers
79 inheaders = request.headers
80
81 atoms = {'h': remote.name or remote.ip,
82 'l': '-',
83 'u': getattr(request, "login", None) or "-",
84 't': self.time(),
85 'r': request.request_line,
86 's': response.status.split(" ", 1)[0],
87 'b': outheaders.get('Content-Length', '') or "-",
88 'f': inheaders.get('Referer', ''),
89 'a': inheaders.get('User-Agent', ''),
90 }
91 for k, v in atoms.items():
92 if isinstance(v, unicode):
93 v = v.encode('utf8')
94 elif not isinstance(v, str):
95 v = str(v)
96 # Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
97 # and backslash for us. All we have to do is strip the quotes.
98 v = repr(v)[1:-1]
99 # Escape double-quote.
100 atoms[k] = v.replace('"', '\\"')
101
102 try:
103 self.access_log.log(logging.INFO, self.access_log_format % atoms)
104 except:
105 self(traceback=True)
106
108 """Return now() in Apache Common Log Format (no timezone)."""
109 now = datetime.datetime.now()
110 month = rfc822._monthnames[now.month - 1].capitalize()
111 return ('[%02d/%s/%04d:%02d:%02d:%02d]' %
112 (now.day, month, now.year, now.hour, now.minute, now.second))
113
118
119
120 # ------------------------- Screen handlers ------------------------- #
121
123 h = self._get_builtin_handler(log, "screen")
124 if enable:
125 if not h:
126 if stream is None:
127 stream=sys.stderr
128 h = logging.StreamHandler(stream)
129 h.setFormatter(logfmt)
130 h._cpbuiltin = "screen"
131 log.addHandler(h)
132 elif h:
133 log.handlers.remove(h)
134
136 h = self._get_builtin_handler
137 has_h = h(self.error_log, "screen") or h(self.access_log, "screen")
138 return bool(has_h)
139
141 self._set_screen_handler(self.error_log, newvalue, stream=sys.stderr)
142 self._set_screen_handler(self.access_log, newvalue)
143 screen = property(_get_screen, _set_screen,
144 doc="If True, error and access will print to stderr.")
145
146
147 # -------------------------- File handlers -------------------------- #
148
150 h = logging.FileHandler(fname)
151 h.setFormatter(logfmt)
152 h._cpbuiltin = "file"
153 log.addHandler(h)
154
156 h = self._get_builtin_handler(log, "file")
157 if filename:
158 if h:
159 if h.baseFilename != os.path.abspath(filename):
160 h.close()
161 log.handlers.remove(h)
162 self._add_builtin_file_handler(log, filename)
163 else:
164 self._add_builtin_file_handler(log, filename)
165 else:
166 if h:
167 h.close()
168 log.handlers.remove(h)
169
171 h = self._get_builtin_handler(self.error_log, "file")
172 if h:
173 return h.baseFilename
174 return ''
177 error_file = property(_get_error_file, _set_error_file,
178 doc="The filename for self.error_log.")
179
181 h = self._get_builtin_handler(self.access_log, "file")
182 if h:
183 return h.baseFilename
184 return ''
187 access_file = property(_get_access_file, _set_access_file,
188 doc="The filename for self.access_log.")
189
190
191 # ------------------------- WSGI handlers ------------------------- #
192
194 h = self._get_builtin_handler(log, "wsgi")
195 if enable:
196 if not h:
197 h = WSGIErrorHandler()
198 h.setFormatter(logfmt)
199 h._cpbuiltin = "wsgi"
200 log.addHandler(h)
201 elif h:
202 log.handlers.remove(h)
203
206
209 wsgi = property(_get_wsgi, _set_wsgi,
210 doc="If True, error messages will be sent to wsgi.errors.")
211
212
214 "A handler class which writes logging records to environ['wsgi.errors']."
215
217 """Flushes the stream."""
218 try:
219 stream = cherrypy.request.wsgi_environ.get('wsgi.errors')
220 except (AttributeError, KeyError):
221 pass
222 else:
223 stream.flush()
224
226 """Emit a record."""
227 try:
228 stream = cherrypy.request.wsgi_environ.get('wsgi.errors')
229 except (AttributeError, KeyError):
230 pass
231 else:
232 try:
233 msg = self.format(record)
234 fs = "%s\n"
235 import types
236 if not hasattr(types, "UnicodeType"): #if no unicode support...
237 stream.write(fs % msg)
238 else:
239 try:
240 stream.write(fs % msg)
241 except UnicodeError:
242 stream.write(fs % msg.encode("UTF-8"))
243 self.flush()
244 except:
245 self.handleError(record)
246
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Sat Aug 15 15:33:07 2009 | http://epydoc.sourceforge.net |