SenchaCon 2016: Building Enterprise Ext JS Apps with Mavenized Sencha Cmd - Frank Wienberg
SenchaCon 2016: Expect the Unexpected - Dealing with Errors in Web Apps
-
Upload
sencha -
Category
Technology
-
view
123 -
download
0
Transcript of SenchaCon 2016: Expect the Unexpected - Dealing with Errors in Web Apps
Expect the unexpected - dealing with errors in web apps
Mats Bryntse
Founder, @bryntum
Who is Mats Bryntse?
• From Stockholm, Sweden
• Working with Ext JS since 2007
• mankz in the Sencha forums
• Founder of Bryntum (Scheduler, Gantt, Kanban Taskboard, Siesta)
• @bryntum
What is a javascript Error?
Javascript error basics
• Javascript errors are unhandled exceptions happening in your code base
• Or in the frameworks you use
• Doesn’t matter where it happens, poor user impression regardless
• With JS codebases in the size of MBs, we can no longer ignore error handling + logging
• Good news - it’s easy 😀
What does the user see when there is a JS error?
🤔
Nothing, unless you show them
😳
The ErrorEvent constructor
• When an error happens, an ErrorEvent is fired on the window object
• ErrorEvent.message
• ErrorEvent.filename
• ErrorEvent.lineno
• ErrorEvent.colno // Normal browsers only
• ErrorEvent.error // Normal browsers only
Global error handler
// Old schoolwindow.onerror = function(message, source, lineno, colno, error) { … };
window.addEventListener(‘error’, function(event) { // event.message // event.filename // event.lineno // event.colno // good browsers only // event.error (has stack property, in good browsers)}, true);
…or by listening to the window ‘error’ eventListen with capture=true to also get notified of resource load errors
Errors are easily caught in window.onerror
You can throw your own Error too
// Bad, no call stack will be availablethrow ‘My own error’;
// preferredthrow new Error(‘This will have call stack’);
try { // Questionable code goes here} catch(e) { // log error} finally { // always called}
• throw a String
• Or better, an Error instance (callstack)
• Catch using simple try/catch/finally
The error reporting cycle
What’s the typical strategy for error reporting at Enterprise X?
Flow of an error - Enterprise version
Error in web app
Reports to own support Your company
User realises it’s an error
010101011011110
User Dear User,
/Depressed dev.
Can’t reproduce, need more info.
Sincerely yours,
Too much guessing…
🕵🏼
10 points
“Add-to-cart button doesn’t work”
9 points ‘a is undefined’
9 points ‘console.lgo is not a function’
8 points line 1, column 536171
7 points
6 points
5 points Step by step:First login as userAdd few items to cartClick checkout button => crash
Logging and monitoring errors in your web app
Logging is easy
• Log message, file, line, stack etc..
• Add any extra meta relevant for your debugging (userId/name/…)
• Poor mans error logger:
function log(msg) { new Image().src = "log.php?msg=" + encodeURIComponent(msg);}
window.onerror = log;
throw new Error("Ooops");
Saving error info
• Store error logs in some database on a non-production server
• Throttle logging on client side + server side
• Probably we only care about the first error on a page
Flow of an error - Improved version
Error in web app
Your company
User realises it’s an error
010101011011110
User
Making sense of a callstack is sometimes easy…
…but often it takes a lot of detective work
🕵🏼
Solving a complex puzzleConnecting the dots…
undefined is not a function
Bryntum - How we (used to) handle errors
Online examples is a test suite of sorts
Previous error handling at Bryntum
• Web site visitors are test monkeys unknowingly === free help• Errors logged in a DB
• Emails sent to devs
= Very useful for finding and rapidly fixing bugs
Error handling at Bryntum
Instant feedback
Site visitors / “Late QA”Developers
Error handling at Bryntum
• What we had was pretty good, not great
• Lots of time spent playing detective, looking at callstacks
• Just error message, filename, callstack isn’t enough to rapidly locate root cause
• We would like to know more…
🕵🏼
Wish list…
Function arguments
Know how the crashing function was called
function getUserInfo(id) { var user = this.store.getById(id); // => null
return user.getInfo(); // Cannot call getInfo of null }
getUserInfo(-1); // crashes, would be neat to know input args
Logs about failed ajax requests
Usually produces errors that are less tested (aka happy testing)
See how the application looked at the time of crash
?
Know what the user did during page session
🎥
What if there was a tool that did all this…?
🤔😀
Introducing the new shiny…
Detailed data about users environment
Capturing arguments passed to the crashing function
Screenshot at the time of the error
Support for hiding sensitive data before screenshot
+ environment data collectedMany things to consider…
• OS
• Browser
• Window size
• Touch support
• Window blur/focus events
• Date + Timezone
• Language
• Failed ajax requests
• Cookie state
• Network connectivity events
Timeline visualising activityShows ajax requests, window resizing, hide/show, connectivity
Notifying the developers
Notifying the affected user
• Optional popup for the user that triggered the error
• Shows status of the error (New, Reproduced, Fixed)
Two way communication
Error data posted
Current error status [new/reproduced/fixed]
Users / QADevelopers
Cuts 99% of communication out
• No need for QA to email devs about crash reports
• No need for devs to notify QA that bug is already fixed
DEMO TIME
Installing the logger in your app
var logger = new Err.ErrorLogger({ recordUserActions : true, maxNbrLogs : 1, logResourceLoadFailures : true, applicationId : ‘your-cool-app‘, version : ‘2.0.0-rc.1’, logAjaxRequests : true, enableScreenshot : true, saveCookies : true, frameworkVersion : Ext.versions.extjs.version });
logger.addTag('ReadOnlyUser', true); logger.addTag('Secret Flag', 'XYZ');
In a dream world we would be able to:
See on the user’s machine when error happens live Reproduce the error on in production Reproduce the error locally
🤔
DEMO TIME
Questions?