Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Expect the unexpected

C3d3ad4d0758d38bf60f1a648bd0fe02?s=47 Mats Bryntse
February 07, 2017

Expect the unexpected

jFokus 2017

C3d3ad4d0758d38bf60f1a648bd0fe02?s=128

Mats Bryntse

February 07, 2017
Tweet

Transcript

  1. Mats Bryntse Founder, @bryntum Expect the Unexpected Dealing with errors

    in large web apps >>
  2. Who is Mats Bryntse? • From Lund, live in Stockholm

    • Working with javascript past 10 years • Founder of Bryntum • Scheduler, Gantt & Kanban UI components • Testing tools, logging tools • @bryntum • www.bryntum.com !
  3. Error handling 101

  4. Javascript error basics • Javascript errors are unhandled exceptions in

    your code base • Or in the frameworks you use • Doesn’t matter where errors happen, poor user impression • With JS codebases in the size of MBs, cannot ignore error handling + logging • Good news - it’s easy
  5. When a web site error happens, you as a dev

    see…
  6. What does the user see when there is a JS

    error?
  7. Nothing

  8. None
  9. Two scenarios for the end user: • Error is captured

    by you. User notified • Or…… • Nothing happens for user, will probably try same action again. • If you’re lucky, user will contact you ✉ ✊
  10. Live demo of an error

  11. What is a javascript Error?

  12. The ErrorEvent constructor • When an error happens, an ´error´

    event is fired on the window object • ErrorEvent.message • ErrorEvent.filename • ErrorEvent.lineno • ErrorEvent.colno // Normal browsers only • ErrorEvent.error // Contains stack. Normal browsers only
  13. Global error handler // Old school window.onerror = function(msg, url,

    line, col, error) { … }; window.addEventListener(‘error’, function(event) { // event.message // event.filename // event.lineno // event.colno // good browsers only // event.error (has ´stack´) }, true); …or by listening to the window ‘error’ event. Listen with capture=true to also get notified of resource load errors Errors are easily caught in window.onerror
  14. You can throw your own Errors too // Bad, no

    call stack will be available throw ‘My own error’; // preferred throw new Error(‘This will have a call stack’); try { // Code written after drinking beer goes here } catch(e) { // Oops, log error } finally { // always called } • throw a String • Or better, an Error instance (=> callstack) • try/catch/finally
  15. Script error. • For errors originating in foreign origin scripts

    • No stack, no line, no col, no error message. Nothing. Nada. Inget. • Solution - add a crossOrigin attribute to external script tags • And add a CORS header: Access-Control-Allow-Origin: * <script src=“https://other.io/file.js” crossOrigin="anonymous"></script>
 <script>
 window.onerror = function (message, url, line, column, error) {
 console.log(message); // Script error if you forget crossOrigin.
 }
 </script>
  16. The bug fix process

  17. Bug life cycle Fix Occurrence ℹ Investigate Reproduce Report ✅

  18. Developers need to be “in context” to fix a bug

  19. Debug context wish list 1. Error message 2. File /

    line number 3. Call stack 4. Screenshot 5. Step by step description 6. Log of user / browser session activity 7. Seeing the user reproduce the error 8. Live breakpoint in production environment 9. Live breakpoint on my localhost, in my fav browser
  20. Once you have breakpoint, it’s all downhill!

  21. Error at Object.module.exports.request (/home/vagrant/src/kumascript/lib/kumascript/caching.js:366:17) at attempt (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:180:24) at ks_utils.Class.get (/home/vagrant/src/kumascript/lib/kumascript/loaders.js:194:9)

    at /home/vagrant/src/kumascript/lib/kumascript/macros.js:282:24 at /home/vagrant/src/kumascript/node_modules/async/lib/async.js:118:13 at Array.forEach (native) at _each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:39:24) at Object.async.each (/home/vagrant/src/kumascript/node_modules/async/lib/async.js:117:9) at ks_utils.Class.reloadTemplates (/home/vagrant/src/kumascript/lib/kumascript/macros.js:281:19) at ks_utils.Class.process (/home/vagrant/src/kumascript/lib/kumascript/macros.js:217:15) “A live breakpoint is worth a 1000 callstacks”
  22. Error handling strategies

  23. • Pros: Cheap • Cons: Bugs live forever Do nothing

  24. Email ping pong

  25. Email ping pong - Enterprise version Error in web app

    Reports to own support Your company User realises it’s an error 01010 10110 11110 User Dear User, /Depressed dev. Can’t reproduce, need more info. Sincerely yours,
  26. • Pros: None • Cons: Slow, expensive, demoralizing, frustrated end

    user
  27. Roll your own logger

  28. Roll your own logger • Pros: Simple, get basic error

    info. Awareness • Cons: Lots of code to scan through
  29. Using a 3rd party logger • Pros: Tons of data,

    call stack, console logs, ajax, user activity. Enables you to search for the error • Cons: Lots of data to parse, manual code review
  30. Quick poll

  31. Roll your own error logger in < 10 minutes

  32. 1. Create single table db • date, message, file, line,

    callstack etc CREATE TABLE `error` ( `msg` char(60), `callstack` char(1000), … ) ENGINE=InnoDB DEFAULT CHARSET=utf8
  33. 2. PHP script to receive error data and store it

    in DB <?php // LOG TO DB
 $link = getLink();
 
 $command = "call insert_error('$msg', ‘$url', ‘$stack’, …); 
 $result = mysqli_query($link, $command);
 

  34. 3. Setup client side logging • Log message, file, line,

    stack etc.. • Add any extra meta relevant for your debugging (userId/name/…) // Poor mans error logger window.onerror = function log(msg) { new Image().src = "log.php?msg=" + encodeURIComponent(msg); } throw new Error("Ooops");
  35. Manual error logging, things to consider • Store error logs

    in a database on a non-production server • Throttle logging on client side + server side • Probably we only care about the first error on a page
  36. Evolution of tools - plenty of choice

  37. First generation tools • Sentry, Rollbar, TrackJS, RayGun, NewRelic, StackHunter…

    • Basic error logging • Call stack + context • Timeline • Dashboard • Statistics • Focus on raising awareness, data gathering
  38. None
  39. Second generation tools • Generate video • Manual video recording

    / feedback collection • Replay & view the error • Focus on reproducing, not data gathering
  40. • Generates video recording of session (via DOM MutationObserver) •

    Replay to view the error • Focus on showing you the bug
  41. • Record and Replay state for Redux apps • Session

    video • Focus on reproducing the bug
  42. • DOM / ajax / event recorder • Replay Studio

    - reproduce the bug live in the browser • Screenshot at time of crash, last user action embedded • Focus on reproducing the bug
  43. Summing up: • Fix your external script tags. Never see

    “Script error”. Ever. • Don’t rely on users reporting bugs • Automate your error reporting
  44. Breakpoint or GTFO @bryntum Questions? @the_rootcause BETA open at http://app.therootcause.io

    (invite code jfokus)