Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Automatically report unhandled javascript exceptions to your server!
(function(exports) {
function nop() {}
// IE doesn't always have console, place a no-op shim for it.
if (!window.console) {
window.console = {log: nop, info: nop, warn: nop, error: nop};
}
// Transforms an Error to a simple object that can be JSONified.
function error_to_object(error) {
var newError = {message: error.message, url: error.fileName, lineNumber: error.lineNumber};
if (error.constructor && error.constructor.name)
newError.type = error.constructor.name;
// get anything missed. For some reason error.message doesn't show up in this pass.
for (var prop in error) {
if (!error.hasOwnProperty(prop)) continue;
var newProp;
if (prop == "fileName")
newProp = "url";
else
newProp = prop;
newError[newProp] = error[prop];
}
return newError;
}
exports.error_to_object = error_to_object;
var max_retry_time = 5*60*1000;
var logger_url = '/logger.php';
var no_send_before = 0;
var no_send_delay = 10;
var send_queued = 0;
var send_max_queued = 7;
function send_error(error, retry_time) {
if (typeof error === "string")
error = {message: error};
else if (error instanceof Error)
error = error_to_object(error);
if (!error.hasOwnProperty("message")) {
console.error("send_error called without error.message", error);
return;
}
error.pageurl = document.location.href;
var errorString = JSON.stringify(error);
var now = (new Date()).getTime();
if (now < no_send_before) {
if (send_queued < send_max_queued) {
send_queued++;
setTimeout(function() {
send_queued--;
send_error(error, retry_time);
}, no_send_before-now+10);
}
return;
}
if (!retry_time)
retry_time = 3*1000;
else if (retry_time > max_retry_time)
retry_time = max_retry_time;
no_send_before = now + no_send_delay;
no_send_delay *= 2;
if (no_send_delay > max_retry_time)
no_send_delay = max_retry_time;
$.ajax({
url: logger_url,
cache: false,
data: {type: "error", data: errorString},
type: 'POST',
success: function(data) {
console.log("sent javascript error report to server for review");
},
error: function(jqXHR, textStatus, errorThrown) {
if (textStatus == "timeout") {
console.log("timeout while trying to send error report, retrying soon");
setTimeout(function() {
send_error(error, retry_time*2);
}, retry_time);
} else {
console.error("could not send error report. textStatus: "+textStatus+", errorThrown: "+errorThrown);
}
}
});
}
exports.send_error = send_error;
var old_onerror = window.onerror;
window.onerror = function(errorMsg, url, lineNumber, column, errorObj) {
try {
if (errorObj !== undefined) {
send_error(errorObj);
} else {
var error = {message: errorMsg, url: url, lineNumber: lineNumber, column: column, caughtBy: "window.onerror"};
send_error(error);
}
if (old_onerror)
old_onerror.apply(this, arguments);
} catch(e) {
// Important. If we have an error in the automatic error reporter,
// we need to make sure we don't get in an infinite loop of trying
// to report it, triggering it again, and trying to report it again.
try {
send_error(e);
} catch(e) {}
}
return false;
};
})(window.reporter||(window.reporter={}));
@Morpho

This comment has been minimized.

Copy link

@Morpho Morpho commented Feb 12, 2014

Hi,
I tried your script. The idea is great, but unfortunately the script itself raises some errors:

{"message":"Converting circular structure to JSON","type":"circular_structure","stack":"TypeError: Converting circular structure to JSON\n at Object.stringify (native)\n at send_error (.../reporter.js:11:59)\n
User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.6; es-es; GT-I9070 Build/GINGERBREAD) App
leWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

{"message":"Cannot call method 'hasOwnProperty' of null","type":"TypeError", ... }
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.