diff --git a/app/assets/javascripts/app.ts b/app/assets/javascripts/app.ts index dd0f8cb0a..9fdb061f2 100644 --- a/app/assets/javascripts/app.ts +++ b/app/assets/javascripts/app.ts @@ -53,6 +53,7 @@ import { import { trusted } from './filters'; import { isDev } from './utils'; import { Bridge, BrowserBridge } from './services/bridge'; +import { startErrorReporting } from './services/errorReporting'; if (__WEB__) { startApplication( @@ -67,6 +68,7 @@ function startApplication( defaultSyncServerHost: string, bridge: Bridge ) { + startErrorReporting(); angular.module('app', ['ngSanitize']); // Config diff --git a/app/assets/javascripts/services/errorReporting.ts b/app/assets/javascripts/services/errorReporting.ts new file mode 100644 index 000000000..3229051ab --- /dev/null +++ b/app/assets/javascripts/services/errorReporting.ts @@ -0,0 +1,23 @@ +import { isDesktopApplication, isDev } from '@/utils'; +import { storage, StorageKey } from './localStorage'; +import Bugsnag from '@bugsnag/js'; + +declare const __VERSION__: string; + +export async function startErrorReporting() { + if (storage.get(StorageKey.DisableErrorReporting)) { + return; + } + try { + Bugsnag.start({ + apiKey: (window as any)._bugsnag_api_key, + appType: isDesktopApplication() ? 'desktop' : 'web', + appVersion: __VERSION__, + collectUserIp: false, + autoTrackSessions: false, + releaseStage: isDev ? 'development' : undefined + }); + } catch (error) { + console.error('Failed to start Bugsnag.', error); + } +} diff --git a/app/assets/javascripts/services/localStorage.ts b/app/assets/javascripts/services/localStorage.ts new file mode 100644 index 000000000..5f832ea00 --- /dev/null +++ b/app/assets/javascripts/services/localStorage.ts @@ -0,0 +1,16 @@ +export enum StorageKey { + DisableErrorReporting = 'DisableErrorReporting', +} + +export const storage = { + get(key: StorageKey) { + const value = localStorage.getItem(key); + return value ? JSON.parse(value) : null; + }, + set(key: StorageKey, value: unknown) { + localStorage.setItem(key, JSON.stringify(value)); + }, + remove(key: StorageKey) { + localStorage.removeItem(key); + }, +}; diff --git a/app/views/application/app.html.erb b/app/views/application/app.html.erb index 724234545..71d29c6bb 100644 --- a/app/views/application/app.html.erb +++ b/app/views/application/app.html.erb @@ -32,6 +32,7 @@ window._default_sync_server = "<%= ENV['SF_DEFAULT_SERVER'] %>"; window._extensions_manager_location = "<%= ENV['EXTENSIONS_MANAGER_LOCATION'] %>"; window._batch_manager_location = "<%= ENV['BATCH_MANAGER_LOCATION'] %>"; + window._bugsnag_api_key = "<%= ENV['BUGSNAG_API_KEY'] %>"; <% if Rails.env.development? %> diff --git a/index.html b/index.html index 4f5967139..01ac2ef10 100644 --- a/index.html +++ b/index.html @@ -32,11 +32,13 @@ data-default-sync-server="<%= env.DEV_DEFAULT_SYNC_SERVER %>" data-extensions-manager-location="<%= env.DEV_EXTENSIONS_MANAGER_LOCATION %>" data-batch-manager-location="<%= env.DEV_BATCH_MANAGER_LOCATION %>" + data-bugsnag-api-key="<%= env.DEV_BUGSNAG_API_KEY %>" > diff --git a/package-lock.json b/package-lock.json index 358dfe1e1..723a81283 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2507,6 +2507,58 @@ } } }, + "@bugsnag/browser": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@bugsnag/browser/-/browser-7.5.1.tgz", + "integrity": "sha512-NLWgSj3elYGSkdth666UxQ6r5Y/zAMidnQZRnOW2ZsW+4W/q+hr7zoN4v5IUnZuoSTQ9QxVYY99wA4hqlDyoJg==", + "requires": { + "@bugsnag/core": "^7.3.5" + } + }, + "@bugsnag/core": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@bugsnag/core/-/core-7.3.5.tgz", + "integrity": "sha512-7zKFLcA6m9aaQ1p1AQx2iRaT3gE/MJqy0vGa/RhlKNdgMdMKYRGECWxJE66firvJT5ZwL7Bu11IkK6sLWHCBaw==", + "requires": { + "@bugsnag/cuid": "^3.0.0", + "@bugsnag/safe-json-stringify": "^6.0.0", + "error-stack-parser": "^2.0.3", + "iserror": "0.0.2", + "stack-generator": "^2.0.3" + } + }, + "@bugsnag/cuid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/cuid/-/cuid-3.0.0.tgz", + "integrity": "sha512-LOt8aaBI+KvOQGneBtpuCz3YqzyEAehd1f3nC5yr9TIYW1+IzYKa2xWS4EiMz5pPOnRPHkyyS5t/wmSmN51Gjg==" + }, + "@bugsnag/js": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@bugsnag/js/-/js-7.5.1.tgz", + "integrity": "sha512-acbq392QYjZNtUHa5tTp+MLTBhNZhI4s6EBrEFqN1TdxrVVGEFfnQqrPISfKtOJ+FW1dZEZiQ0oEGJ127htqIQ==", + "requires": { + "@bugsnag/browser": "^7.5.1", + "@bugsnag/node": "^7.3.5" + } + }, + "@bugsnag/node": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@bugsnag/node/-/node-7.3.5.tgz", + "integrity": "sha512-eN06NgphKYikBq/AXpiLO9tNx1H7cz8C78oQnR5fj2POulj+Zm9njr9dM6DEzGIvBDt952SwwcOA73jAiOmztQ==", + "requires": { + "@bugsnag/core": "^7.3.5", + "byline": "^5.0.0", + "error-stack-parser": "^2.0.2", + "iserror": "^0.0.2", + "pump": "^3.0.0", + "stack-generator": "^2.0.3" + } + }, + "@bugsnag/safe-json-stringify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz", + "integrity": "sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==" + }, "@types/angular": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/@types/angular/-/angular-1.7.0.tgz", @@ -3936,6 +3988,11 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -5079,7 +5136,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -5131,6 +5187,14 @@ "is-arrayish": "^0.2.1" } }, + "error-stack-parser": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", + "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", + "requires": { + "stackframe": "^1.1.1" + } + }, "es-abstract": { "version": "1.17.4", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", @@ -7735,6 +7799,11 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "iserror": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/iserror/-/iserror-0.0.2.tgz", + "integrity": "sha1-vVNFH+L2aLnyQCwZZnh6qix8C/U=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -9174,7 +9243,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -9954,7 +10022,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -11218,6 +11285,19 @@ "figgy-pudding": "^3.5.1" } }, + "stack-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.5.tgz", + "integrity": "sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==", + "requires": { + "stackframe": "^1.1.1" + } + }, + "stackframe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -12908,8 +12988,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", diff --git a/package.json b/package.json index bb7141c7c..337d1cb8a 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "@bugsnag/js": "^7.5.1", "mobx": "^6.0.1", "sncrypto": "github:standardnotes/sncrypto#8794c88daa967eaae493cd5fdec7506d52b257ad", "snjs": "github:standardnotes/snjs#b7866c68243b418ae5e7be830d1593f0e07333e4"