Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
KNOW YOUR ERRORSBECAUSE ITS A JUNGLE OUT THERE
WHO AM I?Diogo AntunesBooking.comSenior Client Side Developer@dicode
OVERVIEWlogging JS errorsproof of concepttools/services
SO WHY LOG JS ERRORS IF?
YOU DO TDD
YOU DO SELENIUM TESTS
YOU DO HEADLESS BROWSER TESTING
YOU HAVE A TESTING TEAM
IT WORKS ON MY MACHINE
ITS A JUNGLE OUT THERE!
3RD PARTY SCRIPTS THAT YOU DONT CONTROLTwitter, Facebook, GA
YOU USE A CDNeven if it is just to load jquery
USERS INSTALL PLUGINS
YOUR MARKETING DEPARTMENT LIKES TRACKING PIXELS
YES, SOME THINGS YOU CANNOT CONTROLbut some of them you can mitigate
SOME CHALLENGES
LOCALIZED MESSAGESExpected identifier, string or numberIdentificador esperadoSe esperaba un identificador, una cadena o un...
LINE NUMBERminify jsusing gzip and preserving new lines may be a temporary solution
CRYPTIC MESSAGEScannot find method of undefinedScript error.cross origin domain policyChrome and FirefoxAccess-Control-All...
BE SAFEdeploy environment vars that disable 3rd party codeif possible, without making any deploy to livethat way you can t...
LETS DO SOME LOGGING
APPROACHES
WINDOW.ONERRORworks across the boardamount of information is limitedwindow.onerror = function(msg, url, lno){/*No impact b...
TRY/CATCHworks across the boardtry {throw new Error("my error");} catch (e){e.stack; //chrome, firefoxe.message; //operalo...
TRY/CATCHmore meaningful errorsperformance hit, but you should evaluate if it mattersmay lead to a lot of nesting if not t...
TYPES OF EXCEPTIONSErrorEvalErrorRangeErrorReferenceErrorSyntaxErrorTypeErrorURIError
LOGGING
GET VS POSTboth methods work fineget has the size of url limitationyou can truncate some data (case by case evaluation)
IMAGE (GET)//assuming src was already calculatedvar img = new Image(1,1);img.onload = function() {};img.src = "/log?msg=er...
IFRAME (POST)var iframe = document.createElement(iframe);document.body.appendChild(iframe);var iframeDoc = iframe.contentD...
XHR (BOTH)var xhr = new XMLHttpRequest();//postxhr.open("POST",/log);xhr.setRequestHeader("Content-type", "application/x-w...
IF YOU WANT JUST A COUNTERGoogle Analytics is also an option_gaq.push([_trackEvent,jserror,url + : + lno,message || ]);
STACKTRACE.JS<script src="path/to/stacktrace.js"></script><script></script>//... your code ...if (errorCondition) {var tra...
STACKTRACE.JSFirefox (and Iceweasel) 0.9+Google Chrome 1+Safari 3.0+ (including iOS 1+)Opera 7+IE 5.5+Konqueror 3.5+Flock ...
YOUR DASHBOARD
NODEJS + REDISexpressnode_redisnpm install -g expressexpress dashboard_jsnpm install redis
EXPRESS//assuming a sample express appvar log = require(./routes/log);app.get(/log, log.index);app.post(/log, log.index);a...
THE ROUTERS
exports.index = function (req, res) {var msg = req.param(msg, ),url = req.param(url, ),lno = req.param(lno, 0),js_error = ...
exports.list = function(req, res) {var to = (+new Date()/60000|0)*60000,from = to - 20 * 60000;inc = 60000,prefix = jserro...
exports.chart = function(req, res) {var to = (+new Date()/60000|0)*60000, inc = 60000,from = to - 20 * 60000,redis_param =...
MISCELLANEOUSjquery 2.0twitter bootstrapmorris
IN ACTION
SERVICES OUT THERE
Smart error groupingTeam collaborationEasiness of integrationUsers statisticsQBAKA
Smart grouping of errorsWe dont rewrite your codeAutomatic ignoring of errorsFilter errors to your liking{ERRORCEPTION}
you can point it to your own serviceor use appspotmore a service than a SAASJSERRLOG
Low overheadEmail digestShows the JavaScript code that caused the errorAutomatic cleanupMUSCULA
SINCE WE ALREADY LOGGINGNavigation Timing APInot available - Opera, Safari
PROPERTIESnavigationStartunloadEventStartunloadEventEndredirectStartredirectEndfetchStartdomainLookupStartdomainLookupEndc...
PROPERTIESsecureConnectionStartrequestStartresponseStartresponseEnddomLoadingdomInteractivedomContentLoadedEventStartdomCo...
VISUAL INDICATION
FRONTEND SPOFany 3rd party widgetcustom font downloadingeven your own JS can cause it...
LOG EVERYTHING YOU CANEVERYWHEREdont expect your users to report your errorsbe aware, be prepared
THANKS!Diogo AntunesBooking.com jobs
Q&A
Know your errors
Upcoming SlideShare
Loading in …5
×

Know your errors

1,979 views

Published on

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

Published in: Technology
  • Be the first to comment

Know your errors

  1. 1. KNOW YOUR ERRORSBECAUSE ITS A JUNGLE OUT THERE
  2. 2. WHO AM I?Diogo AntunesBooking.comSenior Client Side Developer@dicode
  3. 3. OVERVIEWlogging JS errorsproof of concepttools/services
  4. 4. SO WHY LOG JS ERRORS IF?
  5. 5. YOU DO TDD
  6. 6. YOU DO SELENIUM TESTS
  7. 7. YOU DO HEADLESS BROWSER TESTING
  8. 8. YOU HAVE A TESTING TEAM
  9. 9. IT WORKS ON MY MACHINE
  10. 10. ITS A JUNGLE OUT THERE!
  11. 11. 3RD PARTY SCRIPTS THAT YOU DONT CONTROLTwitter, Facebook, GA
  12. 12. YOU USE A CDNeven if it is just to load jquery
  13. 13. USERS INSTALL PLUGINS
  14. 14. YOUR MARKETING DEPARTMENT LIKES TRACKING PIXELS
  15. 15. YES, SOME THINGS YOU CANNOT CONTROLbut some of them you can mitigate
  16. 16. SOME CHALLENGES
  17. 17. LOCALIZED MESSAGESExpected identifier, string or numberIdentificador esperadoSe esperaba un identificador, una cadena o un númeroBezeichner erwartet标识‫ّف‬ ‫د‬ ‫و‬ ‫ا‬
  18. 18. LINE NUMBERminify jsusing gzip and preserving new lines may be a temporary solution
  19. 19. CRYPTIC MESSAGEScannot find method of undefinedScript error.cross origin domain policyChrome and FirefoxAccess-Control-Allow-Origin: *
  20. 20. BE SAFEdeploy environment vars that disable 3rd party codeif possible, without making any deploy to livethat way you can take action quickly
  21. 21. LETS DO SOME LOGGING
  22. 22. APPROACHES
  23. 23. WINDOW.ONERRORworks across the boardamount of information is limitedwindow.onerror = function(msg, url, lno){/*No impact besides parsingoverhead is only for the request to log the errorwhen one actually happens*/return true; //hides the message in supported browsers};
  24. 24. TRY/CATCHworks across the boardtry {throw new Error("my error");} catch (e){e.stack; //chrome, firefoxe.message; //operalog(e.stack || e.message || e);}
  25. 25. TRY/CATCHmore meaningful errorsperformance hit, but you should evaluate if it mattersmay lead to a lot of nesting if not thought throughvar fn = function(){throw "new error"; //this exception will not be caught//since its a string it will not have stack trace};try{setTimeout(fn,0);} catch(e) { }
  26. 26. TYPES OF EXCEPTIONSErrorEvalErrorRangeErrorReferenceErrorSyntaxErrorTypeErrorURIError
  27. 27. LOGGING
  28. 28. GET VS POSTboth methods work fineget has the size of url limitationyou can truncate some data (case by case evaluation)
  29. 29. 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";
  30. 30. 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();
  31. 31. 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();
  32. 32. IF YOU WANT JUST A COUNTERGoogle Analytics is also an option_gaq.push([_trackEvent,jserror,url + : + lno,message || ]);
  33. 33. 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(nn));}//... more code of yours ...
  34. 34. 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+
  35. 35. YOUR DASHBOARD
  36. 36. NODEJS + REDISexpressnode_redisnpm install -g expressexpress dashboard_jsnpm install redis
  37. 37. EXPRESS//assuming a sample express appvar 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);
  38. 38. THE ROUTERS
  39. 39. 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);};
  40. 40. 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) );}};
  41. 41. 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);});};
  42. 42. MISCELLANEOUSjquery 2.0twitter bootstrapmorris
  43. 43. IN ACTION
  44. 44. SERVICES OUT THERE
  45. 45. Smart error groupingTeam collaborationEasiness of integrationUsers statisticsQBAKA
  46. 46. Smart grouping of errorsWe dont rewrite your codeAutomatic ignoring of errorsFilter errors to your liking{ERRORCEPTION}
  47. 47. you can point it to your own serviceor use appspotmore a service than a SAASJSERRLOG
  48. 48. Low overheadEmail digestShows the JavaScript code that caused the errorAutomatic cleanupMUSCULA
  49. 49. SINCE WE ALREADY LOGGINGNavigation Timing APInot available - Opera, Safari
  50. 50. PROPERTIESnavigationStartunloadEventStartunloadEventEndredirectStartredirectEndfetchStartdomainLookupStartdomainLookupEndconnectStartconnectEnd
  51. 51. PROPERTIESsecureConnectionStartrequestStartresponseStartresponseEnddomLoadingdomInteractivedomContentLoadedEventStartdomContentLoadedEventEnddomCompleteloadEventStartloadEventEnd
  52. 52. VISUAL INDICATION
  53. 53. FRONTEND SPOFany 3rd party widgetcustom font downloadingeven your own JS can cause it...
  54. 54. LOG EVERYTHING YOU CANEVERYWHEREdont expect your users to report your errorsbe aware, be prepared
  55. 55. THANKS!Diogo AntunesBooking.com jobs
  56. 56. Q&A

×