import * as Sentry from '@sentry/nextjs'; import { addLocalLog, addLogLine } from '@ente/shared/logging'; import { getSentryUserID, isErrorUnnecessaryForSentry, } from '@ente/shared/sentry/utils'; import InMemoryStore, { MS_KEYS } from '@ente/shared/storage/InMemoryStore'; import { getHasOptedOutOfCrashReports } from '@ente/shared/storage/localStorage/helpers'; import { ApiError, errorWithContext } from '@ente/shared/error'; export const logError = async ( error: any, msg: string, info?: Record, skipAddLogLine = false ) => { const err = errorWithContext(error, msg); if (!skipAddLogLine) { if (error instanceof ApiError) { addLogLine(`error: ${error?.name} ${error?.message} msg: ${msg} errorCode: ${JSON.stringify(error?.errCode)} httpStatusCode: ${JSON.stringify(error?.httpStatusCode)} ${ info ? `info: ${JSON.stringify(info)}` : '' } ${error?.stack}`); } else { addLogLine( `error: ${error?.name} ${error?.message} msg: ${msg} ${info ? `info: ${JSON.stringify(info)}` : ''} ${error?.stack}` ); } } if (!InMemoryStore.has(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { const optedOutOfCrashReports = getHasOptedOutOfCrashReports(); InMemoryStore.set( MS_KEYS.OPT_OUT_OF_CRASH_REPORTS, optedOutOfCrashReports ); } if (InMemoryStore.get(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { addLocalLog(() => `skipping sentry error: ${error?.name}`); return; } if (isErrorUnnecessaryForSentry(error)) { return; } Sentry.captureException(err, { level: 'info', user: { id: await getSentryUserID() }, contexts: { ...(info && { info: info, }), rootCause: { message: error?.message, completeError: error }, }, }); };