Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest way to catch JS errors

I've been doing some research into how we can catch JavaScript errors, and then send them off to our own system for internal logging (so we can try and replicate where possible, and fix any possible bugs). So far I have found quite a few paid services:

  • http://newrelic.com/sp/javascript-errors
  • https://trackjs.com/
  • https://raygun.io

The TrackJS one does look interesting, but we really can't afford to be spending out yet more money each month. I then came across this libray:

http://www.stacktracejs.com/#!/docs/stacktrace-js

I can't seem to get it going though. Here is what I'm trying:

window.onerror = function(msg, file, line, col, error) {
    StackTrace.fromError(error).then(callback).catch(errback);
};

var callback = function(stackframes) {
    var stringifiedStack = stackframes.map(function(sf) {
        return sf.toString();
    }).join('\n');
    console.log(stringifiedStack);
};

var errback = function(err) {
        console.log(err);
};

StackTrace.get().then(callback).catch(errback);

... and all I get back is:

TypeError: ErrorStackParser is undefined

var stackframes = ErrorStackParser.parse(error);

Can anyone else suggest a solution, or see what I'm doing wrong with the stacktrace.js script?

UPDATE: With the help below, I was able to at least get it to do something now. Turns out you need multiple js libs:

  • https://github.com/stacktracejs/stacktrace.js
  • https://github.com/stacktracejs/error-stack-parser
  • https://github.com/stacktracejs/stack-generator

However, I still can't seem to get it going.

var callback = function(stackframes) {
    console.log(stackframes)
    var stringifiedStack = stamap(function(sf) {
        return sf.toString();
    }).join('\n');
    console.log(stringifiedStack);
};

var errback = function(err) { console.log(err.message); };

 try {
    foo;
 } catch(e) {
    StackTrace.get().then(callback).catch(errback);
 }

While I now get errors logged in the console, the line numbers and error messages are less than useless :( Example:

.get()@https://cdn.steampunkjunkies.net/2014/js/scripts-all11.js:5:19706
{anonymous}()@https://cdn.steampunkjunkies.net/2014/js/scripts-all11.js:84:2

Line 84 is the caller function:

StackTrace.get().then(callback).catch(errback);

...and line 5, is the minified include of stacktrace.min.js (in my main JS file)

I'm a bit baffled as to how we can even get any useful information out of this :/

UPDATE 2: Ok, I'm getting closer!

var callback = function(stackframes) {
    var stringifiedStack = stackframes.map(function(sf) {
        return sf.toString();
    }).join('\n');
    alert(stringifiedStack);
};

var errback = function(err) { console.log(err.message); };

 try {
    var foo = 0;
    foo / 1;

    aklert;

    test;
 } catch(e) {
    StackTrace.fromError(e).then(callback).catch(errback);
 }

This now prints out an alert() message:

{anonymous}()@https://cdn.steampunkjunkies.net/2014/js/scripts-all11.js:73:1

However, thats not all the information I need. Obviously it needs a nice message (i.e var x cannot be undefined)

Anyone got any ideas?

I did try storing them in an array (with the line number and col number), but that doesn't work across all browsers (and ironically, the debug code caused a fatal :))

UPDATE 3

Ok, well we are getting closer :)

var callback = function(stackframes) {
    var stringifiedStack = stackframes.map(function(sf) {
        return sf.toString();
    }).join('\n');
    alert(stringifiedStack);
};

var errback = function(err) { console.log(err.message); };

window.onerror = function(msg, file, line, col, error) {
    var callback = reportWithMessage(msg);
    StackTrace.fromError(error).then(callback).catch(errback);
};


function reportWithMessage(message) {
    return function report(stack) {
        var yourErrorCollectorUrl = 'https://steampunkjunkiesdev.net/cgi-bin/debug.cgi';
        stack.message = message;
        StackTrace.report(stack, yourErrorCollectorUrl);
    };
}

 try {
    var foo = 0;
    foo / 1;

    aklert;

    test;
 } catch(e) {
    StackTrace.get().then(reportWithMessage()).catch(errback);
 }

enter image description here

Line 92 is this one}:

StackTrace.get().then(reportWithMessage()).catch(errback);

...so all its doing, is telling me that this function was called, but it no line number for the actual error.

Any ideas? I can't believe how complicated it is to catch JS errors and just report them back to a script. You would have thought with the last 20+ years of the Internet developing, something more compliant would have been developed for us developers :/

like image 485
Andrew Newby Avatar asked Nov 09 '15 15:11

Andrew Newby


1 Answers

I'm sorry for your troubles getting started. Please use dist/stacktrace.min.js which has all dependencies bundled. I filed this issue so we can make this clearer and others avoid the pain you've encountered: https://github.com/stacktracejs/stacktrace.js/issues/140

Regarding the Error message, it seems like you can do something with the msg parameter of window.onerror in your error reporting system. I understand that it's not straight-forward given there is no obvious place to store messages.

How about this?

window.onerror = function(msg, file, line, col, error) {
    var callback = reportWithMessage(msg);
    StackTrace.fromError(error).then(callback).catch(errback);
};


function reportWithMessage(message) {
    return function report(stack) {
        var yourErrorCollectorUrl = 'https://yourdomain.com/ec';
        stack.message = message;
        // HTTP POST with {message: String, stack: JSON}
        StackTrace.report(stack, yourErrorCollectorUrl);
    };
}

Outside of window.onerror you can maybe do:

StackTrace.get().then(reportWithMessage()).catch(errorhandler);

UPDATE: In the case where you've caught an Error, you want to use

StackTrace.fromError(error).then(...).catch(...);
like image 71
Eric Wendelin Avatar answered Nov 06 '22 20:11

Eric Wendelin