mirror of
https://github.com/nocodb/nocodb.git
synced 2026-05-01 09:57:21 +00:00
refactor: GUI error handling (#9528)
* refactor: error reporting Signed-off-by: Pranav C <pranavxc@gmail.com> * refactor: handle ee part Signed-off-by: Pranav C <pranavxc@gmail.com> * refactor: coderabbit review comments Signed-off-by: Pranav C <pranavxc@gmail.com> * refactor: linting Signed-off-by: Pranav C <pranavxc@gmail.com> * refactor: remove duplicate error log Signed-off-by: Pranav C <pranavxc@gmail.com> * refactor: request type correction Signed-off-by: Pranav C <pranavxc@gmail.com> --------- Signed-off-by: Pranav C <pranavxc@gmail.com>
This commit is contained in:
92
packages/nc-gui/plugins/error-reporting.ts
Normal file
92
packages/nc-gui/plugins/error-reporting.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import * as Sentry from '@sentry/vue'
|
||||
import type { Api } from 'nocodb-sdk'
|
||||
|
||||
class ErrorReporting {
|
||||
errors: Error[] = []
|
||||
|
||||
// debounce error reporting to avoid sending multiple reports for the same error
|
||||
private report = useDebounceFn(
|
||||
() => {
|
||||
try {
|
||||
const errors = this.errors
|
||||
// filter out duplicate errors and only include 2 lines of stack trace
|
||||
.filter((error, index, self) => index === self.findIndex((t) => t.message === error.message))
|
||||
.map((error) => ({
|
||||
message: error.message,
|
||||
stack: error.stack?.split('\n').slice(0, 2).join('\n'),
|
||||
}))
|
||||
this.errors = []
|
||||
this.$api.utils.errorReport({ errors, extra: {} })
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
3000,
|
||||
{
|
||||
maxWait: 10000,
|
||||
},
|
||||
)
|
||||
|
||||
constructor(private $api: Api<unknown>) {}
|
||||
|
||||
// collect error to report later
|
||||
collect(error: Error) {
|
||||
this.errors.push(error)
|
||||
// report errors after 3 seconds
|
||||
this.report()
|
||||
}
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
if (isEeUI) {
|
||||
nuxtApp.provide('report', function (error: Error) {
|
||||
try {
|
||||
Sentry.captureException(error)
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const env = process.env.NODE_ENV === 'production' ? 'production' : 'development'
|
||||
let isSentryConfigured = false
|
||||
let isErrorReportingEnabled = false
|
||||
let errorReporting: ErrorReporting | null = null
|
||||
|
||||
// load error reporting only if enabled and sentryDSN is not provided
|
||||
watch(
|
||||
[
|
||||
() => (nuxtApp.$state as ReturnType<typeof useGlobal>).appInfo?.value?.errorReportingEnabled,
|
||||
() => (nuxtApp.$state as ReturnType<typeof useGlobal>).appInfo?.value?.sentryDSN,
|
||||
],
|
||||
([enabled, sentryDSN]) => {
|
||||
isSentryConfigured = enabled && !!sentryDSN
|
||||
isErrorReportingEnabled = enabled
|
||||
if (enabled && !sentryDSN) {
|
||||
errorReporting = new ErrorReporting(nuxtApp.$api as Api<unknown>)
|
||||
} else {
|
||||
errorReporting = null
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
function report(error: Error) {
|
||||
if (process.env.CI || process.env.PLAYWRIGHT) {
|
||||
return
|
||||
}
|
||||
|
||||
if (env !== 'production' && !process.env.NC_ENABLE_DEV_SENTRY) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isSentryConfigured) {
|
||||
Sentry.captureException(error)
|
||||
} else if (isErrorReportingEnabled) {
|
||||
errorReporting?.collect(error)
|
||||
}
|
||||
}
|
||||
|
||||
nuxtApp.provide('report', report)
|
||||
})
|
||||
Reference in New Issue
Block a user