"""Logging related functionality
This logging Handler logs to ``environ['wsgi.errors']`` as designated
in :pep:`333`.
"""
import logging
import types
import pylons
__all__ = ['WSGIErrorsHandler']
class WSGIErrorsHandler(logging.Handler):
"""A handler class that writes logging records to
`environ['wsgi.errors']`.
This code is derived from CherryPy's
:class:`cherrypy._cplogging.WSGIErrorHandler`.
``cache``
Whether the `wsgi.errors` stream is cached (instead of looked up
via `pylons.request.environ` per every logged message). Enabling
this option is not recommended (particularly for the use case of
logging to `wsgi.errors` outside of a request) as the behavior
of a cached `wsgi.errors` stream is not strictly defined. In
particular, `mod_wsgi `_'s `wsgi.errors`
will raise an exception when used outside of a request.
"""
def __init__(self, cache=False, *args, **kwargs):
logging.Handler.__init__(self, *args, **kwargs)
self.cache = cache
self.cached_stream = None
def get_wsgierrors(self):
"""Return the wsgi.errors stream
Raises a TypeError when outside of a web request
(pylons.request is not setup)
"""
if not self.cache:
return pylons.request.environ.get('wsgi.errors')
elif not self.cached_stream:
self.cached_stream = pylons.request.environ.get('wsgi.errors')
return self.cached_stream
return self.cached_stream
def flush(self):
"""Flushes the stream"""
try:
stream = self.get_wsgierrors()
except TypeError:
pass
else:
if stream:
stream.flush()
def emit(self, record):
"""Emit a record"""
try:
stream = self.get_wsgierrors()
except TypeError:
pass
else:
if not stream:
return
try:
msg = self.format(record)
fs = "%s\n"
if not hasattr(types, "UnicodeType"): #if no unicode support...
stream.write(fs % msg)
else:
try:
stream.write(fs % msg)
except UnicodeError:
stream.write(fs % msg.encode("UTF-8"))
self.flush()
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)