update browser sentry

Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
This commit is contained in:
FTCHD
2025-08-31 01:44:04 +02:00
parent 4c0ff4b7d3
commit 6d67f88582
11 changed files with 181 additions and 24 deletions
+2
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { readDir } from '@tauri-apps/plugin-fs'
export async function isDirectoryEmpty(path: string): Promise<boolean> {
@@ -5,6 +6,7 @@ export async function isDirectoryEmpty(path: string): Promise<boolean> {
const entries = await readDir(path)
return entries.length === 0
} catch (err) {
Sentry.captureException(err)
console.error('Error checking directory:', err)
return false
}
+18 -12
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { Menu, MenuItem, PredefinedMenuItem, Submenu } from '@tauri-apps/api/menu'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { ask, message, open } from '@tauri-apps/plugin-dialog'
@@ -48,9 +49,10 @@ async function parseRemotes(remotes: string[]) {
await message(`Successfully unmounted ${remote} from ${mountPoint}`, {
title: 'Success',
})
} catch (err) {
console.error('Unmount operation failed:', err)
await message(`Failed to unmount ${remote}: ${err}`, {
} catch (error) {
Sentry.captureException(error)
console.error('Unmount operation failed:', error)
await message(`Failed to unmount ${remote}: ${error}`, {
kind: 'error',
title: 'Unmount Error',
})
@@ -71,9 +73,10 @@ async function parseRemotes(remotes: string[]) {
if (mountPoint) {
try {
await openPath(mountPoint)
} catch (err) {
console.error('Error opening path:', err)
await message(`Failed to open ${mountPoint} (${err})`, {
} catch (error) {
Sentry.captureException(error)
console.error('Error opening path:', error)
await message(`Failed to open ${mountPoint} (${error})`, {
title: 'Open Error',
kind: 'error',
})
@@ -127,8 +130,8 @@ async function parseRemotes(remotes: string[]) {
try {
directoryExists = await exists(selectedPath)
} catch (err) {
console.error('Error checking if directory exists:', err)
} catch (error) {
console.error('Error checking if directory exists:', error)
}
console.log('directoryExists', directoryExists)
@@ -157,6 +160,7 @@ async function parseRemotes(remotes: string[]) {
try {
await mkdir(selectedPath)
} catch (error) {
Sentry.captureException(error)
console.error('Error creating directory:', error)
await message(
'Failed to create mount directory. Try creating it manually first.',
@@ -206,10 +210,11 @@ async function parseRemotes(remotes: string[]) {
}
await rebuildTrayMenu()
} catch (err) {
} catch (error) {
// await resetMainWindow()
console.error('Mount operation failed:', err)
await message(`Failed to mount ${remote}: ${err}`, {
Sentry.captureException(error)
console.error('Mount operation failed:', error)
await message(`Failed to mount ${remote}: ${error}`, {
title: 'Mount Error',
})
} finally {
@@ -236,7 +241,8 @@ async function parseRemotes(remotes: string[]) {
'browse.html?url=' +
encodeURIComponent(`http://localhost:5572/[${remote}:]/`),
})
} catch {
} catch (error) {
Sentry.captureException(error)
await ask('Could not open browse window. Please try again.', {
title: 'Error',
kind: 'error',
+6
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { fetch } from '@tauri-apps/plugin-http'
import { platform } from '@tauri-apps/plugin-os'
import { useStore } from '../store'
@@ -31,6 +32,7 @@ export async function getVersion() {
headers: getAuthHeader(),
})
.catch((e) => {
Sentry.captureException(e)
console.log('error', e)
throw e
})
@@ -62,6 +64,7 @@ export async function listRemotes() {
headers: getAuthHeader(),
})
.catch((e) => {
Sentry.captureException(e)
console.log('error', e)
throw e
})
@@ -382,6 +385,7 @@ export async function mountRemote({
})
.then((res) => res.json() as Promise<{ remotes: string[] } | Promise<{ error: string }>>)
.catch((e) => {
Sentry.captureException(e)
console.log('error', e)
throw e
})
@@ -409,6 +413,7 @@ export async function unmountRemote({
})
.then((res) => res.json())
.catch((e) => {
Sentry.captureException(e)
console.log('error', e)
throw e
})
@@ -429,6 +434,7 @@ export async function unmountAllRemotes() {
})
.then((res) => res.json())
.catch((e) => {
Sentry.captureException(e)
console.log('error', e)
throw e
})
+7
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { invoke } from '@tauri-apps/api/core'
import { BaseDirectory, appLocalDataDir } from '@tauri-apps/api/path'
import { tempDir } from '@tauri-apps/api/path'
@@ -202,6 +203,7 @@ export async function provisionRclone() {
})
console.log('[provisionRclone] tempDirExists', tempDirExists)
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to check if rclone temp dir exists', error)
}
@@ -213,6 +215,7 @@ export async function provisionRclone() {
})
console.log('[provisionRclone] removed rclone temp dir')
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to remove rclone temp dir', error)
await message('Failed to provision rclone.')
return
@@ -225,6 +228,7 @@ export async function provisionRclone() {
})
console.log('[provisionRclone] created rclone temp dir')
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to create rclone temp dir', error)
await message('Failed to provision rclone.')
return
@@ -237,6 +241,7 @@ export async function provisionRclone() {
await writeFile(zipPath, new Uint8Array(downloadedFile))
console.log('[provisionRclone] wrote zip file')
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to write zip file', error)
await message('Failed to provision rclone.')
return
@@ -249,6 +254,7 @@ export async function provisionRclone() {
})
console.log('[provisionRclone] successfully unzipped file')
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to unzip file', error)
await message('Failed to provision rclone.')
return
@@ -270,6 +276,7 @@ export async function provisionRclone() {
throw new Error('Could not find rclone binary in zip')
}
} catch (error) {
Sentry.captureException(error)
console.error('[provisionRclone] failed to check if rclone binary exists', error)
await message('Failed to provision rclone.')
}
+2
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { Menu } from '@tauri-apps/api/menu'
import { MenuItem } from '@tauri-apps/api/menu'
import { resolveResource } from '@tauri-apps/api/path'
@@ -65,6 +66,7 @@ export async function initTray(): Promise<void> {
action: onTrayAction,
})
} catch (error) {
Sentry.captureException(error)
console.error('[initTray] failed to create tray')
console.error(error)
}
+34 -12
View File
@@ -1,3 +1,4 @@
import * as Sentry from '@sentry/browser'
import { getVersion as getUiVersion } from '@tauri-apps/api/app'
import { getCurrentWindow } from '@tauri-apps/api/window'
import { ask, message } from '@tauri-apps/plugin-dialog'
@@ -6,6 +7,7 @@ import { platform } from '@tauri-apps/plugin-os'
import { exit, relaunch } from '@tauri-apps/plugin-process'
import { check } from '@tauri-apps/plugin-updater'
import { CronExpressionParser } from 'cron-parser'
import { defaultOptions } from 'tauri-plugin-sentry-api'
import { validateLicense } from './lib/license'
import notify from './lib/notify'
import {
@@ -22,25 +24,40 @@ import { usePersistedStore, useStore } from './lib/store'
import { initLoadingTray, initTray, rebuildTrayMenu } from './lib/tray'
import type { ScheduledTask } from './types/task'
try {
Sentry.init({
...defaultOptions,
sendDefaultPii: false,
})
} catch {
console.error('Error initializing Sentry')
}
// forward console logs in webviews to the tauri logger, so they show up in terminal
function forwardConsole(
fnName: 'log' | 'debug' | 'info' | 'warn' | 'error',
logger: (message: string) => Promise<void>
) {
const original = console[fnName]
console[fnName] = (message, ...args) => {
original(message, ...args)
logger(
`${message} ${args?.map((arg) => (typeof arg === 'string' ? arg : JSON.stringify(arg))).join(' ')}`
)
}
try {
const original = console[fnName]
console[fnName] = (message, ...args) => {
original(message, ...args)
logger(
`${message} ${args?.map((arg) => (typeof arg === 'string' ? arg : JSON.stringify(arg))).join(' ')}`
)
}
} catch {}
}
forwardConsole('log', trace)
forwardConsole('debug', debug)
forwardConsole('info', info)
forwardConsole('warn', warn)
forwardConsole('error', error)
try {
forwardConsole('log', trace)
forwardConsole('debug', debug)
forwardConsole('info', info)
forwardConsole('warn', warn)
forwardConsole('error', error)
} catch (error) {
console.error('Could not enable console logs', error)
}
async function waitForHydration() {
console.log('waiting for store hydration')
@@ -125,6 +142,7 @@ async function startRclone() {
// ':5572',
])
} catch (error) {
Sentry.captureException(error)
await ask(error.message || 'Failed to start rclone, please try again later.', {
title: 'Error',
kind: 'error',
@@ -149,6 +167,7 @@ async function startRclone() {
console.log('close', event)
if (event.code === 1 || event.code === 143) {
Sentry.captureException(new Error('Rclone has crashed'))
await message('Rclone has crashed', {
title: 'Error',
kind: 'error',
@@ -215,6 +234,7 @@ async function startupMounts() {
})
} catch (error) {
console.error('Error mounting remote:', error)
Sentry.captureException(error)
await message(`Failed to mount ${remote} on startup.`, {
title: 'Automount Error',
kind: 'error',
@@ -285,6 +305,7 @@ async function resumeTasks() {
}
} catch (error) {
console.error('Error scheduling task:', error)
Sentry.captureException(error)
}
}
@@ -370,6 +391,7 @@ async function handleTask(task: ScheduledTask) {
break
}
} catch (err) {
Sentry.captureException(err)
console.error('Failed to start task:', err)
usePersistedStore.getState().updateScheduledTask(task.id, {
isRunning: false,
+102
View File
@@ -9,6 +9,7 @@
"version": "1.7.1",
"dependencies": {
"@heroui/react": "^2.7.11",
"@sentry/browser": "^10.8.0",
"@tauri-apps/api": "~2.7.0",
"@tauri-apps/plugin-autostart": "^2.5.0",
"@tauri-apps/plugin-clipboard-manager": "^2.3.0",
@@ -33,6 +34,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.28.1",
"tauri-plugin-sentry-api": "^0.4.1",
"use-broadcast-ts": "^2.0.1",
"use-debounce": "^10.0.5",
"zustand": "^5.0.7"
@@ -5092,6 +5094,81 @@
"win32"
]
},
"node_modules/@sentry-internal/browser-utils": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.8.0.tgz",
"integrity": "sha512-FaQX9eefc8sh3h3ZQy16U73KiH0xgDldXnrFiWK6OeWg8X4bJpnYbLqEi96LgHiQhjnnz+UQP1GDzH5oFuu5fA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.8.0.tgz",
"integrity": "sha512-n7SqgFQItq4QSPG7bCjcZcIwK6AatKnnmSDJ/i6e8jXNIyLwkEuY2NyvTXACxVdO/kafGD5VmrwnTo3Ekc1AMg==",
"license": "MIT",
"dependencies": {
"@sentry/core": "10.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.8.0.tgz",
"integrity": "sha512-9+qDEoEjv4VopLuOzK1zM4LcvcUsvB5N0iJ+FRCM3XzzOCbebJOniXTQbt5HflJc3XLnQNKFdKfTfgj8M/0RKQ==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.8.0",
"@sentry/core": "10.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.8.0.tgz",
"integrity": "sha512-jC4OOwiNgrlIPeXIPMLkaW53BSS1do+toYHoWzzO5AXGpN6jRhanoSj36FpVuH2N3kFnxKVfVxrwh8L+/3vFWg==",
"license": "MIT",
"dependencies": {
"@sentry-internal/replay": "10.8.0",
"@sentry/core": "10.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/browser": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.8.0.tgz",
"integrity": "sha512-2J7HST8/ixCaboq17yFn/j/OEokXSXoCBMXRrFx4FKJggKWZ90e2Iau5mP/IPPhrW+W9zCptCgNMY0167wS4qA==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "10.8.0",
"@sentry-internal/feedback": "10.8.0",
"@sentry-internal/replay": "10.8.0",
"@sentry-internal/replay-canvas": "10.8.0",
"@sentry/core": "10.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/core": {
"version": "10.8.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.8.0.tgz",
"integrity": "sha512-scYzM/UOItu4PjEq6CpHLdArpXjIS0laHYxE4YjkIbYIH6VMcXGQbD/FSBClsnCr1wXRnlXfXBzj0hrQAFyw+Q==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.17",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
@@ -7316,6 +7393,31 @@
"node": ">=14.0.0"
}
},
"node_modules/tauri-plugin-sentry-api": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/tauri-plugin-sentry-api/-/tauri-plugin-sentry-api-0.4.1.tgz",
"integrity": "sha512-KgfL7JhN51TOA3e0UYDu6UkdwgH+wC1/RC3qIHJOZIAsvyTfde4uifUFB11GfgXfHgY33xUkIGgqWKkaK5lg6Q==",
"license": "Apache-2.0 OR MIT",
"dependencies": {
"@tauri-apps/api": "2.0.0-beta.8",
"tslib": "^2.6.0"
}
},
"node_modules/tauri-plugin-sentry-api/node_modules/@tauri-apps/api": {
"version": "2.0.0-beta.8",
"resolved": "https://registry.npmjs.org/@tauri-apps/api/-/api-2.0.0-beta.8.tgz",
"integrity": "sha512-fN5u+9HsSfhRaXGOdD2kPGbqDgyX+nkm1XF/4d/LNuM4WiNfvHjjRAqWQYBhQsg1aF9nsTPmSW+tmy+Yn5T5+A==",
"license": "Apache-2.0 OR MIT",
"engines": {
"node": ">= 18",
"npm": ">= 6.6.0",
"yarn": ">= 1.19.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/tauri"
}
},
"node_modules/terser": {
"version": "5.37.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+2
View File
@@ -20,6 +20,7 @@
},
"dependencies": {
"@heroui/react": "^2.7.11",
"@sentry/browser": "^10.8.0",
"@tauri-apps/api": "~2.7.0",
"@tauri-apps/plugin-autostart": "^2.5.0",
"@tauri-apps/plugin-clipboard-manager": "^2.3.0",
@@ -44,6 +45,7 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.28.1",
"tauri-plugin-sentry-api": "^0.4.1",
"use-broadcast-ts": "^2.0.1",
"use-debounce": "^10.0.5",
"zustand": "^5.0.7"
+1
View File
@@ -82,6 +82,7 @@ pub fn run() {
let _guard = minidump::init(&client);
let mut app = tauri::Builder::default()
.plugin(tauri_plugin_sentry::init_with_no_injection(&client))
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_os::init())
+3
View File
@@ -1,6 +1,7 @@
import { Autocomplete, Tooltip } from '@heroui/react'
import { AutocompleteItem, Button } from '@heroui/react'
import { cn } from '@heroui/react'
import * as Sentry from '@sentry/browser'
import { open } from '@tauri-apps/plugin-dialog'
import { readDir } from '@tauri-apps/plugin-fs'
import { platform } from '@tauri-apps/plugin-os'
@@ -356,6 +357,7 @@ export function PathField({
setPath(selected as string)
}
} catch (err) {
Sentry.captureException(err)
console.error('Failed to open folder picker:', err)
setError('Failed to open folder picker')
}
@@ -585,6 +587,7 @@ export function MultiPathField({
}
}
} catch (err) {
Sentry.captureException(err)
console.error('Failed to open folder picker:', err)
setError('Failed to open folder picker')
}
+4
View File
@@ -15,6 +15,7 @@ import {
Textarea,
cn,
} from '@heroui/react'
import * as Sentry from '@sentry/browser'
import { getTauriVersion, getVersion as getUiVersion } from '@tauri-apps/api/app'
import {
appDataDir,
@@ -280,6 +281,7 @@ function GeneralSection() {
timeout: 30000,
})
} catch (e) {
Sentry.captureException(e)
console.error(e)
setUpdateButtonText('Failed to check')
return
@@ -295,6 +297,7 @@ function GeneralSection() {
setUpdate(receivedUpdate)
setUpdateButtonText('Tap to update')
} catch (e) {
Sentry.captureException(e)
console.error(e)
} finally {
setIsWorkingUpdate(false)
@@ -328,6 +331,7 @@ function GeneralSection() {
}
})
} catch (error) {
Sentry.captureException(error)
console.error(error)
setIsWorkingUpdate(false)
setUpdateButtonText('Tap to retry')