mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-23 11:44:06 -08:00
feat(editor): Improve Sentry ignore definitions for class instance types (no-changelog) (#11208)
Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
parent
6c6a8efdea
commit
3d2fbcfd93
|
@ -252,6 +252,7 @@ export class Server extends AbstractServer {
|
|||
JSON.stringify({
|
||||
dsn: this.globalConfig.sentry.frontendDsn,
|
||||
environment: process.env.ENVIRONMENT || 'development',
|
||||
serverName: process.env.DEPLOYMENT_NAME,
|
||||
release: N8N_VERSION,
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { createApp } from 'vue';
|
||||
import * as Sentry from '@sentry/vue';
|
||||
|
||||
import '@vue-flow/core/dist/style.css';
|
||||
import '@vue-flow/core/dist/theme-default.css';
|
||||
|
@ -30,32 +29,13 @@ import { FontAwesomePlugin } from './plugins/icons';
|
|||
import { createPinia, PiniaVuePlugin } from 'pinia';
|
||||
import { JsPlumbPlugin } from '@/plugins/jsplumb';
|
||||
import { ChartJSPlugin } from '@/plugins/chartjs';
|
||||
import { AxiosError } from 'axios';
|
||||
import { SentryPlugin } from '@/plugins/sentry';
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
if (window.sentry?.dsn) {
|
||||
const { dsn, release, environment } = window.sentry;
|
||||
Sentry.init({
|
||||
app,
|
||||
dsn,
|
||||
release,
|
||||
environment,
|
||||
beforeSend(event, { originalException }) {
|
||||
if (
|
||||
!originalException ||
|
||||
originalException instanceof AxiosError ||
|
||||
(originalException instanceof Error && originalException.message.includes('ResizeObserver'))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
app.use(SentryPlugin);
|
||||
app.use(TelemetryPlugin);
|
||||
app.use(PiniaVuePlugin);
|
||||
app.use(I18nPlugin);
|
||||
|
|
46
packages/editor-ui/src/plugins/sentry.spec.ts
Normal file
46
packages/editor-ui/src/plugins/sentry.spec.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import type * as Sentry from '@sentry/vue';
|
||||
import { beforeSend } from '@/plugins/sentry';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ResponseError } from '@/utils/apiUtils';
|
||||
|
||||
function createErrorEvent(): Sentry.ErrorEvent {
|
||||
return {} as Sentry.ErrorEvent;
|
||||
}
|
||||
|
||||
describe('beforeSend', () => {
|
||||
it('should return null when originalException is undefined', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: undefined };
|
||||
expect(beforeSend(event, hint)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when originalException matches ignoredErrors by instance and message', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: new ResponseError("Can't connect to n8n.") };
|
||||
expect(beforeSend(event, hint)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when originalException matches ignoredErrors by instance and message regex', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: new ResponseError('ECONNREFUSED') };
|
||||
expect(beforeSend(event, hint)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when originalException matches ignoredErrors by instance only', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: new AxiosError() };
|
||||
expect(beforeSend(event, hint)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when originalException matches ignoredErrors by instance and message regex (ResizeObserver)', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: new Error('ResizeObserver loop limit exceeded') };
|
||||
expect(beforeSend(event, hint)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return event when originalException does not match any ignoredErrors', () => {
|
||||
const event = createErrorEvent();
|
||||
const hint = { originalException: new Error('Some other error') };
|
||||
expect(beforeSend(event, hint)).toEqual(event);
|
||||
});
|
||||
});
|
59
packages/editor-ui/src/plugins/sentry.ts
Normal file
59
packages/editor-ui/src/plugins/sentry.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import type { Plugin } from 'vue';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ResponseError } from '@/utils/apiUtils';
|
||||
import * as Sentry from '@sentry/vue';
|
||||
|
||||
const ignoredErrors = [
|
||||
{ instanceof: AxiosError },
|
||||
{ instanceof: ResponseError, message: /ECONNREFUSED/ },
|
||||
{ instanceof: ResponseError, message: "Can't connect to n8n." },
|
||||
{ instanceof: Error, message: /ResizeObserver/ },
|
||||
] as const;
|
||||
|
||||
export function beforeSend(event: Sentry.ErrorEvent, { originalException }: Sentry.EventHint) {
|
||||
if (
|
||||
!originalException ||
|
||||
ignoredErrors.some((entry) => {
|
||||
const typeMatch = originalException instanceof entry.instanceof;
|
||||
if (!typeMatch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('message' in entry) {
|
||||
if (entry.message instanceof RegExp) {
|
||||
return entry.message.test(originalException.message ?? '');
|
||||
} else {
|
||||
return originalException.message === entry.message;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
export const SentryPlugin: Plugin = {
|
||||
install: (app) => {
|
||||
if (!window.sentry?.dsn) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { dsn, release, environment, serverName } = window.sentry;
|
||||
|
||||
Sentry.init({
|
||||
app,
|
||||
dsn,
|
||||
release,
|
||||
environment,
|
||||
beforeSend,
|
||||
});
|
||||
|
||||
if (serverName) {
|
||||
Sentry.setTag('server_name', serverName);
|
||||
}
|
||||
},
|
||||
};
|
2
packages/editor-ui/src/shims.d.ts
vendored
2
packages/editor-ui/src/shims.d.ts
vendored
|
@ -18,7 +18,7 @@ declare global {
|
|||
interface Window {
|
||||
BASE_PATH: string;
|
||||
REST_ENDPOINT: string;
|
||||
sentry?: { dsn?: string; environment: string; release: string };
|
||||
sentry?: { dsn?: string; environment: string; release: string; serverName?: string };
|
||||
n8nExternalHooks?: PartialDeep<ExternalHooks>;
|
||||
preventNodeViewBeforeUnload?: boolean;
|
||||
maxPinnedDataSize?: number;
|
||||
|
|
Loading…
Reference in a new issue