[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/ Improved system
error handling
Jim Fulton
jim at zope.com
Thu Oct 28 18:56:34 EDT 2004
Log message for revision 28280:
Improved system error handling
Added a tiny framework to allow the publication object to detect
system errors. Renamed the default (system error) view to
systemerror.pt and updated it to let the publication know that it
handles system errors. Updated the publication to log system errors.
The end result of this (and the previous revision) is that, by
default, we *only* log system errors and publication failures to the
site error log, so that these errors get the attention they deserve
without being hidden by user errors.
Changed:
U Zope3/trunk/src/zope/app/exception/browser/configure.zcml
D Zope3/trunk/src/zope/app/exception/browser/default.pt
A Zope3/trunk/src/zope/app/exception/browser/systemerror.pt
U Zope3/trunk/src/zope/app/exception/interfaces.py
A Zope3/trunk/src/zope/app/exception/systemerror.py
U Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py
U Zope3/trunk/src/zope/app/publication/zopepublication.py
-=-
Modified: Zope3/trunk/src/zope/app/exception/browser/configure.zcml
===================================================================
--- Zope3/trunk/src/zope/app/exception/browser/configure.zcml 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/exception/browser/configure.zcml 2004-10-28 22:56:34 UTC (rev 28280)
@@ -5,7 +5,8 @@
<page
for="zope.interface.common.interfaces.IException"
name="index.html"
- template="default.pt"
+ template="systemerror.pt"
+ class="..systemerror.SystemErrorView"
permission="zope.Public"
/>
Deleted: Zope3/trunk/src/zope/app/exception/browser/default.pt
===================================================================
--- Zope3/trunk/src/zope/app/exception/browser/default.pt 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/exception/browser/default.pt 2004-10-28 22:56:34 UTC (rev 28280)
@@ -1,5 +0,0 @@
-<html><title>System Error</title>
-<body tal:define="ignored python:request.response.setStatus(500)">
- A system error occurred.
-</body>
-</html>
Copied: Zope3/trunk/src/zope/app/exception/browser/systemerror.pt (from rev 28274, Zope3/trunk/src/zope/app/exception/browser/default.pt)
Modified: Zope3/trunk/src/zope/app/exception/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/app/exception/interfaces.py 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/exception/interfaces.py 2004-10-28 22:56:34 UTC (rev 28280)
@@ -28,3 +28,12 @@
they are handled.
"""
implements(IUserError)
+
+class ISystemErrorView(Interface):
+ """Error views that can classify their contexts as system errors
+ """
+
+ def isSystemError():
+ """Return a boolean indicating whether the error is a system errror
+ """
+
Added: Zope3/trunk/src/zope/app/exception/systemerror.py
===================================================================
--- Zope3/trunk/src/zope/app/exception/systemerror.py 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/exception/systemerror.py 2004-10-28 22:56:34 UTC (rev 28280)
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""System error indicator
+
+$Id$
+"""
+
+import zope.interface
+import zope.app.exception.interfaces
+
+class SystemErrorView:
+ zope.interface.implements(zope.app.exception.interfaces.ISystemErrorView)
+
+ def isSystemError(self):
+ return True
+
Property changes on: Zope3/trunk/src/zope/app/exception/systemerror.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Modified: Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py 2004-10-28 22:56:34 UTC (rev 28280)
@@ -108,6 +108,9 @@
def foo(self):
pass
+class TestRequest(TestRequest):
+ URL='http://test.url'
+
class BasePublicationTests(PlacelessSetup, unittest.TestCase):
def setUp(self):
@@ -188,18 +191,17 @@
' ConflictError: database conflict error')
def testViewOnException(self):
- from ZODB.POSException import ConflictError
from zope.interface import Interface
- class IConflictError(Interface):
+ class E1(Exception):
pass
- classImplements(ConflictError, IConflictError)
- ztapi.setDefaultViewName(IConflictError, 'name',
+
+ ztapi.setDefaultViewName(E1, 'name',
type=self.presentation_type)
view_text = 'You had a conflict error'
- ztapi.provideView(IConflictError, self.presentation_type, Interface,
+ ztapi.provideView(E1, self.presentation_type, Interface,
'name', lambda obj, request: lambda: view_text)
try:
- raise ConflictError
+ raise E1
except:
pass
self.publication.handleException(
@@ -207,6 +209,74 @@
self.request.response.outputBody()
self.assertEqual(self.out.getvalue(), view_text)
+ def testHandlingSystemErrors(self):
+
+ # Generally, when there is a view for an excepton, we assume
+ # it is a user error, not a system error and we don't log it.
+
+ from zope.testing import loggingsupport
+ handler = loggingsupport.InstalledHandler('SiteError')
+
+ self.testViewOnException()
+
+ self.assertEqual(
+ str(handler),
+ 'SiteError ERROR\n'
+ ' Error while reporting an error to the ErrorLogging service')
+
+ # Here we got a single log record, because we havdn't
+ # installed an error reporting service. That's OK.
+
+ handler.uninstall()
+ self.out.seek(0)
+ self.out.truncate(0)
+ handler = loggingsupport.InstalledHandler('SiteError')
+
+ # Now, we'll register an exception view that indicates that we
+ # have a system error.
+
+ from zope.interface import Interface, implements
+ class E2(Exception):
+ pass
+
+ ztapi.setDefaultViewName(E2, 'name',
+ type=self.presentation_type)
+ view_text = 'You had a conflict error'
+
+ from zope.app.exception.interfaces import ISystemErrorView
+ class MyView:
+ implements(ISystemErrorView)
+ def __init__(self, context, request):
+ pass
+
+ def isSystemError(self):
+ return True
+
+ def __call__(self):
+ return view_text
+
+ ztapi.provideView(E2, self.presentation_type, Interface,
+ 'name', MyView)
+ try:
+ raise E2
+ except:
+ self.publication.handleException(
+ self.object, self.request, sys.exc_info(), retry_allowed=False)
+ self.request.response.outputBody()
+
+ # Now, since the view was a system error view, we should have
+ # a log entry for the E2 error (as well as the missing
+ # error reporting service).
+ self.assertEqual(
+ str(handler),
+ 'SiteError ERROR\n'
+ ' Error while reporting an error to the ErrorLogging service\n'
+ 'SiteError ERROR\n'
+ ' http://test.url'
+ )
+
+ handler.uninstall()
+
def testNoViewOnClassicClassException(self):
from zope.interface import Interface
from types import ClassType
Modified: Zope3/trunk/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-10-28 22:56:32 UTC (rev 28279)
+++ Zope3/trunk/src/zope/app/publication/zopepublication.py 2004-10-28 22:56:34 UTC (rev 28280)
@@ -42,6 +42,7 @@
import applicationControllerRoot
from zope.app.component.hooks import getSite
from zope.app.errorservice import RootErrorReportingService
+from zope.app.exception.interfaces import ISystemErrorView
from zope.app.location import LocationProxy
from zope.app.publication.interfaces import BeforeTraverseEvent
from zope.app.publication.interfaces import EndRequestEvent
@@ -308,10 +309,24 @@
tryToLogException(
'Exception while getting view on exception')
+
if view is not None:
try:
response.setBody(self.callObject(request, view))
get_transaction().commit()
+ if (ISystemErrorView.providedBy(view)
+ and view.isSystemError()):
+ # Got a system error, want to log the error
+
+ # Lame hack to get around logging missfeature
+ # that is fixed in Python 2.4
+ try:
+ raise exc_info[0], exc_info[1], exc_info[2]
+ except:
+ logging.getLogger('SiteError').exception(
+ str(request.URL),
+ )
+
except:
# Problem rendering the view for this exception.
# Log an error.
More information about the Zope3-Checkins
mailing list