mirror of https://github.com/nocodb/nocodb
Browse Source
* 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>pull/9601/head
Pranav C
2 months ago
committed by
GitHub
9 changed files with 210 additions and 10 deletions
@ -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) |
||||
}) |
Loading…
Reference in new issue