mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
feat: cache report error
This commit is contained in:
parent
bcc34949ab
commit
919ce07b20
6 changed files with 76 additions and 14 deletions
|
|
@ -2,6 +2,8 @@ import * as Sentry from '@sentry/browser'
|
|||
import { Middleware } from 'driver/connect.js'
|
||||
import { IN_PRODUCTION_MODE, VERSION } from 'env'
|
||||
import { platform } from 'platforms'
|
||||
import { atomicAsyncFunction } from 'utils/general'
|
||||
import { storageHelper, storageKeys } from 'utils/storageHelper'
|
||||
|
||||
const PUBLIC_KEY = 'd22ec5c9cc874539a51c78388c12e3b0'
|
||||
const PROJECT_ID = '1406497'
|
||||
|
|
@ -69,12 +71,43 @@ export const withErrorLog: Middleware = function withErrorLog(method, args) {
|
|||
]
|
||||
}
|
||||
|
||||
export function raiseError(
|
||||
// 1. Only cache errors for current version, so that future errors can still be exposed
|
||||
// - Run migration to clean on every update
|
||||
|
||||
// 2. Only cache the top 2 levels of stack, e.g.
|
||||
// ```
|
||||
// Error: cannot get current branch
|
||||
// at Module.getCurrentBranch (chrome-extension://______id______/index.js:1:1)"
|
||||
// ```
|
||||
// So that different initial callees would not result in multiple records
|
||||
const MAX_STACK_LEVEL = 2
|
||||
const hasTheErrorBeenReported = atomicAsyncFunction(async function hasTheErrorBeenReported(
|
||||
error: Error,
|
||||
) {
|
||||
const message = error.stack?.split('\n').slice(0, MAX_STACK_LEVEL).join('\n')
|
||||
if (!message) return true // ignore errors that has no stack
|
||||
|
||||
type ErrorCache = string
|
||||
const cache: ErrorCache[] =
|
||||
(await storageHelper.get(storageKeys.raiseErrorCache))?.[storageKeys.raiseErrorCache] || []
|
||||
const has = cache.includes(message)
|
||||
|
||||
if (!has) {
|
||||
cache.push(message)
|
||||
await storageHelper.set({ [storageKeys.raiseErrorCache]: cache })
|
||||
}
|
||||
|
||||
return has
|
||||
})
|
||||
|
||||
export async function raiseError(
|
||||
error: Error,
|
||||
extra?: {
|
||||
[key: string]: any
|
||||
},
|
||||
) {
|
||||
if (await hasTheErrorBeenReported(error)) return
|
||||
|
||||
if (!IN_PRODUCTION_MODE || platform.isEnterprise()) {
|
||||
// ignore errors from enterprise to get less noise on Sentry
|
||||
console.error(error)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { SearchMode } from 'components/searchModes'
|
||||
import { platformName } from 'platforms'
|
||||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Storage, storageHelper } from 'utils/storageHelper'
|
||||
import { migrateConfig } from './migrations'
|
||||
|
||||
export type Config = {
|
||||
|
|
@ -83,7 +83,7 @@ function applyDefaultConfigs(configs: Partial<Config>) {
|
|||
}, {} as Config)
|
||||
}
|
||||
|
||||
export type VersionedConfig<SiteConfig> = Record<string, SiteConfig> & { configVersion: string }
|
||||
export type VersionedConfig<SiteConfig> = Record<string, SiteConfig> & Storage
|
||||
|
||||
export const configRef: Partial<Config> = {}
|
||||
const updateConfigRef = async (config: Partial<Config>) => {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration } from '.'
|
||||
import { Storage } from '../../storageHelper'
|
||||
import { Config, VersionedConfig } from '../helper'
|
||||
|
||||
export const migration: Migration = {
|
||||
version: '1.3.4',
|
||||
async migrate(version) {
|
||||
const config: any | void = await storageHelper.get<VersionedConfig<Config> & Storage>([
|
||||
const config: any | void = await storageHelper.get<VersionedConfig<Config>>([
|
||||
'configVersion',
|
||||
'platform_undefined',
|
||||
'platform_GitHub',
|
||||
|
|
|
|||
13
src/utils/config/migrations/clearRaiseErrorCache.ts
Normal file
13
src/utils/config/migrations/clearRaiseErrorCache.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { Migration, onConfigOutdated } from '.'
|
||||
import { version } from '../../../../package.json'
|
||||
|
||||
// Run every time a new version is released.
|
||||
export const migration: Migration = {
|
||||
version,
|
||||
async migrate(version) {
|
||||
await onConfigOutdated(version, async () => {
|
||||
await storageHelper.set({ raiseErrorCache: [] })
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
import { storageHelper } from 'utils/storageHelper'
|
||||
import { storageHelper, storageKeys } from 'utils/storageHelper'
|
||||
import { version } from '../../../../package.json'
|
||||
import { Storage } from '../../storageHelper'
|
||||
import { migration as v1v0v1 } from './1.0.1'
|
||||
import { migration as v1v3v4 } from './1.3.4'
|
||||
import { migration as v2v6v0 } from './2.6.0'
|
||||
import { migration as v3v0v0 } from './3.0.0'
|
||||
import { migration as v3v5v0 } from './3.5.0'
|
||||
import { migration as clearRaiseErrorCache } from './clearRaiseErrorCache'
|
||||
|
||||
export type Migration = {
|
||||
version: string
|
||||
|
|
@ -13,21 +15,29 @@ export type Migration = {
|
|||
|
||||
export async function migrateConfig() {
|
||||
const migrations: Migration[] = [v1v0v1, v1v3v4, v2v6v0, v3v0v0, v3v5v0]
|
||||
migrations.push(clearRaiseErrorCache) // Make sure this is run after other version-specific migrations
|
||||
|
||||
for (const { version, migrate } of migrations) {
|
||||
await migrate(version)
|
||||
}
|
||||
|
||||
await storageHelper.set({ [storageKeys.configVersion]: version })
|
||||
}
|
||||
|
||||
export async function onConfigOutdated<T extends { [key: string]: any }>(
|
||||
configVersion: string,
|
||||
migrationConfigVersion: string,
|
||||
runIfOutdated: (config: T) => Async<void>,
|
||||
) {
|
||||
const config = await storageHelper.get<Storage>()
|
||||
|
||||
if (config && config.configVersion < configVersion) {
|
||||
const { configVersion: $configVersion, ...restConfig } = config
|
||||
await runIfOutdated(restConfig as T)
|
||||
await storageHelper.set({ configVersion })
|
||||
if (config) {
|
||||
const {
|
||||
[storageKeys.configVersion]: savedConfigVersion,
|
||||
[storageKeys.raiseErrorCache]: __,
|
||||
...restConfig
|
||||
} = config
|
||||
if (savedConfigVersion < migrationConfigVersion) {
|
||||
await runIfOutdated(restConfig as T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
const localStorage = browser.storage.local
|
||||
|
||||
const keys = {
|
||||
configVersion: 'configVersion',
|
||||
raiseErrorCache: 'raiseErrorCache',
|
||||
} as const
|
||||
|
||||
export const storageKeys = keys
|
||||
|
||||
export type Storage = {
|
||||
// save root level `configVersion` for easier future migrating
|
||||
[key in EnumString<'configVersion'>]: string
|
||||
// save root level keys for easier future migrating
|
||||
[key in EnumString<keyof typeof keys>]: string
|
||||
|
||||
// separate different platform configs to simplify interactions with browser storage API
|
||||
// e.g.
|
||||
|
|
@ -12,7 +19,7 @@ export type Storage = {
|
|||
async function get<
|
||||
T extends {
|
||||
[key: string]: any
|
||||
}
|
||||
},
|
||||
>(mapping: string | string[] | null = null): Promise<T | undefined> {
|
||||
try {
|
||||
return (await localStorage.get(mapping || undefined)) as T
|
||||
|
|
|
|||
Loading…
Reference in a new issue