Skip to content

Commit

Permalink
refactor(core): Consolidate path-related errors in Sentry (no-changel…
Browse files Browse the repository at this point in the history
…og) (#7757)

Keep reporting [path-related
errors](https://n8nio.sentry.io/issues/4649493725) in Sentry but
consolidate them in a single error group.

Also, add `options.extra` as `meta` so they remain visible in debug
logs:

```
2023-11-24T11:50:54.852Z | error    | ReportableError: Something went wrong "{ test: 123, file: 'LoggerProxy.js', function: 'exports.error' }"
```

---------

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
  • Loading branch information
ivov and netroy committed Nov 24, 2023
1 parent 5914e97 commit eec2ec1
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 22 deletions.
11 changes: 10 additions & 1 deletion packages/cli/src/ErrorReporting.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createHash } from 'crypto';
import config from '@/config';
import { ErrorReporterProxy, ExecutionBaseError } from 'n8n-workflow';
import { ErrorReporterProxy, ExecutionBaseError, ReportableError } from 'n8n-workflow';

let initialized = false;

Expand Down Expand Up @@ -41,10 +41,19 @@ export const initErrorHandling = async () => {
addGlobalEventProcessor((event, { originalException }) => {
if (originalException instanceof ExecutionBaseError && originalException.severity === 'warning')
return null;

if (originalException instanceof ReportableError) {
const { level, extra } = originalException;
if (level === 'warning') return null;
event.level = level;
if (extra) event.extra = { ...event.extra, ...extra };
}

if (!event.exception) return null;
const eventHash = createHash('sha1').update(JSON.stringify(event.exception)).digest('base64');
if (seenErrors.has(eventHash)) return null;
seenErrors.add(eventHash);

return event;
});

Expand Down
13 changes: 0 additions & 13 deletions packages/core/src/errors.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/core/src/errors/filesystem.errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ReportableError } from 'n8n-workflow';

abstract class FileSystemError extends ReportableError {
constructor(message: string, filePath: string) {
super(message, { extra: { filePath } });
}
}

export class FileNotFoundError extends FileSystemError {
constructor(filePath: string) {
super('File not found', filePath);
}
}

export class BinaryFileNotFoundError extends FileNotFoundError {}

export class InvalidPathError extends FileSystemError {
constructor(filePath: string) {
super('Invalid path detected', filePath);
}
}
1 change: 1 addition & 0 deletions packages/core/src/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { BinaryFileNotFoundError, FileNotFoundError, InvalidPathError } from './filesystem.errors';
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as NodeExecuteFunctions from './NodeExecuteFunctions';

export * from './errors';
export * from './ActiveWorkflows';
export * from './BinaryData/BinaryData.service';
export * from './BinaryData/types';
Expand Down
11 changes: 3 additions & 8 deletions packages/workflow/src/ErrorReporterProxy.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import type { Primitives } from './utils';
import * as Logger from './LoggerProxy';

export interface ReportingOptions {
level?: 'warning' | 'error' | 'fatal';
tags?: Record<string, Primitives>;
extra?: Record<string, unknown>;
}
import { ReportableError, type ReportingOptions } from './errors/reportable.error';

interface ErrorReporter {
report: (error: Error | string, options?: ReportingOptions) => void;
Expand All @@ -16,7 +10,8 @@ const instance: ErrorReporter = {
if (error instanceof Error) {
let e = error;
do {
Logger.error(`${e.constructor.name}: ${e.message}`);
const meta = e instanceof ReportableError ? e.extra : undefined;
Logger.error(`${e.constructor.name}: ${e.message}`, meta);
e = e.cause as Error;
} while (e);
}
Expand Down
1 change: 1 addition & 0 deletions packages/workflow/src/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ReportableError } from './reportable.error';
24 changes: 24 additions & 0 deletions packages/workflow/src/errors/reportable.error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Event } from '@sentry/node';

type Level = 'warning' | 'error' | 'fatal';

export type ReportingOptions = {
level?: Level;
} & Pick<Event, 'tags' | 'extra'>;

export type ReportableErrorOptions = Partial<ErrorOptions> & ReportingOptions;

export class ReportableError extends Error {
readonly level: Level;

readonly tags?: Event['tags'];

readonly extra?: Event['extra'];

constructor(message: string, { level, tags, extra, ...rest }: ReportableErrorOptions) {
super(message, rest);
this.level = level ?? 'error';
this.tags = tags;
this.extra = extra;
}
}
1 change: 1 addition & 0 deletions packages/workflow/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as NodeHelpers from './NodeHelpers';
import * as ObservableObject from './ObservableObject';
import * as TelemetryHelpers from './TelemetryHelpers';

export * from './errors';
export * from './Authentication';
export * from './Constants';
export * from './Cron';
Expand Down

0 comments on commit eec2ec1

Please sign in to comment.