A Journey into
Client Side Errors
Arunoda Susiripala
MeteorHacks
Kadira.io
Overview
How we debug errors locally
(Dev Mode)
How we can track errors in Production
Some Better Options
Our Demo App
Code
Template.simple.events({
"click button": function() {
fetchFromServer("getSomeTweets", displayTweets);
}
});
function displayTweets(err, date) {
console.log(data.tweets);
}
Let's Debug Our Error
Async Errors
Template.without_async.events({
"click button": function() {
throw new Error("oops. something went wrong");
}
});
Template.with_async.events({
"click button": function() {
setTimeout(function() {
throw new Error("oops. something went wrong");
}, 100);
}
});
Minified Code
Source Maps
Our App in Production
On Users Browser
We can't Debug It
User is your Grandma
(Code is not minified yet)
function ReportError(type, data) {
console.log("A new Error of type: " + type);
console.log(data);
}
window.onerror
Code
Template.window_onerror.events({
"click button": function() {
fetchFromServer("getSomeTweets", displayTweets);
}
});
function displayTweets(err, date) {
console.log(data.tweets);
}
window.onerror = function() {
ReportError("window.onerror", arguments);
};
Result: Chrome
Result: Firefox
Result: Safari
Tracking Error Manually
Template.trycatch1.events({
"click button": function() {
try {
throw new Error("oops. something went wrong");
} catch(ex) {
ReportError("trycatch1", ex);
}
}
});
Template.trycatch2.events({
"click button": function() {
try {
setTimeout(function() {
throw new Error("oops. something went wrong");
}, 100);
} catch(ex) {
ReportError("trycatch2", ex);
}
}
});
Different StackTrace Formats
Result: Chrome
Result: FireFox
Result: IE
Result: Safari
Solution
No Async Stacks
Issues
window.onerror is limited
tracking errors manually is hard
no async stacks
Enter: Zone.JS
It's a Execution Context
Zone.JS Demo Time
var reporter = {
onError: function(ex) {
console.log(ex);
}
};
zone.fork(reporter).run(function() {
throw new Error('oops something goes wrong');
});
Async Errors
var reporter = {
onError: function(ex) {
console.log(ex);
}
};
zone.fork(reporter).run(function() {
setTimeout(function() {
throw new Error('oops something goes wrong inside setTimeout');
}, 1000);
});
Long StackTraces
zone.fork(Zone.longStackTraceZone);
Template.with_async.events({
"click button": function() {
setTimeout(function() {
throw new Error("oops. something went wrong");
}, 100);
}
});
Zone.JS with Minified Code
zone.fork(Zone.longStackTraceZone);
Template.with_async.events({
"click button": function() {
setTimeout(function() {
throw new Error("oops. something went wrong");
}, 100);
}
});
Let's Think Differently!
To Fix an Error?
We need context
Set of Actions Occured
Error Message
How We Did It?
Extending Zones
var originalMeteorCall = Meteor.call;
Meteor.call = function(methodName) {
var args = Array.prototype.slice.call(arguments, 1);
zone.addAction("Meteor.call", {
method: methodName,
args: args
}};
originalMeteorCall.apply(this, arguments);
}
Nothing is Free
try {
this.beforeTask();
result = fn.apply(applyTo, applyWith);
} catch (e) {
if (zone.onError) {
zone.onError(e);
} else {
throw e;
}
} finally {
this.afterTask();
window.zone = oldZone;
}
Thank You!
A Tour on Client Side Errors
By arunoda
A Tour on Client Side Errors
- 1,842