[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 352
  • Last Modified:

Error Class

I was surfing the web to see how others are doing error catching and the following caught my eye:

<%
Class TestForError
     Dim sLogFile

     Private Sub Class_Initialize
          sLogFile = "C:\temp\testforerror.txt"
     End Sub

     Private Sub Class_Terminate
          RespondToCrash
          'If Err Then RespondToCrash
     End Sub

     Private Sub RespondToCrash
          Dim oFS, oTextFile
          Set oFs = Server.Createobject("Scripting.FileSystemObject")
          Set oTextFile = oFs.OpenTextFile(sLogFile,8)
          oTextFile.WriteLine "Err = " & Err & ", Err.Description = " & Err.Description
          oTextFile.Close
          Set oTextFile = Nothing
          Set oFs = Nothing
     End Sub

End Class
%>
====================================

Now just at the top of every page, you can do this:
<%
Set oErrorTest = new TestForError
%>

This was posted by experts-exchange member sybe.  I really like the idea of doing it this way, but what if there is more than on error on this page.  Is there a way for this script to log all of the errors?

In addition to that, is there a way to do it without adding On Error Resume Next?

The reason I like the idea of using the class is so I do not have to manually add checks in everywhere to see if there has been an error.  I can just place that code at the top of the page and be done with it.
0
mystami
Asked:
mystami
  • 21
  • 15
1 Solution
 
chisholmdCommented:
You would still need to use on error resume next,

also after any line of code that you want to trap a potential error you would still have to do this:
oErrorTest.RespondToCrash

It is really to bad ASP never had an "on error goto [label]"  or even a try catch




0
 
mystamiAuthor Commented:
actually with what i just posted you do not have to do that.  

assuming there is only one error, it will of course stop your page from loading, but all you have to do is post that one line at the top and it catches it.
0
 
chisholmdCommented:
Oh I see on class terminate it calls the method, missed that the first time.

I am not sure if you can achieve what you want, and I am not understanding why you would want to.

Once the first run time error occurs it changes the environment so much that you would most likely get cascading errors that would not occur if the first one did.  

For example lets say you created a connection object to your db and tried opening it with a typo in your connection string.  It will cause an error.  Now maybe the next line of code uses that connection object, but since you had the wrong connection string it would throw an error saying that the connection is not open.  Its a useless error because it wouldn't have happened if the first one hadn't.  So if you let operation continue logging each error, you'll have a full page of error messages from the one simply cause.

Was there some reason this is desirable?

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
mystamiAuthor Commented:
I just thought since there are many things going on at one time that it may be good to see all the errors.  When other coders  have an email/log error function and do If Err<>0 Then throughout all of their code.  They see every single error.  What's the difference?

And I don't want to do it the way everyone else does because it's too much work to add that to every sub/function, etc.
0
 
chisholmdCommented:
What I do is have a custom 500 error page.  So I configure IIS to use asp500.asp for 500 errors.  Then on that page I give the user a Whoops! type message and email myself the information about the error.

Whenever I get one of those emails I go investigate and fix it as soon as possible.

I don't have to wrap my code in any error trapping code, and I only wrote the custom 500 page once and use it on a bunch of different sites.

Would that type of solution work for you?

Note: There are times that I do check err within my code like when I am opening a HTTP connection to another site, or sending confirmation emails, places when I have a higher expectation of an error condition. Then I can give the user a more useful message then Whoops!  eg. "Flikr is unavailable please try again later"  or things like that.
0
 
mystamiAuthor Commented:
I would definitely be interested to see it.  

See my concern is on one of the last sites I did I had people signing up to become a member.  The system at first so I could monitor who was signing up would e-mail me and tell me some brief information.  Everything worked great except for periodically I would get an e-mail that would be partially blank, and I would check the database and sure enough there was a problem.

Well I never did figure out what was causing it, so when I do this again, I want to be sure I'm receiving all the information I need to debug something incase I run into something similar.

That's why I've been so concerned about having the best proper error submission.
0
 
chisholmdCommented:
I understand completely. My customer satisfaction went up a lot when I started calling clients to tell them something was fixed before they had a chance to call me to tell me it was broken.

This solution involves a free COM object and a free event log monitor  program both have to be installed on the server so it might be tough in a shared hosting environment.

So here is what you do.  Make a page called something like 500.asp (code below).  Then in IIS go to the  custom errors tab on your websites properties.  Scroll down to 500 and change it to type "URL" and put in the relative path to your new asp page. eg "/500.asp" (without quotes).  

For simplicity sake I make a separate page to show users and then redirect to it after I have finished processing the error. In the sample below I call it error.asp

(Information about the COM object and the event monitor after the the 500.asp code)

<%@ language="VBScript" %>
<%
  Option Explicit

  Const lngMaxFormBytes = 200

  Dim objASPError, blnErrorWritten, strServername, strServerIP, strRemoteIP
  Dim strMethod, lngPos, datNow, strQueryString, strURL,strEventText

Set objASPError = Server.GetLastError
strEventText = objASPError.Source & vbCrLF _
            & "File: " & Server.HTMLEncode(objASPError.File) & vbCrLF _
            & "Line: " & Server.HTMLEncode(objASPError.Line) & vbCrLF _
            & "Source: " & Server.HTMLEncode(objASPError.Source) & vbCrLF _
            & "Description: " & Server.HTMLEncode(objASPError.Description) & vbCrLF _
            & "Number: (0x" & Server.HTMLEncode(Hex(objASPError.Number)) & ")" & vbCrLF _
            & "ASPCode: " & Server.HTMLEncode(objASPError.ASPCode) & vbCrLF _
            & "Category: " & Server.HTMLEncode(objASPError.Category) & vbCrLF _
            & "ASP Description: " & Server.HTMLEncode(objASPError.ASPDescription) & vbCrLF _
            & "Browser: " & Server.HTMLEncode(request.servervariables("HTTP_USER_AGENT")) & vbCrLF _
            & "Server: " & Server.HTMLEncode(request.servervariables("SERVER_NAME")) & vbCrLF _
            & "URL: " & Server.HTMLEncode(request.servervariables("URL")) & vbCrLF _
            & "REMOTE ADDR: " & Server.HTMLEncode(request.servervariables("REMOTE_ADDR")) & vbCrLF _
            & "Refering page: " & Server.HTMLEncode(request.servervariables("HTTP_referer"))

'response.write "<!--<hr>"& vbcrlf& vbcrlf
'response.write request.servervariables("REMOTE ADDR") & vbcrlf
'response.write strEventText& vbcrlf& vbcrlf
'response.write "<hr>-->"& vbcrlf& vbcrlf

'********************************************
'  Write ASP error to application event log.
'********************************************
Const EVENTLOG_SUCCESS = 0
Const EVENTLOG_ERROR_TYPE = 1
Const EVENTLOG_WARNING_TYPE = 2
Const EVENTLOG_INFORMATION_TYPE = 4
Dim xObj, bResult
Set xObj = Server.CreateObject("SOFTWING.ASPEventlog")
bResult = xObj.Open()
bResult = xObj.ReportEvent(EVENTLOG_ERROR_TYPE, strEventText)
bResult = xObj.Close()
Set xObj = Nothing

response.redirect("/error.asp")
%>

Information about SOFTWING.ASPEventlog  and how to install it can be found here:
http://www.alphasierrapapa.com/IisDev/Components/AspEventLog/

So at this point we have all our 500 errors being written to the windows event log.  But we want them emailed to us. For that I use the free "Lite version" of EventSentry.  All the info about it can be found here:

http://www.eventsentry.com/

EventSentry has a lot of options that are all out of the scope of this solution. Suffice to say you can set the lite version to email one or more people anything you want from the event log errors, warnings, etc.  You can also set specific filters so that you only receive certain errors if you want.  Its all in the docs :)

Up until now I had considered this one of my trade secretes. I guess the cats out of the bag now :)

Let me know how it works out for you.
0
 
chisholmdCommented:
btw: I also use this for 404 errors.
0
 
mystamiAuthor Commented:
Currently, as you guessed, I'm using a shared hosting, I like what I see so far though, any thoughts toward a solution for my situation?

You think just change from posting to the event log to sending an e-mail?
0
 
chisholmdCommented:
ya you could easily just have the 500.asp send the email either with cdo or any smtp component they make available.  Are you able to specify custom 500 error pages?

How much you paying for hosting and what is the site?

0
 
mystamiAuthor Commented:
To minimize cost for testing until the site is actually running and making some cash we are using a GoDaddy account.  :-\  So I don't think using the custom 500 error page is going to work in this situation.  Considering the only custom error page they allow for is the 404 page.

I also have another account that I would like to use this on which is also on a GoDaddy hosting plan.

I'm not real familiar with how the Server.GetLastError works, would it work properly if just used in conjunction with the class that I showed at the top?

Also, I noticed you do not have it show you the users Operating System, do you find it unnecessary when trying to duplicate the error when trying to debug?
0
 
mystamiAuthor Commented:
Also, just reading through the code again, what's this in your code for?

Const lngMaxFormBytes = 200
0
 
chisholmdCommented:
Can't remember. :)   I copy this page to each new site then adjust as necessary for any specific needs. Sometimes I get leftover junk DNA :)
0
 
mystamiAuthor Commented:
Did you read my message before that one?
0
 
chisholmdCommented:
No I typically don't need their operating system because these are server side errors and it isn't typically a factor.

Well if that class works then in the RespondToCrash method it already references the err object and should already have access to the error info.  I don't see why the Server.GetLastError method wouldn't work. Testing will tell for sure.

You can just change the respond to crash method to email you instead of writing it to a text file, or you can do both.  

I am surprised that they don't offer a custom error page option, a real pity.
0
 
mystamiAuthor Commented:
Well I just tested it and wherever it calls the server object it returns an empty string.  :(
0
 
mystamiAuthor Commented:
You better believe I'm going to save what you have showed me though as far as if they did offer a custom error page.  But for now I would love to find a way to get the Server.GetlastError to function.
0
 
chisholmdCommented:
Are you generating an error to test?

I always put a page on my sites that I can use to force an error and test the monitoring.  http://[domain]/makeerror.asp

All I put in it is a code block with a string variable assignment with an unterminated string.

I just ran it and this is the message that is written to the event logs and emailed to me.

========================================
EVENT #      1513885
EVENT LOG      Application
EVENT TYPE      Error
SOURCE      AspEventLog
EVENT ID      100
COMPUTERNAME        [SNIPPED SERVER NAME]
TIME      10/18/2007 4:07:57 AM
MESSAGE      AspEventlog: someVar = "this
File: /makeerror.asp
Line: 10
Source: fish = "this
Description: Unterminated string constant
Number: (0x800A0409)
ASPCode:
Category: Microsoft VBScript compilation
ASP Description:
Browser: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7
Server: [snip domain]com
URL: /makeerror.asp
REMOTE ADDR: 000.000.000.00
Refering page:
========================================


Have you ever got that class to work?  I just tried it and it didn't for me.
0
 
mystamiAuthor Commented:
Actually, I just was testing and noticed I had On Error Resume Next, so I took that out of the code and it wrote to my log...

-----------------------------------
File: /roommate/default2.asp
Line: 66
Source:
Description: Type mismatch: 'PageLoading1'
Number: (0x800A000D)
ASPCode:
Category: Microsoft VBScript runtime
ASP Description:
Browser: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; .NET CLR 1.1.4322; InfoPath.2)
Server: localhost
URL: /roommate/default2.asp
REMOTE ADDR: ::1
Refering page:
-----------------------------------

Which is definitely making progress!  I wonder why the On Error Resume Next kills it?  And it's not retrieving all of the properties like it should?
0
 
mystamiAuthor Commented:
So maybe you can test it here's the exact code that I'm running is as follows:

=====clsError.asp=====
<%
Class TestForError

Dim sLogFile

Private Sub Class_Initialize
      sLogFile = "C:\temp\testforerror.txt"
End Sub

Private Sub Class_Terminate
      RespondToCrash
      'If Err Then RespondToCrash
End Sub

Private Sub RespondToCrash
      Dim oFS, oTextFile
      Set oFs = Server.Createobject("Scripting.FileSystemObject")
      Set oTextFile = oFs.OpenTextFile(sLogFile,8)

            Const lngMaxFormBytes = 200
      
        Dim objASPError, blnErrorWritten, strServername, strServerIP, strRemoteIP
        Dim strMethod, lngPos, datNow, strQueryString, strURL,strEventText
      
                  Set objASPError = Server.GetLastError
                  strEventText = objASPError.Source & vbCrLF _
                              & "File: " & Server.HTMLEncode(objASPError.File) & vbCrLF _
                              & "Line: " & Server.HTMLEncode(objASPError.Line) & vbCrLF _
                              & "Source: " & Server.HTMLEncode(objASPError.Source) & vbCrLF _
                              & "Description: " & Server.HTMLEncode(objASPError.Description) & vbCrLF _
                              & "Number: (0x" & Server.HTMLEncode(Hex(objASPError.Number)) & ")" & vbCrLF _
                              & "ASPCode: " & Server.HTMLEncode(objASPError.ASPCode) & vbCrLF _
                              & "Category: " & Server.HTMLEncode(objASPError.Category) & vbCrLF _
                              & "ASP Description: " & Server.HTMLEncode(objASPError.ASPDescription) & vbCrLF _
                              & "Browser: " & Server.HTMLEncode(request.servervariables("HTTP_USER_AGENT")) & vbCrLF _
                              & "Server: " & Server.HTMLEncode(request.servervariables("SERVER_NAME")) & vbCrLF _
                              & "URL: " & Server.HTMLEncode(request.servervariables("URL")) & vbCrLF _
                              & "REMOTE ADDR: " & Server.HTMLEncode(request.servervariables("REMOTE_ADDR")) & vbCrLF _
                              & "Refering page: " & Server.HTMLEncode(request.servervariables("HTTP_referer"))
      
                  'response.write "<!--<hr>"& vbcrlf& vbcrlf
                  'response.write request.servervariables("REMOTE ADDR") & vbcrlf
                  'response.write strEventText& vbcrlf& vbcrlf
                  'response.write "<hr>-->"& vbcrlf& vbcrlf

      'oTextFile.WriteLine "Err = " & Err & ", Err.Description = " & Err.Description
      oTextFile.WriteLine strEventText
      oTextFile.Close
      Set oTextFile = Nothing
      Set oFs = Nothing

      End Sub

End Class
%>
=====clsErro.asp End=====



=====default2.asp=====
<!--#include virtual="/roommate/scripts/clsError.asp"-->

<%
Dim oErrorTest
Set oErrorTest = New TestForError
PageLoading1
%>
=====default2.asp End=====

which in the log returns...
=====testforerror.txt=====

File: /roommate/default2.asp
Line: 8
Source:
Description: Type mismatch: 'PageLoading1'
Number: (0x800A000D)
ASPCode:
Category: Microsoft VBScript runtime
ASP Description:
Browser: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; .NET CLR 1.1.4322; InfoPath.2)
Server: localhost
URL: /roommate/default2.asp
REMOTE ADDR: ::1
Refering page:
=====testforerror.asp End=====
0
 
chisholmdCommented:
I am trying to remember about the "Refering page"  I think I never got this working the way that I wanted.  

What I wanted was the referring page to the page with the error (eg when they went from a to b thats when the error happened on b)  but the best I got was the referring page to the custom error page (b) and of course thats the same url as "File: /roommate/default2.asp"

I think the source field depends on the type of error.   Sometimes I get it sometimes not.

For me this was enough.  Most of the time if I get a message it tells me the page and the line number which is typically all I need to go in and figure out what happened.

Looks like your on your way. Just need a CDO emailer and this would be a very portable script for any ASP developer.  Maybe I'll post a cleaned up copy on my site in the web developers checklist:  http://lonecrow.net/lc-checklist.asp

I'll post this portable version, and my preferred version writing to the event log.

0
 
mystamiAuthor Commented:
Well, I just tried to do an Unterminated string like you did, with no response to the log at all.  So something is not quite finished.
0
 
mystamiAuthor Commented:
I think I've decided to go with a dedicated server, but I would for you to tell me what I'm doing wrong with trying to setup the custom error page on my IIS on my vista system.
0
 
chisholmdCommented:
I am not sure I understand.  A few posts ago you showed that it wrote the error to your log.
-----------------------------------
File: /roommate/default2.asp
Line: 8
Source:
Description: Type mismatch: 'PageLoading1'
Number: (0x800A000D)
-----------------------------------
So your error class was working but now its not?  I am confused.

What is your site?
0
 
mystamiAuthor Commented:
It only worked for that error and I could not get it to work with any other error.  So I had abandoned the idea that it would ever work properly.

So I attempted to setup the custom error pages but only ever got a blank page when Execute URL was selected.
0
 
mystamiAuthor Commented:
I did get it to do the division by zero, but it definitely would not do the Unterminated string.  Any thoughts?  I may even consider accepting it not doing that if we could figure out how to get the Server.GetLastError to work.

Or do you think it won't work and I should just go for the custom error pages?  
0
 
chisholmdCommented:
Perhaps the different errors produce different stop conditions.  For example maybe the unterminated string causes operation to cease in a way that prevents the error class from doing termination.  

Hmmm Ya you would think that the unterminated string would be a compile error, whereas the divid by zero is a run time error.  So in the unterminated string scenario the error class never gets instantiated.

Ya I found a reference that bears that out:
 http://www.plourdenet.com/asp30/10.aspx

ASP is a compile on first run script engine.  There is a great series of posts from one of the ASP developers at: http://blogs.msdn.com/ericlippert/ 

I found this post particularly enlightening
http://blogs.msdn.com/ericlippert/archive/2003/09/18/53046.aspx



0
 
mystamiAuthor Commented:
When this is processed where can I find the log?

Const EVENTLOG_SUCCESS = 0
Const EVENTLOG_ERROR_TYPE = 1
Const EVENTLOG_WARNING_TYPE = 2
Const EVENTLOG_INFORMATION_TYPE = 4
Dim xObj, bResult
Set xObj = Server.CreateObject("SOFTWING.ASPEventlog")
bResult = xObj.Open()
bResult = xObj.ReportEvent(EVENTLOG_ERROR_TYPE, strEventText)
bResult = xObj.Close()
Set xObj = Nothing
0
 
mystamiAuthor Commented:
I finally got the two COM objects installed on the server and am trying to use them that's why I asked the question above.  I would love to see an example of the EventSentry Lite that you are using to get a good feel of how it works.

Thanks for all your help!!
0
 
chisholmdCommented:
The logs are written to the "Windows Event Logs"  (event viewer under admin tools)

They probably have screenshots and docs here about event sentry:
http://www.eventsentry.com/

0
 
mystamiAuthor Commented:
So with ASPEventlog installed on the server does it write logs to the server or does it write to the users computer?

And I cannot find any example code on the EventSentry Lite e-mailing.
0
 
mystamiAuthor Commented:
I'd be willing to open another question and award you another 500 points for the extra information!
0
 
chisholmdCommented:
ASPEventLog write to the windows event logs on the server.  

When you dl and install event sentry lite it has a GUI for configuring the types of event log information you want to establish alerts and also how you would like to be notified smtp, pager, etc.

Its a windows service that has a GUI for configuring all the options, no code to write.

Thats kinda the point of this setup.  I want to receive emails from the server when for example disk space gets low. That information is written to the event log so I use EventSentry to configure alerts to be emailed.  I also want to know if a website has a 500 or 404 error, so I use ASPEventLog to write those errors the the event log...which is already configured to email to me.

0
 
mystamiAuthor Commented:
Oh so I had that company install EventSentry for me, there's no way I can control how it operates through code?  Since I have no access to the actual server?
0
 
chisholmdCommented:
I thought you got a dedicated server? don't you have admin access via remote desktop? (terminal services)

I rolled out EventSentry to about a dozen servers once and I used a registry import to do it.  Umm I wonder if I sent you the .Reg file and you changed the email setting they could simply import it to the registry...sounds a bit dicey though if they didn't install to the same place.

Perhaps you wanna visit this page.
http://lonecrow.net/lc-contact.asp




0
 
mystamiAuthor Commented:
Well I got a reseller plan for pretty cheap and I'm hosting for a few companies.  Figured I would start there until I built up my client base then I would switch to a true dedicated server.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 21
  • 15
Tackle projects and never again get stuck behind a technical roadblock.
Join Now