mirror of
https://github.com/floccusaddon/floccus
synced 2025-04-29 15:57:24 +08:00
Add optional telemetry
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
parent
d439d11815
commit
91133f6c9a
3
.gitignore
vendored
3
.gitignore
vendored
@ -5,3 +5,6 @@ builds
|
||||
key.pem
|
||||
.idea
|
||||
.DS_STORE
|
||||
|
||||
# Sentry Config File
|
||||
.env.sentry-build-plugin
|
||||
|
@ -704,5 +704,17 @@
|
||||
},
|
||||
"LabelGitbranch": {
|
||||
"message": "Git branch"
|
||||
},
|
||||
"LabelTelemetry": {
|
||||
"message": "Automated Error Reporting"
|
||||
},
|
||||
"DescriptionTelemetry": {
|
||||
"message": "Floccus can automatically send error data to me, the developer. This is a tremendous help for discovering and resolving bugs in floccus more quickly and will help improve your experience with floccus in the long run. Even when error reporting is enabled, the floccus developers will never be able to see your bookmarks."
|
||||
},
|
||||
"LabelTelemetryenable": {
|
||||
"message": "Automatically send error data to floccus developers"
|
||||
},
|
||||
"LabelTelemetrydisable": {
|
||||
"message": "Do not send error data to floccus developers"
|
||||
}
|
||||
}
|
||||
|
18
gulpfile.js
18
gulpfile.js
@ -77,6 +77,22 @@ const icons = function() {
|
||||
return gulp.src(paths.icons).pipe(gulp.dest('./dist/icons/'))
|
||||
}
|
||||
|
||||
const devjs = function() {
|
||||
return new Promise((resolve) =>
|
||||
webpack(devConfig, (err, stats) => {
|
||||
if (err) console.log('Webpack', err)
|
||||
|
||||
console.log(
|
||||
stats.toString({
|
||||
/* stats options */
|
||||
})
|
||||
)
|
||||
|
||||
resolve()
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const js = function() {
|
||||
return new Promise((resolve) =>
|
||||
webpack(config, (err, stats) => {
|
||||
@ -214,7 +230,7 @@ exports.js = js
|
||||
exports.mocha = mocha
|
||||
exports.watch = watch
|
||||
exports.release = release
|
||||
exports.watch = gulp.series(main, watch)
|
||||
exports.watch = gulp.series(gulp.parallel(assets, devjs), native, watch)
|
||||
exports.publish = publish
|
||||
exports.build = build
|
||||
exports.native = native
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"manifest_version": 2,
|
||||
"name": "floccus bookmarks sync",
|
||||
"short_name": "floccus",
|
||||
"version": "5.1.0",
|
||||
@ -10,23 +10,27 @@
|
||||
"128": "icons/logo_128.png"
|
||||
},
|
||||
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "floccus@handmadeideas.org",
|
||||
"strict_min_version": "57.0"
|
||||
}
|
||||
},
|
||||
|
||||
"default_locale": "en",
|
||||
|
||||
"permissions": ["alarms", "bookmarks", "storage", "unlimitedStorage", "tabs", "identity"],
|
||||
"host_permissions": [
|
||||
"*://*/*"
|
||||
],
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self'; object-src 'self';"
|
||||
},
|
||||
"permissions": ["*://*/*", "alarms", "bookmarks", "storage", "unlimitedStorage", "tabs", "identity"],
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",
|
||||
|
||||
"options_ui": {
|
||||
"page": "dist/html/options.html",
|
||||
"browser_style": false
|
||||
"browser_style": false,
|
||||
"chrome_style": false
|
||||
},
|
||||
|
||||
"action": {
|
||||
"browser_action": {
|
||||
"browser_style": false,
|
||||
"chrome_style": false,
|
||||
"default_icon": {
|
||||
"48": "icons/logo.png"
|
||||
},
|
||||
@ -35,6 +39,6 @@
|
||||
},
|
||||
|
||||
"background": {
|
||||
"service_worker": "dist/js/background-script.js"
|
||||
"page": "dist/html/background.html"
|
||||
}
|
||||
}
|
||||
|
922
package-lock.json
generated
922
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -84,6 +84,8 @@
|
||||
"@capacitor/share": "^5.0.0",
|
||||
"@capacitor/splash-screen": "^5.0.0",
|
||||
"@isomorphic-git/lightning-fs": "^4.6.0",
|
||||
"@sentry/vue": "^7.113.0",
|
||||
"@sentry/webpack-plugin": "^2.16.1",
|
||||
"async-lock": "^1.2.8",
|
||||
"async-parallel": "^1.2.3",
|
||||
"batching-toposort": "^1.2.0",
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* global DEBUG */
|
||||
import AdapterFactory from './AdapterFactory'
|
||||
import Logger from './Logger'
|
||||
import { Folder, ItemLocation, TItemLocation } from './Tree'
|
||||
@ -12,6 +13,7 @@ import IAccount from './interfaces/Account'
|
||||
import Mappings from './Mappings'
|
||||
import { isTest } from './isTest'
|
||||
import CachingAdapter from './adapters/Caching'
|
||||
import * as Sentry from '@sentry/vue'
|
||||
|
||||
// register Adapters
|
||||
AdapterFactory.register('nextcloud-folders', async() => (await import('./adapters/NextcloudBookmarks')).default)
|
||||
@ -148,6 +150,7 @@ export default class Account {
|
||||
if (!(await this.server.isAvailable()) || !(await localResource.isAvailable())) return
|
||||
|
||||
Logger.log('Starting sync process for account ' + this.getLabel())
|
||||
Sentry.setUser({ id: this.id })
|
||||
this.syncing = true
|
||||
await this.setData({ ...this.getData(), syncing: 0.05, scheduled: false, error: null })
|
||||
|
||||
@ -163,6 +166,7 @@ export default class Account {
|
||||
} catch (e) {
|
||||
// Resource locked
|
||||
if (e.code === 37) {
|
||||
Sentry.captureException(e)
|
||||
// We got a resource locked error
|
||||
if (this.getData().lastSync < Date.now() - LOCK_TIMEOUT) {
|
||||
// but if we've been waiting for the lock for more than 2h
|
||||
@ -310,6 +314,25 @@ export default class Account {
|
||||
const message = await Account.stringifyError(e)
|
||||
console.error('Syncing failed with', message)
|
||||
Logger.log('Syncing failed with', message)
|
||||
// send error to sentry
|
||||
const logData = await Logger.anonymizeLogs(Logger.messages)
|
||||
Sentry.setContext('accountData', {
|
||||
...this.getData(),
|
||||
username: 'SENSITIVEVALUEHIDDEN',
|
||||
password: 'SENSITIVEVALUVALUEHIDDEN',
|
||||
passphrase: 'SENSITIVEVALUVALUEHIDDEN'
|
||||
})
|
||||
if (!(window || self)['DEBUG']) {
|
||||
Sentry.getCurrentScope().addAttachment({
|
||||
filename: 'floccus-log.txt',
|
||||
data: logData.slice(-200000).join('\n'),
|
||||
})
|
||||
}
|
||||
if (e.list) {
|
||||
Sentry.captureException(message)
|
||||
} else {
|
||||
Sentry.captureException(e)
|
||||
}
|
||||
|
||||
await this.setData({
|
||||
...this.getData(),
|
||||
|
@ -8,6 +8,7 @@ import BrowserAccountStorage from './BrowserAccountStorage'
|
||||
import uniqBy from 'lodash/uniqBy'
|
||||
import Account from '../Account'
|
||||
import { STATUS_ALLGOOD, STATUS_DISABLED, STATUS_ERROR, STATUS_SYNCING } from '../interfaces/Controller'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
|
||||
const INACTIVITY_TIMEOUT = 7 * 1000 // 7 seconds
|
||||
const DEFAULT_SYNC_INTERVAL = 15 // 15 minutes
|
||||
@ -379,5 +380,17 @@ export default class BrowserController {
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
browser.storage.local.get('telemetryEnabled').then(async d => {
|
||||
if (!d.telemetryEnabled) {
|
||||
return
|
||||
}
|
||||
Sentry.init({
|
||||
dsn: 'https://836f0f772fbf2e12b9dd651b8e6b6338@o4507214911307776.ingest.de.sentry.io/4507216408870992',
|
||||
integrations: [],
|
||||
release: packageJson.version,
|
||||
debug: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,21 @@
|
||||
</template>
|
||||
<span>{{ t('LabelFunddevelopment') }}</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn
|
||||
x-small
|
||||
text
|
||||
class="white--text"
|
||||
v-bind="attrs"
|
||||
:to="{name: routes.TELEMETRY}"
|
||||
target="_blank"
|
||||
v-on="on">
|
||||
<v-icon>{{ telemetryEnabled ? 'mdi-bug-play-outline' : 'mdi-bug-pause-outline' }}</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>{{ t('LabelTelemetry') }}</span>
|
||||
</v-tooltip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-footer>
|
||||
@ -74,6 +89,7 @@ import { version as VERSION } from '../../package.json'
|
||||
import { actions } from './store'
|
||||
import { routes } from './router'
|
||||
import Controller from '../lib/Controller'
|
||||
import browser from '../lib/browser-api'
|
||||
export default {
|
||||
name: 'App',
|
||||
data() {
|
||||
@ -81,6 +97,7 @@ export default {
|
||||
VERSION,
|
||||
key: '',
|
||||
unlockError: null,
|
||||
telemetryEnabled: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -109,6 +126,8 @@ export default {
|
||||
window.addEventListener('beforeunload', unregister)
|
||||
window.addEventListener('unload', unregister)
|
||||
window.addEventListener('close', unregister)
|
||||
const {telemetryEnabled} = await browser.storage.local.get({'telemetryEnabled': false})
|
||||
this.telemetryEnabled = telemetryEnabled
|
||||
},
|
||||
methods: {
|
||||
async onUnlock() {
|
||||
|
@ -6,6 +6,7 @@ import Update from './views/Update'
|
||||
import ImportExport from './views/ImportExport'
|
||||
import Donate from './views/Donate'
|
||||
import About from './views/native/About'
|
||||
import Telemetry from './views/Telemetry.vue'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
@ -18,6 +19,8 @@ export const routes = {
|
||||
UPDATE: 'UPDATE',
|
||||
IMPORTEXPORT: 'IMPORTEXPORT',
|
||||
DONATE: 'DONATE',
|
||||
TELEMETRY: 'TELEMETRY',
|
||||
|
||||
}
|
||||
|
||||
export const router = new Router({
|
||||
@ -59,5 +62,10 @@ export const router = new Router({
|
||||
name: routes.DONATE,
|
||||
component: Donate,
|
||||
},
|
||||
{
|
||||
path: '/telemetry',
|
||||
name: routes.TELEMETRY,
|
||||
component: Telemetry,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
63
src/ui/views/Telemetry.vue
Normal file
63
src/ui/views/Telemetry.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-card
|
||||
class="options mt-3">
|
||||
<v-container class="pa-5">
|
||||
<v-card-title>
|
||||
{{ t("LabelTelemetry") }}
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="body-1">
|
||||
{{ t("DescriptionTelemetry") }}
|
||||
</div>
|
||||
<v-radio-group v-model="telemetry" class="mt-4">
|
||||
<v-radio :value="true">
|
||||
<template #label>
|
||||
<div class="heading">
|
||||
{{ t("LabelTelemetryenable") }}
|
||||
</div>
|
||||
</template>
|
||||
</v-radio>
|
||||
<v-radio :value="false">
|
||||
<template #label>
|
||||
<div class="heading">
|
||||
{{ t("LabelTelemetrydisable") }}
|
||||
</div>
|
||||
</template>
|
||||
</v-radio>
|
||||
</v-radio-group>
|
||||
</v-card-text>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import browser from '../../lib/browser-api'
|
||||
|
||||
export default {
|
||||
name: 'Telemetry',
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
telemetry: false,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
telemetry(enabled) {
|
||||
browser.storage.local.set({'telemetryEnabled': enabled})
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
const {telemetryEnabled} = await browser.storage.local.get({'telemetryEnabled': false})
|
||||
this.telemetry = telemetryEnabled
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.options {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
@ -17,6 +17,30 @@
|
||||
{{ t('LabelReleaseNotes') }}
|
||||
</v-btn>
|
||||
</v-card-text>
|
||||
<v-card-title>
|
||||
{{ t("LabelTelemetry") }}
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="body-1">
|
||||
{{ t("DescriptionTelemetry") }}
|
||||
</div>
|
||||
<v-radio-group v-model="telemetry" class="mt-4">
|
||||
<v-radio :value="true">
|
||||
<template #label>
|
||||
<div class="heading">
|
||||
{{ t("LabelTelemetryenable") }}
|
||||
</div>
|
||||
</template>
|
||||
</v-radio>
|
||||
<v-radio :value="false">
|
||||
<template #label>
|
||||
<div class="heading">
|
||||
{{ t("LabelTelemetrydisable") }}
|
||||
</div>
|
||||
</template>
|
||||
</v-radio>
|
||||
</v-radio-group>
|
||||
</v-card-text>
|
||||
<v-card-title>
|
||||
{{ t("LabelFunddevelopment") }}
|
||||
</v-card-title>
|
||||
@ -59,12 +83,14 @@
|
||||
<script>
|
||||
import {version as VERSION} from '../../../package.json'
|
||||
import { routes } from '../NativeRouter'
|
||||
import browser from '../../lib/browser-api'
|
||||
|
||||
export default {
|
||||
name: 'Update',
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
telemetry: false,
|
||||
paymentOptions: [
|
||||
{
|
||||
href: 'https://www.paypal.me/marcelklehr1',
|
||||
@ -107,8 +133,15 @@ export default {
|
||||
return routes
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
watch: {
|
||||
telemetry(enabled) {
|
||||
browser.storage.local.set({'telemetryEnabled': enabled})
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const {telemetryEnabled} = await browser.storage.local.get({'telemetryEnabled': false})
|
||||
this.telemetry = telemetryEnabled
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,12 +1,21 @@
|
||||
const {
|
||||
sentryWebpackPlugin
|
||||
} = require("@sentry/webpack-plugin")
|
||||
const merge = require('webpack-merge')
|
||||
const common = require('./webpack.common.js')
|
||||
const webpack = require('webpack')
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
DEBUG: JSON.stringify(!process.env['CI'])
|
||||
})
|
||||
}),
|
||||
sentryWebpackPlugin({
|
||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||
org: "marcel-klehr",
|
||||
project: "floccus"
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user