Saturday 24 March 2012

Logging and Suppressing JavaScript errors

Logging JavaScript errors to a file by overwriting the window.onerror method

Sometimes you may have intermittent JavaScript errors that you cannot re-produce or maybe you just want to be able to log JavaScript errors for later viewing. Or maybe you just want to suppress them so that end users don't see them.

By using the useful and also dangerous feature of being able to overwrite core JavaScript functions and objects you can utilise this to your advantage by overwriting the window.onerror method.

The window.onerror method takes 3 parameters which are:

  • message : the error message
  • url: the URL of the file that raised the error message
  • line: the line number that the error occurred on.


Therefore it is very easy to create your own window.onerror function to take these values and then make an AJAX call to a server side page which logs the JavaScript error details to a file or database or even sends an email.

Also by overwriting the window.onerror function we can suppress JavaScript errors if we chose to.

Maybe if we are debugging a script and don't want the error console constantly filled up or maybe some of our users are still using Windows 98 and use IE 4.

If we are using unobtrusive JavaScript that builds layer upon layer of functionality starting with the lowest common denominator e.g HTML, then adding JavaScript functionality if they have it, Flash if they have it and so on then we may want to just suppress these JavaScript errors in old browsers.

To suppress a JavaScript error you just need to return true.

This example uses jQuery seeing that is so popular but any AJAX library can be used. The point is that you are taking the error parameters and logging them somewhere useful.

I have used a little JavaScript wrapper object to set some system properties like a config object to define whether error logging is on or off and whether or not to suppress errors in older browsers. 

The code to define which browsers to suppress in can be left to you but I have done a simple test for document.getElementById which means browsers like IE 4 and NN4 won't get errors raised.


// Log JS errors to a file - file is overwritten each day only use when debugging a particular page/site

// Set up our global config options to decide whether to log JavaScript errors and whether or not to suppress them. A simple false/true could suffice but we might want to test for old browsers or certain features. If the browser doesn't support document.getElementById it's a pretty old browser!
GlobalSettings = {
 SystemName : "Strictly-Software",
 Version : 2.0.1,
 LogJSErrors : true,
 SuppressJSErrors : (document.getElementById) ? false : true
}

// override the onerror object
window.onerror = function(msg, url, line)
{   
 // does our global system want to log errors - this could be a Client or Serverside setting
 if (GlobalSettings.LogJSErrors)
 {  
                // using JQuery to post a GET request to a page that logs the error details
  $.get("logJSError.php", { message: msg, errorlocation: url, lineno: line } );
 }
 

 // do we still raise the error or for old browsers which might have a lot of errors do we try and supresss them? Use our global config options again.
 if(GlobalSettings.SuppressJSErrors){  
  // return true to suppress the error so its not raised to the console.
  return true;
 }else{
  // return false to raise the error to the console.
  return false;
 } 
}

Then all you need is to define your server side page logJSError.php (or whatever language you are using) to collect the error data from the request and do whatever you want with it e.g log it somewhere for later viewing.

Remember whilst being able to overwrite functions that already exist is good in certain situations like this and the Lazy Function scenario but it can also cause you severe debugging nightmares like the one I discovered when using the common addEvent naming convention for cross browser adding of events.

Therefore be careful especially when overwriting core JavaScript features but also use them to your advantage when possible.


3 comments:

Anonymous said...

onerror is a great way to start. We'
ve done a ton of work on logging JavaScript errors at our startup at http://muscula.com.
It's a complex problem, one problem is that your log gets clouded with all sorts of irellevant errors caused by browser plugins.
But if you are not logging at the moment adding logging to window.onerror will get you started.

Dumitru Glavan said...

It's a bit more complex to log the clientside errors, supporting all the major browsers and mobile devices. We built http://jslogger.com to take care about that. It's also possible to log the backend errors with the NodeJS library. Worth to give it a try.

Rob Reid said...

Explain yourselves, what's so difficult about trapping and logging JS errors by overwriting the onerror object?