57
KNOW YOUR ERRORS BECAUSE IT'S A JUNGLE OUT THERE

Know your errors

Embed Size (px)

DESCRIPTION

JS errors, they come from browsers. In various forms, languages and if they are happening in a customer you don't see them. We have a jungle of browsers out there, between desktop, mobile, tablets, tv's etc. Different flavors with the same pain in the end. Log your JS errors, adding stack trace information for them using stacktrace.js. And a small dashboard to look into it. Presented @ #fronttrends 2013

Citation preview

Page 1: Know your errors

KNOW YOUR ERRORSBECAUSE IT'S A JUNGLE OUT THERE

Page 2: Know your errors

WHO AM I?Diogo AntunesBooking.comSenior Client Side Developer@dicode

Page 3: Know your errors

OVERVIEW

logging JS errorsproof of concepttools/services

Page 4: Know your errors

SO WHY LOG JS ERRORS IF?

Page 5: Know your errors

YOU DO TDD

Page 6: Know your errors

YOU DO SELENIUM TESTS

Page 7: Know your errors

YOU DO HEADLESS BROWSER TESTING

Page 8: Know your errors

YOU HAVE A TESTING TEAM

Page 9: Know your errors

IT WORKS ON MY MACHINE

Page 10: Know your errors

IT'S A JUNGLE OUT THERE!

Page 11: Know your errors

3RD PARTY SCRIPTS THAT YOU DON'T CONTROLTwitter, Facebook, GA

Page 12: Know your errors

YOU USE A CDN

even if it is just to load jquery

Page 13: Know your errors

USERS INSTALL PLUGINS

Page 14: Know your errors

YOUR MARKETING DEPARTMENT LIKES TRACKING PIXELS

Page 15: Know your errors

YES, SOME THINGS YOU CANNOT CONTROLbut some of them you can mitigate

Page 16: Know your errors

SOME CHALLENGES

Page 17: Know your errors

LOCALIZED MESSAGES

Expected identifier, string or number

Identificador esperado

Se esperaba un identificador, una cadena o un número

Bezeichner erwartet

标识ّف د ا و

Page 18: Know your errors

LINE NUMBERminify js

using gzip and preserving new lines may be a temporary solution

Page 19: Know your errors

CRYPTIC MESSAGEScannot find method of undefined

Script error.

cross origin domain policy

Chrome and Firefox

Access-Control-Allow-Origin: *

Page 20: Know your errors

BE SAFEdeploy environment vars that disable 3rd party code

if possible, without making any deploy to live

that way you can take action quickly

Page 21: Know your errors

LET'S DO SOME LOGGING

Page 22: Know your errors

APPROACHES

Page 23: Know your errors

WINDOW.ONERROR

works across the board

amount of information is limited

window.onerror = function(msg, url, lno){ /* No impact besides parsing overhead is only for the request to log the error when one actually happens */ return true; //hides the message in supported browsers};

Page 24: Know your errors

TRY/CATCH

works across the board

try { throw new Error("my error");} catch (e){ e.stack; //chrome, firefox e.message; //opera log(e.stack || e.message || e);}

Page 25: Know your errors

TRY/CATCH

more meaningful errors

performance hit, but you should evaluate if it matters

may lead to a lot of nesting if not thought through

var fn = function(){ throw "new error"; //this exception will not be caught //since it's a string it will not have stack trace};try{ setTimeout(fn,0);} catch(e) { }

Page 26: Know your errors

TYPES OF EXCEPTIONS

ErrorEvalErrorRangeErrorReferenceErrorSyntaxErrorTypeErrorURIError

Page 27: Know your errors

LOGGING

Page 28: Know your errors

GET VS POST

both methods work fine

get has the size of url limitation

you can truncate some data (case by case evaluation)

Page 29: Know your errors

IMAGE (GET)//assuming src was already calculatedvar img = new Image(1,1);img.onload = function() {};img.src = "/log?msg=error&url=http%3A%2F%2Flocalhost&lno=1";

Page 30: Know your errors

IFRAME (POST)var iframe = document.createElement('iframe');document.body.appendChild(iframe);var iframeDoc = iframe.contentDocument,content = '<form method="post" action="/log">\<input type="text" name="msg" value="Script Error">\<input type="text" name="url" value="http%3A%2F%2Flocalhost">\<input type="text" name="lno" value="1">\</form>';iframeDoc.open();iframeDoc.write(content);iframeDoc.close();iframeDoc.body.firstChild.submit();

Page 31: Know your errors

XHR (BOTH)var xhr = new XMLHttpRequest();//postxhr.open("POST",'/log');xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");xhr.send( payload );//getxhr.open("GET",'/log?' + qs);xhr.send();

Page 32: Know your errors

IF YOU WANT JUST A COUNTER

Google Analytics is also an option

_gaq.push([ '_trackEvent', 'jserror', url + ':' + lno, message || '']);

Page 33: Know your errors

STACKTRACE.JS<script src="path/to/stacktrace.js"></script>

<script>

</script>

//... your code ...

if (errorCondition) {

var trace = printStackTrace();

//Output however you want!

alert(trace.join('\n\n'));

}

//... more code of yours ...

Page 34: Know your errors

STACKTRACE.JSFirefox (and Iceweasel) 0.9+

Google Chrome 1+

Safari 3.0+ (including iOS 1+)

Opera 7+

IE 5.5+

Konqueror 3.5+

Flock 1.0+

SeaMonkey 1.0+

K-Meleon 1.5.3+

Epiphany 2.28.0+

Iceape 1.1+

Page 35: Know your errors

YOUR DASHBOARD

Page 36: Know your errors

NODEJS + REDIS

express

node_redis

npm install -g express

express dashboard_js

npm install redis

Page 37: Know your errors

EXPRESS//assuming a sample express app

var log = require('./routes/log');

app.get('/log', log.index);app.post('/log', log.index);app.get('/log_list', log.list);app.get('/log_chart', log.chart);

Page 38: Know your errors

THE ROUTERS

Page 39: Know your errors

exports.index = function (req, res) { var msg = req.param('msg', ''), url = req.param('url', ''), lno = req.param('lno', 0), js_error = msg + ':!:' + url + ':!:' + lno; minute = ((+new Date()/60000|0)*60000), data = [ 'jserrors', '' + minute, 1 ];

if(!msg) { res.send('', 400); }

redis_cli.hincrby( data, function(){} ); redis_cli.lpush( 'jserror_' + minute, js_error); res.send('', 202);};

Page 40: Know your errors

exports.list = function(req, res) {var to = (+new Date()/60000|0)*60000, from = to - 20 * 60000; inc = 60000, prefix = 'jserror_', result = {}, cb = function(res, i){. return function(err, reply){ var ret = []; reply.forEach(function(val, ind){ ret[ind] = val.split(':!:'); }); result[i] = ret; if(i === to) { res.json(result); } }; }; for(var i = from; i<=to; i+=inc) { redis_cli.lrange( [prefix+i,0,100], cb(res, i) ); }};

Page 41: Know your errors

exports.chart = function(req, res) { var to = (+new Date()/60000|0)*60000, inc = 60000, from = to - 20 * 60000, redis_param = ['jserrors'], ret = []; for(var i = from; i<=to; i+=inc) { redis_param.push(''+i); ret.push({d: new Date(i)}); } redis_cli.hmget( redis_param, function(err, reply){ reply.forEach(function(val, ind){ ret[ind].v = val || 0; }); res.json(ret); });};

Page 42: Know your errors

MISCELLANEOUS

jquery 2.0

twitter bootstrap

morris

Page 43: Know your errors

IN ACTION

Page 44: Know your errors

SERVICES OUT THERE

Page 45: Know your errors

Smart error groupingTeam collaborationEasiness of integrationUsers statistics

QBAKA

Page 46: Know your errors

Smart grouping of errorsWe don't rewrite your codeAutomatic ignoring of errorsFilter errors to your liking

{ERRORCEPTION}

Page 47: Know your errors

you can point it to your own serviceor use appspotmore a service than a SAAS

JSERRLOG

Page 48: Know your errors

Low overheadEmail digestShows the JavaScript code that caused the errorAutomatic cleanup

MUSCULA

Page 49: Know your errors

SINCE WE ALREADY LOGGING

Navigation Timing API

not available - Opera, Safari

Page 50: Know your errors

PROPERTIES

navigationStartunloadEventStartunloadEventEndredirectStartredirectEndfetchStartdomainLookupStartdomainLookupEndconnectStartconnectEnd

Page 51: Know your errors

PROPERTIES

secureConnectionStartrequestStartresponseStartresponseEnddomLoadingdomInteractivedomContentLoadedEventStartdomContentLoadedEventEnddomCompleteloadEventStartloadEventEnd

Page 52: Know your errors

VISUAL INDICATION

Page 53: Know your errors

FRONTEND SPOF

any 3rd party widgetcustom font downloadingeven your own JS can cause it...

Page 54: Know your errors

LOG EVERYTHING YOU CANEVERYWHERE

don't expect your users to report your errors

be aware, be prepared

Page 55: Know your errors

THANKS!

Diogo Antunes

Booking.com jobs

Page 56: Know your errors

Q&A

Page 57: Know your errors