Know your errors

  • 1,004 views
Uploaded 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, …

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

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,004
On Slideshare
0
From Embeds
0
Number of Embeds
4

Actions

Shares
Downloads
13
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

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