Skip to content

Commit

Permalink
Add integration for offline support
Browse files Browse the repository at this point in the history
Offline events are cached in the browser with localforage.
  • Loading branch information
davidmyersdev committed Jul 28, 2020
1 parent a19e33e commit b0d0260
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 1 deletion.
2 changes: 2 additions & 0 deletions packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
},
"dependencies": {
"@sentry/core": "5.20.1",
"@sentry/minimal": "5.20.1",
"@sentry/types": "5.20.1",
"@sentry/utils": "5.20.1",
"localforage": "^1.8.1",
"tslib": "^1.9.3"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/integrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { TryCatch } from './trycatch';
export { Breadcrumbs } from './breadcrumbs';
export { LinkedErrors } from './linkederrors';
export { UserAgent } from './useragent';
export { Offline } from './offline';
99 changes: 99 additions & 0 deletions packages/browser/src/integrations/offline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core';
import { captureEvent } from '@sentry/minimal';
import { Event, Integration } from '@sentry/types';
import { getGlobalObject, uuid4 } from '@sentry/utils';
import * as localforage from 'localforage';

/**
* cache offline errors and send when connected
*/
export class Offline implements Integration {
/**
* @inheritDoc
*/
public static id: string = 'Offline';

/**
* @inheritDoc
*/
public readonly name: string = Offline.id;

/**
* event cache
*/
public offlineEventStore: LocalForage;

/**
* @inheritDoc
*/
public constructor() {
this.offlineEventStore = localforage.createInstance({
name: 'sentry/offlineEventStore',
});

getGlobalObject<Window>().addEventListener('online', () => {
this._sendEvents().catch(() => {
// todo: handle localforage error
});
});
}

/**
* @inheritDoc
*/
public setupOnce(): void {
addGlobalEventProcessor(async (event: Event) => {
if (getCurrentHub().getIntegration(Offline)) {
const global = getGlobalObject<Window>();

// cache if we are positively offline
if ('navigator' in global && 'onLine' in global.navigator && !global.navigator.onLine) {
try {
await this._cacheEvent(event);
} catch (error) {
// todo: handle localforage error
}

// return null on success or failure, because being offline will still result in an error
return null;
}
}

return event;
});
}

/**
* cache an event to send later
* @param event an event
*/
private async _cacheEvent(event: Event): Promise<Event> {
return this.offlineEventStore.setItem(uuid4(), event);
}

/**
* purge event from cache
*/
private async _purgeEvent(cacheKey: string): Promise<void> {
return this.offlineEventStore.removeItem(cacheKey);
}

/**
* send all events
*/
private async _sendEvents(): Promise<void> {
return this.offlineEventStore.iterate((event, cacheKey, _index) => {
try {
const newEventId = captureEvent(event);

if (newEventId) {
this._purgeEvent(cacheKey)
.then(_ => _)
.catch(_ => _);
}
} catch (error) {
// handle JSON.parse error
}
});
}
}
54 changes: 53 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1939,11 +1939,32 @@ after@0.8.2:
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=

agent-base@4, agent-base@5, agent-base@6, agent-base@^4.3.0, agent-base@~4.2.1:
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
dependencies:
es6-promisify "^5.0.0"

agent-base@5:
version "5.1.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==

agent-base@6:
version "6.0.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4"
integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==
dependencies:
debug "4"

agent-base@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies:
es6-promisify "^5.0.0"

agentkeepalive@^3.4.1:
version "3.5.2"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67"
Expand Down Expand Up @@ -5114,6 +5135,18 @@ es6-object-assign@^1.1.0:
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=

es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==

es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"

escalade@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4"
Expand Down Expand Up @@ -6528,6 +6561,11 @@ ignore@^5.1.4:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==

immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=

import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
Expand Down Expand Up @@ -8106,6 +8144,13 @@ libnpmpublish@^1.1.1:
semver "^5.5.1"
ssri "^6.0.1"

lie@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=
dependencies:
immediate "~3.0.5"

lines-and-columns@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
Expand Down Expand Up @@ -8155,6 +8200,13 @@ loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"

localforage@^1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.8.1.tgz#f6c0a24b41ab33b10e4dc84342dd696f6f3e3433"
integrity sha512-azSSJJfc7h4bVpi0PGi+SmLQKJl2/8NErI+LhJsrORNikMZnhaQ7rv9fHj+ofwgSHrKRlsDCL/639a6nECIKuQ==
dependencies:
lie "3.1.1"

locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
Expand Down

0 comments on commit b0d0260

Please sign in to comment.