log errors with stack trace in javascript

2ni picture 2ni · Dec 25, 2009 · Viewed 9.7k times · Source

I'm trying to log javascript errors on a productive site. So far it worked quite well with the following code included in the site:

function catcherr(errorMessage, url, line) {
    var parameters = "msg=" + escape(errorMessage)
            + "&url=" + escape(url)
            + "&line=" + escape(line);

    new Image().src = "/error.gif?" + parameters;

    return false;
};

window.onerror = catcherr;

I'm trying to add a stack trace to the errors to get more information. This basically works with the following idea including into the function above:

    try { i.dont.exist += 0; } // does not exist - that's the point
    catch (e)
    {
            if (e.stack) // Firefox
            {
               // do some stuff

I use jquery, a simple example:

<script type="text/javascript">
jQuery(document).ready(function() {
    p.foo += 1; // this should throw an error
    // do stuff
});
</script>

The funny part is, that when I have an error inside the "ready" function of jquery, the part "try { i.dont.exist += 0; }" does not throw any exception anymore and the engine stops without any error. With the example above, and catcherr extended as follows, only "1" gets alerted:

function catcherr(errorMessage, url, line) {
    try { alert(1); i.dont.exist += 0; alert(4);} catch(e) { alert(5);}
    alert(2);
    var parameters = "msg=" + escape(errorMessage)
    // ...
}

Anyone having an idea why this breaks, when an error occurs inside the "ready" function of jquery?

Answer

Guss picture Guss · Dec 29, 2009

I don't know why you have that problem (it looks very weird and I don't think its a problem with JQuery eating your exceptions, as your alert(1) wouldn't have fired), but I did want to mention your use of Error.stack - when the onerror event gets called, you do not have the stack context of the original error, so getting a stack trace at that point (by catching your own error) will not yield a meaningful stack.

But back to a real answer - instead of simulating a problem by writing specifically broken code so you can catch the error, how about just directly throwing an error? The first line in your onerror handler could be:

try { throw new Error("dummy"); } catch (e) { alert(e.stack); }

This is valid code which will more likely not cause you problems.