File size: 1,717 Bytes
1a00f18
7b0c22b
1a00f18
 
 
 
 
 
7b0c22b
1a00f18
 
7b0c22b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1a00f18
 
 
 
 
7b0c22b
1a00f18
 
7b0c22b
 
 
 
 
 
 
 
 
 
1a00f18
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { logger } from '../logger';
import * as Sentry from '@sentry/node';

export interface ErrorContext {
    organizationId?: string;
    userId?: string;
    jobId?: string;
    jobName?: string;
    extra?: Record<string, unknown>;
}

let sentryInitialized = false;

export function initSentry() {
    const dsn = process.env.SENTRY_DSN;
    if (!dsn) {
        logger.info('[SENTRY] SENTRY_DSN not set — error reporting via logger only');
        return;
    }
    Sentry.init({
        dsn,
        environment: process.env.NODE_ENV || 'production',
        tracesSampleRate: 0.1,
    });
    sentryInitialized = true;
    logger.info('[SENTRY] Initialized');
}

export const reportError = (error: unknown, context: ErrorContext) => {
    const errorMessage = error instanceof Error ? error.message : String(error);
    const errorStack = error instanceof Error ? error.stack : undefined;

    logger.error({
        msg: `[ERROR-REPORT] ${context.jobName || 'unknown'}: ${errorMessage}`,
        context: { ...context, stack: errorStack }
    });

    if (sentryInitialized) {
        Sentry.withScope(scope => {
            scope.setTags({
                jobName: context.jobName ?? 'unknown',
                organizationId: context.organizationId ?? 'unknown',
            });
            if (context.extra) scope.setExtras(context.extra);
            Sentry.captureException(error);
        });
    }
};

export const withErrorLogging = async <T>(
    task: () => Promise<T>,
    context: ErrorContext
): Promise<T | undefined> => {
    try {
        return await task();
    } catch (error) {
        reportError(error, context);
        throw error; // Rethrow to let BullMQ handle retries
    }
};