Created
October 17, 2017 23:10
-
-
Save rgoldfinger/e945c7cf949ceb5e6506659a8cd35d0e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -------------------------------------------------- | |
// rollbar.ejs | |
// -------------------------------------------------- | |
<%_ if (!__DEV__ && !__FUNCTIONAL__) { _%> | |
<script> | |
var _rollbarConfig = { | |
accessToken: "37c613c5a8b34fba89cd4fcfebc76808", | |
captureUncaught: true, | |
captureUnhandledRejections: true, | |
reportLevel: 'error', | |
payload: { | |
environment: '<%= ROLLBAR_ENVIRONMENT %>', | |
release: '<%= VERSION %>', | |
client: { | |
javascript: { | |
source_map_enabled: true, | |
guess_uncaught_frames: true, | |
code_version: '<%= COMMIT_SHA %>', | |
} | |
}, | |
}, | |
transform: function(payload) { | |
if (window._rolbarTransform) { | |
console.warn('initial transform sending to window._rolbarTransform'); | |
window._rolbarTransform(payload); | |
} else { | |
console.warn('initial transform called without window._rolbarTransform'); | |
} | |
}, | |
checkIgnore: function(isUncaught, args, payload) { | |
if (window._rollbarCheckIgnore) { | |
console.warn('initial checkIgnore sending to window._rollbarCheckIgnore'); | |
return window._rollbarCheckIgnore(isUncaught, args, payload); | |
} else { | |
console.warn('initial transform called without window._rollbarCheckIgnore'); | |
return false; | |
} | |
}, | |
}; | |
// Rollbar Snippet | |
!function(r){function o(n){if(e[n])return e[n].exports;var t=e[n]={exports:{},id:n,loaded:!1};return r[n].call(t.exports,t,t.exports,o),t.loaded=!0,t.exports}var e={};return o.m=r,o.c=e,o.p="",o(0)}([function(r,o,e){"use strict";var n=e(1),t=e(4);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://cdnjs.cloudflare.com/ajax/libs/rollbar.js/2.2.9/rollbar.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,o,e){"use strict";function n(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}function t(r,o){this.options=r,this._rollbarOldOnError=null;var e=s++;this.shimId=function(){return e},window&&window._rollbarShims&&(window._rollbarShims[e]={handler:o,messages:[]})}function a(r,o){var e=o.globalAlias||"Rollbar";if("object"==typeof r[e])return r[e];r._rollbarShims={},r._rollbarWrappedError=null;var t=new p(o);return n(function(){o.captureUncaught&&(t._rollbarOldOnError=r.onerror,i.captureUncaughtExceptions(r,t,!0),i.wrapGlobals(r,t,!0)),o.captureUnhandledRejections&&i.captureUnhandledRejections(r,t,!0);var n=o.autoInstrument;return o.enabled!==!1&&(void 0===n||n===!0||"object"==typeof n&&n.network)&&r.addEventListener&&(r.addEventListener("load",t.captureLoad.bind(t)),r.addEventListener("DOMContentLoaded",t.captureDomContentLoaded.bind(t))),r[e]=t,t})()}function l(r){return n(function(){var o=this,e=Array.prototype.slice.call(arguments,0),n={shim:o,method:r,args:e,ts:new Date};window._rollbarShims[this.shimId()].messages.push(n)})}var i=e(2),s=0,d=e(3),c=function(r,o){return new t(r,o)},p=d.bind(null,c);t.prototype.loadFull=function(r,o,e,t,a){var l=function(){var o;if(void 0===r._rollbarDidLoad){o=new Error("rollbar.js did not load");for(var e,n,t,l,i=0;e=r._rollbarShims[i++];)for(e=e.messages||[];n=e.shift();)for(t=n.args||[],i=0;i<t.length;++i)if(l=t[i],"function"==typeof l){l(o);break}}"function"==typeof a&&a(o)},i=!1,s=o.createElement("script"),d=o.getElementsByTagName("script")[0],c=d.parentNode;s.crossOrigin="",s.src=t.rollbarJsUrl,e||(s.async=!0),s.onload=s.onreadystatechange=n(function(){if(!(i||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){s.onload=s.onreadystatechange=null;try{c.removeChild(s)}catch(r){}i=!0,l()}}),c.insertBefore(s,d)},t.prototype.wrap=function(r,o,e){try{var n;if(n="function"==typeof o?o:function(){return o||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrapped=function(){e&&"function"==typeof e&&e.apply(this,arguments);try{return r.apply(this,arguments)}catch(e){var o=e;throw"string"==typeof o&&(o=new String(o)),o._rollbarContext=n()||{},o._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=o,o}},r._rollbar_wrapped._isWrap=!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrapped[t]=r[t]);return r._rollbar_wrapped}catch(o){return r}};for(var u="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleUnhandledRejection,captureEvent,captureDomContentLoaded,captureLoad".split(","),f=0;f<u.length;++f)t.prototype[u[f]]=l(u[f]);r.exports={setupShim:a,Rollbar:p}},function(r,o){"use strict";function e(r,o,e){if(r){var t;"function"==typeof o._rollbarOldOnError?t=o._rollbarOldOnError:r.onerror&&!r.onerror.belongsToShim&&(t=r.onerror,o._rollbarOldOnError=t);var a=function(){var e=Array.prototype.slice.call(arguments,0);n(r,o,t,e)};a.belongsToShim=e,r.onerror=a}}function n(r,o,e,n){r._rollbarWrappedError&&(n[4]||(n[4]=r._rollbarWrappedError),n[5]||(n[5]=r._rollbarWrappedError._rollbarContext),r._rollbarWrappedError=null),o.handleUncaughtException.apply(o,n),e&&e.apply(r,n)}function t(r,o,e){if(r){"function"==typeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener("unhandledrejection",r._rollbarURH);var n=function(r){var e=r.reason,n=r.promise,t=r.detail;!e&&t&&(e=t.reason,n=t.promise),o&&o.handleUnhandledRejection&&o.handleUnhandledRejection(e,n)};n.belongsToShim=e,r._rollbarURH=n,r.addEventListener("unhandledrejection",n)}}function a(r,o,e){if(r){var n,t,a="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(n=0;n<a.length;++n)t=a[n],r[t]&&r[t].prototype&&l(o,r[t].prototype,e)}}function l(r,o,e){if(o.hasOwnProperty&&o.hasOwnProperty("addEventListener")){for(var n=o.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)n=n._rollbarOldAdd;var t=function(o,e,t){n.call(this,o,r.wrap(e),t)};t._rollbarOldAdd=n,t.belongsToShim=e,o.addEventListener=t;for(var a=o.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)a=a._rollbarOldRemove;var l=function(r,o,e){a.call(this,r,o&&o._rollbar_wrapped||o,e)};l._rollbarOldRemove=a,l.belongsToShim=e,o.removeEventListener=l}}r.exports={captureUncaughtExceptions:e,captureUnhandledRejections:t,wrapGlobals:a}},function(r,o){"use strict";function e(r,o){this.impl=r(o,this),this.options=o,n(e.prototype)}function n(r){for(var o=function(r){return function(){var o=Array.prototype.slice.call(arguments,0);if(this.impl[r])return this.impl[r].apply(this.impl,o)}},e="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureEvent,captureDomContentLoaded,captureLoad".split(","),n=0;n<e.length;n++)r[e[n]]=o(e[n])}e.prototype._swapAndProcessMessages=function(r,o){this.impl=r(this.options);for(var e,n,t;e=o.shift();)n=e.method,t=e.args,this[n]&&"function"==typeof this[n]&&("captureDomContentLoaded"===n||"captureLoad"===n?this[n].apply(this,[t[0],e.ts]):this[n].apply(this,t));return this},r.exports=e},function(r,o){"use strict";r.exports=function(r){return function(o){if(!o&&!window._rollbarInitialized){r=r||{};for(var e,n,t=r.globalAlias||"Rollbar",a=window.rollbar,l=function(r){return new a(r)},i=0;e=window._rollbarShims[i++];)n||(n=e.handler),e.handler._swapAndProcessMessages(l,e.messages);window[t]=n,window._rollbarInitialized=!0}}}}]); | |
// End Rollbar Snippet | |
</script> | |
<%_ } _%> | |
// -------------------------------------------------- | |
// setupErrorLogging.js | |
// -------------------------------------------------- | |
/* @flow */ | |
import idx from 'idx'; | |
const regexsToIgnore = [ | |
/Branch init failed/gi, | |
/GoogleAPI.*popup_closed_by_user/gi, // google auth | |
/GoogleAPI.*access_denied/gi, // google auth | |
/unhandled rejection was null or undefined/gi, | |
/script error/gi, | |
/object Object/gi, | |
/GraphQL error: 503/gi, | |
/GraphQL error: Unauthorized/gi, | |
/GraphQL error: 401/gi, | |
/Network error: Failed to fetch/gi, | |
// prettier-ignore | |
/\$ is not defined/gi, // eslint-disable-line | |
/Blocked a frame with origin "https:\/\/www.remind.com" from accessing a frame with origin "https:\/\/accounts.google.com". Protocols, domains, and ports must match./gi, // error with chrome on ios. Verified that it works correctly. | |
/event is not defined/gi, | |
/Failed to load because no supported source was found./gi, | |
/maxItems has been hit. Ignoring errors until reset./gi, // When rollbar's max items per browser session have been hit | |
/Cannot read property 'load' of undefined/gi, // chrome 47 auth | |
]; | |
export function checkIgnore(isUncaught: boolean, args: Array<*>, payload: Object) { | |
try { | |
if (payload.fingerprint) { | |
return regexsToIgnore.some(pattern => payload.fingerprint.search(pattern) !== -1); | |
} | |
return false; | |
} catch (e) { | |
// if we did this wrong, lets log it so we can track why, and send the error anyway. | |
console.error(e); | |
return false; | |
} | |
} | |
export function transform(payload: Object) { | |
const message = | |
idx(payload, _ => _.body.message.body) || | |
idx(payload, _ => _.body.message) || | |
idx(payload, _ => _.body.trace.exception.message) || | |
idx(payload, _ => _.body.trace.extra.extraArgs[0].message) || | |
idx(payload, _ => _.body.trace.extra.extraArgs[1].message) || | |
idx(payload, _ => _.body.trace.extra.extraArgs[0]) || | |
idx(payload, _ => _.body.trace.extra.extraArgs[1]); | |
const description = | |
idx(payload, _ => _.body.trace.exception.description) || | |
idx(payload, _ => _.body.message.extra.error); | |
if (typeof message === 'string' && message !== '') { | |
const shouldAddDescription = typeof description === 'string' && description !== message; | |
payload.fingerprint = message + (shouldAddDescription ? ` ${description || ''}` : ''); | |
} else if (description && typeof description === 'string') { | |
payload.fingerprint = description; | |
} | |
} | |
if (typeof window !== 'undefined' && window.Rollbar) { | |
// TODO some way to disable console output. This seems to require a PR to rollbar's lib. | |
const { Rollbar } = window; | |
const nativeConsoleError = console.error; | |
// $FlowFixMe | |
console.error = (...args) => { | |
// If there's an error passed to the console, we want to use thar directly to preserve the stacktrace | |
const hasError = args.some(e => e instanceof Error); | |
if (hasError) { | |
Rollbar.error(...args); | |
} else { | |
// otherwise generate a stack trace | |
try { | |
throw Error(args[0]); | |
} catch (e) { | |
Rollbar.error(e, ...args.slice(1)); | |
} | |
} | |
return nativeConsoleError.apply(console, args); | |
}; | |
Rollbar.global({ | |
maxItems: 10, | |
}); | |
Rollbar.configure({ | |
transform, | |
checkIgnore, | |
}); | |
} else if (typeof window !== 'undefined') { | |
// Put these on the window so they can be picked up by the initial rollbar config, in case Rollbar wasn't initalized at the time this runs. | |
window._rolbarTransform = transform; | |
window._rollbarCheckIgnore = checkIgnore; | |
} | |
// -------------------------------------------------- | |
// setupErrorLogging-test.js | |
// -------------------------------------------------- | |
/* @flow weak */ | |
import { transform, checkIgnore } from '../setupErrorLogging'; | |
describe('setupErrorLogging', () => { | |
const errorsToSend = [ | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: 'Received 401 after finding a window user', | |
class: 'Error', | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
message: 'abcdefghijklmnopqurstuvwxyz1234567890', | |
}, | |
}, | |
]; | |
const errorsToIgnore = [ | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: 'Request blocked by client, probably adblock', | |
class: 'Error', | |
description: 'Branch init failed', | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
message: { | |
body: 'GoogleAPI fetchAuthorizationCode failed', | |
extra: { | |
error: 'popup_closed_by_user', | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: 'unhandled rejection was null or undefined!', | |
class: '(unknown)', | |
description: 'unhandled rejection was null or undefined!', | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: 'Script error.', | |
class: '(unknown)', | |
description: 'Script error.', | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: 'Unhandled error', | |
class: 'Error', | |
description: 'GraphQL error: Unauthorized', | |
}, | |
extra: { | |
extraArgs: [ | |
'Error: GraphQL error: Unauthorized\n at new t (https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:82572)\n at https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:49350\n at https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:59168\n at Array.forEach (<anonymous>)\n at https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:59142\n at Array.forEach (<anonymous>)\n at e.broadcastQueries (https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:59091)\n at https://d32zu3mt2bvf74.cloudfront.net/assets/dll.vendor_7220b67f6999fe47e18e.js:1:58142\n at <anonymous>', | |
], | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: "Cannot read property 'load' of undefined", | |
class: 'TypeError', | |
description: "Uncaught TypeError: Cannot read property 'load' of undefined", | |
}, | |
}, | |
}, | |
}, | |
{ | |
body: { | |
trace: { | |
exception: { | |
message: '0', | |
class: 'Error', | |
description: 'Branch init failed', | |
}, | |
}, | |
}, | |
}, | |
]; | |
errorsToSend.forEach(payload => { | |
transform(payload); // mutates the payload | |
it(`should send with fingerprint ${payload.fingerprint}`, () => { | |
expect(checkIgnore(false, [], payload)).toBe(false); | |
}); | |
}); | |
errorsToIgnore.forEach(payload => { | |
transform(payload); // mutates the payload | |
it(`should ignore with fingerprint ${payload.fingerprint}`, () => { | |
expect(checkIgnore(false, [], payload)).toBe(true); | |
expect(checkIgnore(false, [], payload)).toBe(true); // testing twice becaused regexs are stateful | |
}); | |
}); | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment