Skip to content

Commit

Permalink
Merge pull request #34 from MindscapeHQ/offline-localstorage-caching
Browse files Browse the repository at this point in the history
Offline localstorage caching
  • Loading branch information
fundead committed Apr 1, 2014
2 parents ddf2937 + 929a72d commit 6fcf7f0
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 33 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,27 @@ This will allow you to filter the errors in the dashboard by that version. You c
### Source maps support
Raygun4JS now features source maps support through the transmission of column numbers for errors, where available. As at March 2014, this is confirmed to work in recent version of Chrome, Safari and Opera, and IE 10 and 11. See the Raygun dashboard or documentation for more information.
Raygun4JS now features source maps support through the transmission of column numbers for errors, where available. This is confirmed to work in recent version of Chrome, Safari and Opera, and IE 10 and 11. See the Raygun dashboard or documentation for more information.
### Offline saving
The provider has a feature where if errors are caught when there is no network activity they can be saved (in Local Storage). When an error arrives and connectivity is regained, previously saved errors are then sent. This is useful in environments like WinJS, where a mobile device's internet connection is not constant.
#### Options
Offline saving is **disabled by default.** To get or set this option, call the following after your init() call:
```js
Raygun.saveIfOffline(boolean)
```
If an error is caught and no network connectivity is available (the Raygun API cannot be reached), or if the request times out after 10s, the error will be saved to LocalStorage. This is confirmed to work on Chrome, Firefox, IE10/11, Opera and WinJS.
Limited support is available for IE 8 and 9 - errors will only be saved if the request times out.
## Release History
- 1.8.0 - Add Offline Saving feature; add support for WinJS
- 1.7.2 - Fixed tags not being included when error caught from global window.onerror handler
- 1.7.1 - Fixed broken withTags when no other custom data provided on Send
- 1.7.0 - Added source maps support by transmitting column numbers (from supported browsers)
Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "raygun4js",
"version": "1.7.2",
"version": "1.8.0",
"homepage": "http://raygun.io",
"authors": [
"Mindscape <[email protected]>"
Expand Down
111 changes: 98 additions & 13 deletions dist/raygun.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! Raygun4js - v1.7.2 - 2014-03-06
/*! Raygun4js - v1.8.0 - 2014-04-02
* https://github.com/MindscapeHQ/raygun4js
* Copyright (c) 2014 MindscapeHQ; Licensed MIT */
;(function(window, undefined) {
Expand Down Expand Up @@ -183,7 +183,7 @@ TraceKit.report = (function reportModuleWrapper() {
};
}
}

notifyHandlers(stack, 'from window.onerror');

if (_oldOnerrorHandler) {
Expand Down Expand Up @@ -604,6 +604,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
/**
* Computes stack trace information from the stack property.
* Chrome and Gecko use this property.
* Added WinJS regex for Raygun4JS's offline caching support
* @param {Error} ex
* @return {?Object.<string, *>} Stack trace information.
*/
Expand All @@ -614,6 +615,7 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {

var chrome = /^\s*at (?:((?:\[object object\])?\S+) )?\(?((?:file|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
gecko = /^\s*(\S*)(?:\((.*?)\))?@((?:file|http|https).*?):(\d+)(?::(\d+))?\s*$/i,
winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:ms-appx|http|https):.*?):(\d+)(?::(\d+))?\)?\s*$/i,
lines = ex.stack.split('\n'),
stack = [],
parts,
Expand All @@ -636,6 +638,13 @@ TraceKit.computeStackTrace = (function computeStackTraceWrapper() {
'line': +parts[3],
'column': parts[4] ? +parts[4] : null
};
} else if ((parts = winjs.exec(lines[i]))) {
element = {
'url': parts[2],
'func': parts[1] || UNKNOWN_FUNCTION,
'line': +parts[3],
'column': parts[4] ? +parts[4] : null
};
} else {
continue;
}
Expand Down Expand Up @@ -1239,10 +1248,12 @@ window.TraceKit = TraceKit;
_raygunApiKey,
_debugMode = false,
_allowInsecureSubmissions = false,
_enableOfflineSave = false,
_customData = {},
_tags = [],
_user,
_version,
_raygunApiUrl = 'https://api.raygun.io',
$document;

if ($) {
Expand Down Expand Up @@ -1270,6 +1281,8 @@ window.TraceKit = TraceKit;
}
}

sendSavedErrors();

return Raygun;
},

Expand Down Expand Up @@ -1323,6 +1336,14 @@ window.TraceKit = TraceKit;

setVersion: function (version) {
_version = version;
return Raygun;
},

saveIfOffline: function (enableOffline) {
if (typeof enableOffline !== 'undefined' && typeof enableOffline === 'boolean') {
_enableOfflineSave = enableOffline;
}

return Raygun;
}
};
Expand Down Expand Up @@ -1382,6 +1403,10 @@ window.TraceKit = TraceKit;
return true;
}

function getRandomInt() {
return Math.floor(Math.random() * 9007199254740993);
}

function getViewPort() {
var e = document.documentElement,
g = document.getElementsByTagName('body')[0],
Expand All @@ -1390,6 +1415,30 @@ window.TraceKit = TraceKit;
return { width: x, height: y };
}

function offlineSave (data) {
var dateTime = new Date().toJSON();

try {
var key = 'raygunjs=' + dateTime + '=' + getRandomInt();

if (typeof localStorage[key] === 'undefined') {
localStorage[key] = data;
}
} catch (e) {
log('Raygun4JS: LocalStorage full, cannot save exception');
}
}

function sendSavedErrors() {
for (var key in localStorage) {
if (key.substring(0, 9) === 'raygunjs=') {
sendToRaygun(JSON.parse(localStorage[key]));

localStorage.removeItem(key);
}
}
}

function processUnhandledException(stackTrace, options) {
var stack = [],
qs = {};
Expand Down Expand Up @@ -1453,7 +1502,7 @@ window.TraceKit = TraceKit;
},
'Client': {
'Name': 'raygun-js',
'Version': '1.7.2'
'Version': '1.8.0'
},
'UserCustomData': options.customData,
'Tags': options.tags,
Expand All @@ -1473,16 +1522,18 @@ window.TraceKit = TraceKit;
if (_user) {
payload.Details.User = _user;
}

sendToRaygun(payload);
}

function sendToRaygun(data) {
if (!isApiKeyConfigured()) {
return;
}

log('Sending exception data to Raygun:', data);
var url = 'https://api.raygun.io/entries?apikey=' + encodeURIComponent(_raygunApiKey);
makeCorsRequest(url, JSON.stringify(data));
var url = _raygunApiUrl + '/entries?apikey=' + encodeURIComponent(_raygunApiKey);
makePostCorsRequest(url, JSON.stringify(data));
}

// Create the XHR object.
Expand All @@ -1493,6 +1544,7 @@ window.TraceKit = TraceKit;
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);

} else if (window.XDomainRequest) {
// XDomainRequest for IE.
if (_allowInsecureSubmissions) {
Expand All @@ -1501,23 +1553,56 @@ window.TraceKit = TraceKit;
// on http
url = url.slice(6);
}

xhr = new window.XDomainRequest();
xhr.open(method, url);
}

xhr.onload = function () {
log('logged error to Raygun');
};
xhr.onerror = function () {
log('failed to log error to Raygun');
};
xhr.timeout = 10000;

return xhr;
}

// Make the actual CORS request.
function makeCorsRequest(url, data) {
var xhr = createCORSRequest('POST', url);
function makePostCorsRequest(url, data) {
var xhr = createCORSRequest('POST', url, data);

if ('withCredentials' in xhr) {

xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) {
return;
}

if (xhr.status === 202) {
sendSavedErrors();
} else if (_enableOfflineSave && xhr.status !== 403 && xhr.status !== 400) {
offlineSave(data);
}
};

xhr.onload = function () {
log('logged error to Raygun');
};

} else if (window.XDomainRequest) {
xhr.ontimeout = function () {
if (_enableOfflineSave) {
log('Raygun: saved error locally');
offlineSave(data);
}
};

xhr.onload = function () {
log('logged error to Raygun');
sendSavedErrors();
};
}

xhr.onerror = function () {
log('failed to log error to Raygun');
};

if (!xhr) {
log('CORS not supported');
return;
Expand Down
Loading

0 comments on commit 6fcf7f0

Please sign in to comment.