Inspired? No home

Custom Error page on IIS and logging

Errors are unwanted, but is almost impossible to eliminate especially with a large application. We all know that we should minimize errors and that errors are bad, but to handle this there are three issues we need to be aware of:

Problem: When the user see an error in the application, the user becomes unhappy and it results in a negative experience with the product. If this hapens often it will lead to the customer becoming unsatisfied and it addition it will hurt the brand image.
Our solution: When an error occurs a custom and a pleasant error page is displayed. It will alert the user that an error occurred and that it has been logged to a database. This gives the user confidence that the error will be fixed. It is also much better to view a relatively nice error page than a broken document with an ugly ASP error in the middle of the page.

Problem: An error means a system bug. Most bugs are left unreported by user. For a developer it can be close to impossible to find and track all bugs.
Our solution: Using an error logging tool which logs all errors occurred to a database, developers have overview of when and where the error occurred, what the error message was, what input variables was given to the script and which user who executed the script. In most cases this will give the developer enough information to fix the error straight away or test the script and understand the cause of the error.

Problem: When a user received an error when working with an important task or if the error repeats itself then the user calls customer service. Having worked in customer service earlier I know how difficult it is to get a clear overview of the user is doing and what the error is. When the developer gets the error report it is very hard to track and debug the error.
Our solution: When the user receives an error, the user is presented with an option to contact customer service through a form. This form automatically fills out the error reference. In addition the error reference number is displayed for the user so he/she can quote it when calling customer service. This results in the developer being able to pinpoint the error that occurred making the process much quicker and keeping the customer happy.

So how do we do this in practice?

1. Set up a custom error page in IIS. Create a page in your web-application, i.e. /system/error.asp. Have IIS execute this page when 500 and 500.100 error occurs. For more information see this MSDN article. The article covers how to implement a custom 404 page, but it's the same with 500/500.100 pages, just select those from the list instead. I recommend that you set up a custom 404 page as well.

2. When that is done try to view a script with an error in your web-application. See it will redirect to the /system/error.asp page.

3. Next task is to create the error.asp page. First thing to do is design it with information that shall be displayed to the user. Then comes the scripting part:

Make sure you include response.clear at the top of the script. This is because when an error occurs IIS is doing a server.execute("/system/error.asp"), thus all the contents from the script where the error occurred will be included unless the response is cleared.

then we get all the information about the error using the ASP error object:

dim objErr, err_asp_desc, err_desc, err_no, err_src, err_line
dim err_col, err_page, err_cat, err_asp_code, err_input, err_script
set objErr = server.GetLastError()
if objErr.Number <> 0 then
err_asp_desc = objErr.ASPDescription
err_desc = objErr.Description
err_no = objErr.Number
err_src = objErr.Source
err_line = objErr.Line
err_col = objErr.Column
err_page = objErr.File
err_cat = objErr.Category
err_asp_code = objErr.ASPCode
err_input = request.ServerVariables.Item("QUERY_STRING")
err_script = request.ServerVariables.Item("SCRIPT_NAME")
end if
set objErr = Nothing

See there are scripts here. That is because when using an include file, the ASP error object will report the name of the include file if that is where the error occurred. But many times the script which holds the reference to the include file is the reason for the error, thus we need to get the script name as well.

The next task is to log this error to the database:

dim c_db, sql, RefId, c_dbrs
set c_db = server.CreateObject("ADODB.Connection")
c_db.Open Application("ConnString")
sql = "INSERT INTO Website_Error (ErrorNumber, ErrorDesc, Script, ErrorScript, QueryString, ErrorLine, ErrorColumn, ErrorCategory, ErrorSource, ASPError, ASPDescription, IP, UserId, ContactId) VALUES (" & err_no & ", '" & err_desc & "', '" & err_script & "', '" & err_page & "', '" & err_input & "', " & err_line & ", " & err_col & ", '" & err_cat & "', '" & err_src & "', '" & err_asp_code & "', '" & err_asp_desc & "', '" & request.ServerVariables.Item("REMOTE_ADDR") & "');"
sql = "SELECT @@Identity FROM Website_Error;"
set c_dbrs = c_db.Execute(sql)
RefId = c_dbrs.fields.item(0).value
set c_dbrs = nothing
set c_db = Nothing

The RefId is used to identify the error. This can be displayed to the user the user can quote this reference id when contacting customer service.

And there you have it - a custom error page with error logging!

Written on 16 June 2004.
blog comments powered by Disqus