Task: When an error occurs in one of my views I need to show a custom error view. The error type does not matter.
I tried to override all exceptions by registring a view for all exceptions, like this:
<view
context="Exception"
renderer="server_error.pt"
/>
It worked good. All exceptions were showing my view. But the problem was that those errors stopped logging. Of cource I can do something like logger.error(traceback) in my error view, but this is a dumb idea.
How can I register a view for all errors without breaking the logging pyramid system.
You can log the error in your view via the plain old python logging. Or Set the status on the response to 500 (assuming your view is now return a status of 200 which indicates a successful response ).
Edit: working example
I'm not a logging expert, but I was under the impression that your logging config in development.ini/production.ini would be picked up, the example below seems to prove that but you be the judge.....
changes to log config from default
[formatter_generic]
# format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = y u no work??!!?? %(message)s
# End logging configuration
the views
from pyramid.view import view_config
from webob import Response
import logging
log = logging.getLogger(__name__)
@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
raise ValueError("oops")
return {'project':'tstLogError'}
@view_config(context=Exception)
def exception_view(context, request):
log.error("The error was: %s" % context, exc_info=(context))
return Response(status_int=500, body=str(context))
from pyramid.view import view_config
from webob import Response
console output:
serving on http://0.0.0.0:6543
y u no work??!!?? The error was: oops
Traceback (most recent call last):
File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/tweens.py", line 20, in excview_tween
response = handler(request)
File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/router.py", line 164, in handle_request
response = view_callable(context, request)
File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/config/views.py", line 333, in rendered_view
result = view(context, request)
File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/config/views.py", line 471, in _requestonly_view
response = view(request)
File "/home/twillis/projects/TestLogError/tstLogError/tstlogerror/views.py", line 8, in my_view
raise ValueError("oops")
ValueError: oops
It is not dumb to log the exception in your own error view (the exception will be available as request.context
.) As is always the case with exceptions, you can either do nothing, handle the exception and log it, or re-raise the same exception.
In my setup, an uncaught exception is logged by the WSGI server itself, in this case wsgiref. It's not possible to trigger both the WSGI server's normal response mechanism and its exception logger.
wsgiref's exception logger:
def log_exception(self,exc_info):
"""Log the 'exc_info' tuple in the server log
Subclasses may override to retarget the output or change its format.
"""
try:
from traceback import print_exception
stderr = self.get_stderr()
print_exception(
exc_info[0], exc_info[1], exc_info[2],
self.traceback_limit, stderr
)
stderr.flush()
finally:
exc_info = None
One alternative that may be acceptable to you is to display your custom error page at the web server layer instead of at the Pyramid layer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With