/** * App-level logger. In development, delegates to console. In production, * routes errors/warnings to Sentry and silences debug noise. */ import * as Sentry from "@sentry/react-router"; const isDev = process.env.NODE_ENV !== "production"; /** Splits args into the first Error found and everything else (for Sentry context). */ function splitArgs(args: unknown[]): { err: Error | undefined; extra: unknown[] } { const err = args.find((a): a is Error => a instanceof Error); const extra = args.filter((a) => a !== err); return { err, extra }; } function log(...args: unknown[]): void { if (isDev) console.log(...args); } function info(...args: unknown[]): void { if (isDev) console.info(...args); } function warn(...args: unknown[]): void { if (isDev) { console.warn(...args); } else { const { err, extra } = splitArgs(args); if (err) { Sentry.captureException(err, { level: "warning", extra: { context: extra } }); } else { Sentry.captureMessage(String(args[0]), { level: "warning", extra: { args: extra.slice(1) }, }); } } } function error(...args: unknown[]): void { if (isDev) { console.error(...args); } else { const { err, extra } = splitArgs(args); if (err) { Sentry.captureException(err, extra.length ? { extra: { context: extra } } : undefined); } else { Sentry.captureMessage(String(args[0]), { level: "error", extra: { args: extra.slice(1) }, }); } } } export const logger = { log, info, warn, error };