skip navigation

JavaScript: Using XMLHttpRequest to log JavaScript errors

If you've read the related article Recording Outbound Links using Ajax you'll be familiar with the concept of using Ajax to record user actions. This article goes a step further letting you log any JavaScript errors that occur on your site to a text file that you can later view or download.

This can be very handy as many JavaScript errors are user-, browser- or platform-specific and it's not always possible to test a site yourself using all the different combinations.

Defining a Custom Error Handler

The first step is to override or redirect the built in error handler window.onerror with our own function. This is a lot simpler than it sounds:

<script type="text/javascript" src="ajaxrequest.js"></script> <script type="text/javascript"> window.onerror = function(msg, url, line) { if(encodeURIComponent) { var req = new AjaxRequest(); var params = "msg=" + encodeURIComponent(msg) + '&url=' + encodeURIComponent(url) + "&line=" + line; req.setMethod("POST"); return req.loadXMLDoc("/scripts/logerror.php", params); } return false; } </script>

One point to note is the return value of the window.onerror function. If you return a value of true then only your function will be called and no message will be presented in the browser. If you instead return a value of false, your error handler will be called and then the browser will respond to the error in it's own way.

The function as presented will either make a successful call to the server-side script (see below) or let the browser display the error to the user as it sees fit. That way someone is always notified of the error.

The best place for this code is in the HEAD of your HTML document or in an included JavaScript file.

Logging errors to a text file

Here we see how a PHP script can be used as the target of the Ajax request in order to record the details of the error:

<?PHP include "class.xmlresponse.php"; if($_POST && isset($_POST['msg']) && isset($_POST['url']) && isset($_POST['line'])) { $msg = $_POST['msg']; $url = $_POST['url']; $line = $_POST['line']; if($fp = fopen("{$_SERVER['DOCUMENT_ROOT']}/onerror.log", "a")) { $logline = "[{$_SERVER['REMOTE_ADDR']}]: $msg in $url on line $line"; fwrite($fp, date("M d H:i:s") . " $logline\n"); fclose($fp); } } $xml = new xmlResponse(); $xml->start(); $xml->end(); ?>

Note: save this script as ~/scripts/logerror.php for the whole example to work.

When it receives a POST request with values for msg, url and line then a line containing that information is added to the file onerror.log. The XML header and empty response tag are necessary only to prevent a JavaScript error in the processReqChange - very important in this case as you don't want to create an infinite loop.

The onerror.log file needs to be writable by the webserver. The best way to enable this is to first touch the file so that it exists, then chgrp the file to the webserver user and finally chmod 664 to make it writable.

Unfortunately the Safari and Opera web browsers no longer support the setting of an onerrer event handler, so this script is less useful than it might have been.

Possible additions to the script

If you're going to use this on a live site then you might want to consider:

  • checking that the Referer is actually your own website;
  • modifying the fwrite message to include the User Agent string so you can see which browser encountered the error; and
  • monitoring the log file using a cron or similar script to make sure it's not growing out of control.

The code presented here works in Internet Explorer (Win) and Firefox, but not so well in Safari which seems to have it's own way of handling errors. Some Mozilla browsers also don't seem to pass a value for url to the error handling function.

Related Articles

References

< Back to JavaScript


User Comments and Notes

21 July 2008: Carro DF Brasilia says:

Thanks for the function, a use them to build a prototype version:

function js_err_logger(msg, url, line)
{
if(encodeURIComponent) {
var params = 'msg=' + encodeURIComponent(msg) + '&url=' + encodeURIComponent(url) + '&line=' + line;
var uri = '/index.php?opcao=default&tarefa=js_err_logger';
var opt= { method:'post', postBody:params, onSuccess:function(r) { if(debug=='1') alert(r.responseText); }, on404:function(t) { alert(t.statusText)}, onFailure:function(t) { alert(t.statusText) }, asynchronous:true };
return new Ajax.Request(uri,opt);
}
return false;
}

window.onerror = js_err_logger;


Send Feedback

Send Your Feedback (will not be published) (optional) CAPTCHA refresh copy the digits from the image into this box

[top]