[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