Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 4 and Version 5 of ErrorReporting


Ignore:
Timestamp:
06/24/07 18:32:35 (12 years ago)
Author:
Chris Arndt
Comment:

migration notice

Legend:

Unmodified
Added
Removed
Modified
  • ErrorReporting

    v4 v5  
    1 == Custom Error Reporting == 
    2  
    3 We're not perfect. Sometimes we don't catch every exception, even after piles of testing. This is why it's a good idea to be told if disaster strikes and one of your pages bombs out. This is a good idea during so-called "beta testing" (otherwise known as "releasing unfinished product") as you can't always rely on your users informing you of such problems. 
    4  
    5 Here's a brief rundown on how I did it. I won't go in to how to send an E-mail as that's covered better elsewhere, such as Python's documentation. 
    6  
    71{{{ 
    8 # Your controller: 
    9  
    10     @turbogears.errorhandling.dispatch_error.when("tg_exceptions is not None") 
    11     def unhandled_exception(self, tg_source, tg_errors, tg_exception): 
    12         try: 
    13                 # Spam me here, whatever 
    14                 programmer_notified = True 
    15                 pass 
    16         except: 
    17                 programmer_notified = False 
    18         return dict(tg_template=".templates.unhandled_exception", title="500 Internal error", programmer_notified=programmer_notified) 
     2#!rst 
     3.. note:: This page has been migrated to http://docs.turbogears.org/1.0/ErrorReporting. 
    194}}} 
    20  
    21 {{{ 
    22 # And an example template (unhandled_exception.kid in mine) 
    23  
    24 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    25 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://purl.org/kid/ns#" 
    26     py:extends="'master.kid'"> 
    27  
    28 <head> 
    29     <title py:content="title">Title</title> 
    30 </head> 
    31  
    32 <body> 
    33     <h1>Oops! An error occured</h1> 
    34     <p>Something went wonky and we weren't expecting it. Sorry about that. This is commonly known as an &quot;Error 500&quot; or &quot;Internal Server Error&quot;. It means we messed up.</p> 
    35     <p py:if="programmer_notified">A programmer has been notified and will try to fix the problem as soon as possible.</p> 
    36     <p py:if="not programmer_notified">The problem was actually so bad that we couldn't even send an E-mail to our team to sort the problem out! If you keep getting this message, please send us an E-mail with some information about what you were doing when this happened, so we can try and smooth things over :-)</p> 
    37     <p>Our sincerest apologies,</p> 
    38     <p style="font-style: italic">-The Team</p> <!--! No <em> because this is just convention !--> 
    39 </body> 
    40 </html> 
    41 }}} 
    42  
    43 Of course, you don't really wanna be hiding your exceptions while you're developing, so I recommend commenting out the @turbogears.errorhandling.dispatch_error decorator until people are going to start visiting the site while you're not sitting over the server output. 
    44  
    45 Bear in mind that this method supresses exception output in the log so there is a chance that the exception could be lost forever. 
    46  
    47 == Custom Error Reporting - Method 2 (Application Wide Catch All) == 
    48  
    49 Personally I found the following worked much better if you have multiple controllers. You hook the code into your Root controller, and your done. This however makes use of CherryPy instead of TurboGears specifics. Readers should also check out the HowDoesErrorHandlingWork page for info on the exception_handler to do custom handling for each method. 
    50  
    51 The following code has pretty much everything you need to provide a custom error page, and send an email to someone with the error. You will need to change the email settings though, but other then that should be good to go. (Tested in TG 0.9a6) 
    52  
    53 {{{ 
    54 class Root(controllers.RootController): 
    55         @turbogears.expose() 
    56         @identity.require(identity.in_group("user")) 
    57         def index(self): 
    58                 return self.main() 
    59  
    60         def cp_on_http_error(self, status, message): 
    61                 from cherrypy import _cputil 
    62                 _cputil._cp_on_http_error(status, message) 
    63  
    64                 # Go to a specific 404 page (don't want a lot of spam about people typing in wrong URLs) 
    65                 if status == 404: 
    66                         url = "%s %s" % (cherrypy.request.method, cherrypy.request.path) 
    67                         output = dict( 
    68                                 status = status, 
    69                                 message = message or '-', 
    70                                 theError = '404 - Page Not Found', 
    71                                 admin = 'admin' in identity.current.identity().groups, 
    72                                 url = url) 
    73  
    74                         template = ".templates.404_exception" 
    75                         format = 'html' 
    76                         content_type = 'text/html' 
    77                         mapping = None 
    78  
    79                         # Probably don't want to send an email, but it is here if you do 
    80                         #self.send_exception_to_developer(status, url, '404 error') 
    81  
    82                         # Return customized page 
    83                         body = controllers._process_output(output, template, format, content_type, mapping) 
    84                         cherrypy.response.headers['Content-Length'] = len(body) 
    85                         cherrypy.response.body = body 
    86                         return 
    87  
    88                 import logging 
    89                 log = logging.getLogger("turbogears.controllers") 
    90                 log.exception('CherryPy %s error (%s)', status, message) 
    91  
    92                 import traceback, StringIO 
    93                 buf = StringIO.StringIO() 
    94                 traceback.print_exc(file=buf) 
    95                 url = "%s %s" % (cherrypy.request.method, cherrypy.request.path) 
    96  
    97                 self.send_exception_to_developer(status, url, buf.getvalue()) 
    98  
    99                 theError = { 
    100                         400: u'400 - Bad Request', 
    101                         401: u'401 - Unauthorized', 
    102                         403: u'403 - Forbidden', 
    103                         404: u'404 - Not Found', 
    104                         500: u'500 - Internal Server Error', 
    105                         501: u'501 - Not Implemented', 
    106                         502: u'502 - Bad Gateway', 
    107                 }.get(status, message or u'General Error')  
    108  
    109                 output = dict( 
    110                         status = status, 
    111                         message = message or '-', 
    112                         theError = theError, 
    113                         admin = 'admin' in identity.current.identity().groups, 
    114                         url = url, 
    115                         details = buf.getvalue()) 
    116  
    117                 template = ".templates.unhandled_exception" 
    118                 format = 'html' 
    119                 content_type = 'text/html' 
    120                 mapping = None 
    121  
    122                 # Return customized page 
    123                 body = controllers._process_output(output, template, format, content_type, mapping) 
    124                 cherrypy.response.headers['Content-Length'] = len(body) 
    125                 cherrypy.response.body = body  
    126  
    127         # Hook in error stuff for production only 
    128         if turbogears.config.get('server.environment') == 'production': 
    129                 _cp_on_http_error = cp_on_http_error 
    130  
    131         def send_exception_to_developer(self, status, url, data): 
    132                 import smtplib 
    133                 from email.MIMEMultipart import MIMEMultipart 
    134                 from email.MIMEBase import MIMEBase 
    135                 from email.MIMEText import MIMEText 
    136                 from email.Utils import formatdate 
    137  
    138                 fromAddy = "Server <server@mydomain.com>" 
    139                 to = "servererrors@server@mydomain.com" 
    140  
    141                 msg = MIMEMultipart() 
    142                 msg['From'] = fromAddy 
    143                 msg['To'] = to 
    144                 msg['Date'] = formatdate(localtime=True) 
    145                 msg['Subject'] = '%d ERROR on the Server' % status 
    146  
    147                 text = "----------URL----------\n%s\n----------DATA:----------\n%s" % (url, data) 
    148  
    149                 msg.attach(MIMEText(text)) 
    150  
    151                 smtp = smtplib.SMTP("mailserver.net") 
    152                 smtp.login('username', 'password') 
    153                 smtp.sendmail(fromAddy, to, msg.as_string()) 
    154                 smtp.close() 
    155 }}} 
    156  
    157 For the lazy out there who wanted to know how to handle an exception on each mehod but didn't follow the above link, here is the code you want: 
    158  
    159 {{{ 
    160 class Root(controllers.RootController): 
    161     @turbogears.expose() 
    162     def error(self): 
    163         return "An error ocured" 
    164  
    165     @turbogears.expose() 
    166     @turbogears.controllers.exception_handler(error, "ValueError") 
    167     def index(self): 
    168         raise ValueError 
    169 }}} 
    170  
    171 References: 
    172 http://groups.google.com/group/turbogears/browse_frm/thread/61a48b1f7fdfe354/de325500f437f632?lnk=gst&q=custom+500&rnum=1#de325500f437f632 
    173 http://groups.google.com/group/turbogears/browse_thread/thread/ba80c6d7ecc4a349/5522ae1cfceab877?lnk=gst&q=_cp_on_error&rnum=3#5522ae1cfceab877 
    174 http://groups.google.com/group/turbogears/browse_thread/thread/e7c103acb7b786ab/263115b72e9dfcd4?lnk=gst&q=exception_handler&rnum=5#263115b72e9dfcd4