Raymond Camden's Blog Rss

Simple Error Templates

10

Posted in ColdFusion | Posted on 12-04-2006 | 2,079 views

A few days ago I promised I'd blog about the error templates I use. Obviously part of the template is set up to show the site's look and feel and present a generic "We are so sorry, blah blah blah" type message. Outside of that though here is typically what I do with the error itself.

view plain print about
1<cfmail to="me" from="me" subject="SiteX Error" type="html">
2<cfdump var="#exception#" label="Exception">
3<cfdump var="#cgi#" label="cgi">
4<cfdump var="#form#" label="form">
5<cfdump var="#url#" label="url">
6</cfmail>

As you can see - I just take a massive dump in the email. Typically this is all I need. Sometimes though I need the session info so I just add a dump of that. I also bring up information on top of the dumps when I think it will be helpful. So for example, on RIAForge, I have both a main site and any number of project sites. To help me see a bit quicker, I can add this on top:

view plain print about
1Site: #cgi.server_name#<br />
2URL: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />

I typically also make the URL hot to ensure I can click on it from my email program.

Another idea to consider is placing the exception.message value in the message subject. You may want to trim it at 500 characters or so to keep it readable in your mail program.

One last suggestion: When working locally, it helps if you can skip the whole email process. While SpoolMail is helpful, I'd rather just get the error immediately. What I do then typically is check the server name CGI variable. If it is my local version, I dump the exception to screen.

Comments

[Add Comment] [Subscribe to Comments]

Ray: You're getting more into Flex lately - how do you handle errors thrown in cfc's called via flash remoting? I have a method I use - but I'm curious as to how you're doing it.
Todd, I knew there is a Fault handler when working with remote stuff. I'll blog on that. I'm DEFINITELY a noob but I'll share as it will flesh out better comments.

Ray Camden - making the world smarter by showing how much he doesn't know.

p.s. Check this blog for a very important announcement later today.
Sweet! Can't wait. Hey, just another quick FYI - your sites have been a little slow for me lately. I'm sitting on a T3 at work, so I don't think it's my connection.
Yeah, I see it too. I may be outgrowing the box that Hosting.com gave me. I can't complain as they have been hosting me free for a LONG time, and I give many kudos to them, but the box is a P3 with 1 gig of RAM.
Ray, just a tip that I picked up from Toby Goldfinger a while back at the NY CFUG meeting: when CFMailing yourself an error, you should do a StructDelete() on the FORM scope for any sensitive information like SSN or Credit Cards. That way, if the CFMail is send out over an unsecured (I don't know how it works behind the scenese), you don't have to worry about any one snooping on you. Either that, or encrypt it or something.
Very good point Ben.
<!--- ON ERROR --->
   <cffunction name="onError">
   
      <cfargument name="Exception" required="yes" />
      <cfargument name="EventName" type="string" required="yes" />
      
      <!--- Watch out for "coldfusion.runtime.AbortException" errors that result from <cfabort> and <cflocation> tags --->
      <cfif arguments.exception.rootcause.type neq "coldfusion.runtime.AbortException">
         
         <!--- Construct error message --->
         <cfsavecontent variable="mailMessage">
            <!--- Mail message goes here (can be in html format) --->
         </cfsavecontent>
         
         <!--- Invoke Mail component (my CFC for sending emails) and send email --->
         <cfinvoke
          component="#Application.config.componentPath#.Mail"
          method="sendMail"
          returnvariable="sentStatus">
            <cfinvokeargument name="toEmail" value="foo@foo.com"/>
            <cfinvokeargument name="fromEmail" value="foo@foo.com"/>
            <cfinvokeargument name="fromName" value="foo foo"/>
            <cfinvokeargument name="subject" value="An error occured in website"/>
            <cfinvokeargument name="message" value="#mailMessage#"/>
            <cfinvokeargument name="htmlFormat" value=true />
         </cfinvoke>
         
         <!--- If the error didn't occur in the "onSessionEnd" and "onApplicationEnd" event handlers display error page --->
         <cfif NOT (arguments.EventName EQ "onSessionEnd") OR (arguments.EventName EQ "onApplicationEnd")>
            <!--- Redirect to error template --->
            <cflocation url="errorTemplate.cfm" addtoken="no" />
         </cfif>
         
         
      </cfif>
   </cffunction>
Oops I missed out the important part.

The mail message in the <cfsavecontent> tag could be in this format

<cfsavecontent variable="mailMessage">
            <cfoutput>
               <h3>An error occcured on the website, foo.com</h3>
               <p>The error information is given below.</p>
               <div style='background-color:##FDFFEF;border:1px solid ##ECEFD1; margin-top: -0.3em;   padding: 8px; margin-bottom: 0.3em; color: ##666666; font-size:13px; font-family:"Tahoma, Verdana"'>
               <p><b>ERROR INFORMATION</b></p>
               <p><strong>Page : </strong> #cgi.SCRIPT_NAME#</p>
               <p><b>Error Type : </b>#arguments.Exception.type#</p>
               <p><b>Error Message : </b>#arguments.Exception.message#</p>
               <p><b>Error Details : </b>#arguments.Exception.Detail#</p>
               <p><strong>ROOT CAUSE </strong></p>
               <p><strong>Type : </strong>#IIf(arguments.exception.rootcause.type neq "",Evaluate(DE("arguments.exception.rootcause.type")),DE("None"))#</p>
               <p><strong>Message : </strong>#IIf(arguments.exception.rootcause.message neq "",Evaluate(DE("arguments.exception.rootcause.message")),DE("None"))#</p>
               <p><strong>Detail : </strong>#IIf(arguments.exception.rootcause.detail neq "",Evaluate(DE("arguments.exception.rootcause.detail")),DE("None"))#</p>
               <cfdump var="#arguments.exception.rootcause.tagcontext#" />
               <p><strong>Date and time : </strong> #TimeFormat(now(),"short")# #DateFormat(now(),"full")# <br>
               <strong>IP Address : </strong> #cgi.REMOTE_ADDR# <br>
               <strong>Browser : </strong> #detectBrowser()#<br>
               <strong>HTTP Referer : </strong> #IIf(cgi.HTTP_REFERER neq "",Evaluate(DE("cgi.http_referer")),DE("None"))#<br></p>
               </div>
               <p>-----------------------------------------------------------------------------</p>
            <p style='color:##666666; font-size:11px; font-family:"Verdana"'>foo foo<br/><br/><br/><a href="foo.com">foo.com</a></p>
            </cfoutput>
         </cfsavecontent>
I setup a template that logs errors to a DB. This way I can run reports and such. I setup scheduled tasks to email error reports even. Able to snag a stack trace this way too. Note that need to add a cflog call to enter the data in the application log.

DK
Re showing the debug info on the screen: One could also switch based on a client.debug variable (or session.debug), and allow users to switch debug modes based on other criteria (like IP+url vars or password or login) -- if client.debug on, skip the email and show debug info.

Especially if you are looking at the same hostname that others are seeing.

[Add Comment] [Subscribe to Comments]