feat(errors): add Sentry observability behind a sinks facade
logError / reportError now route through a pair of sinks installed at
bootstrap by each process (main + every renderer entry). No call site
knows about Sentry — if sentryDsn is empty, the sinks simply aren't
installed and logError/reportError stay console-only.
- appConfig.sentryDsn: per-env string (empty for now — populate when
ops creates the DSNs). Empty is the no-op mode for dev.
- lib/errors.ts: installErrorSinks({ capture, breadcrumb }) gates
Sentry.captureException / Sentry.addBreadcrumb. Everything flows
through toUserMessage and the two existing call types.
- lib/sentry.ts: initSentryRenderer() for the main window + autoplay,
huddle, and screen-record renderers.
- main/sentry.ts: initSentryMain() runs before anything else in
main.ts to catch bootstrap failures. Captures uncaught exceptions
and the crash reporter automatically.
- main/ipc-utils.ts::safeHandle now routes through reportError.
- main.ts::fetchLinkMetadata logs via logError.
This commit is contained in:
+19
-2
@@ -59,17 +59,34 @@ export function toUserMessage(err: unknown): string {
|
||||
}
|
||||
|
||||
type ErrorContext = Record<string, unknown>;
|
||||
type ErrorSink = (err: unknown, context?: ErrorContext) => void;
|
||||
|
||||
/** Expected-but-recordable failures. Dev logs; prod is currently a no-op. */
|
||||
// Sentry (or any observability backend) installs itself via `installErrorSinks`
|
||||
// from renderer.tsx / main.ts. Until then, logError is a dev-only console call
|
||||
// and reportError always prints — no call site needs to know.
|
||||
let captureSink: ErrorSink | null = null;
|
||||
let breadcrumbSink: ErrorSink | null = null;
|
||||
|
||||
export function installErrorSinks(sinks: {
|
||||
capture: ErrorSink;
|
||||
breadcrumb: ErrorSink;
|
||||
}): void {
|
||||
captureSink = sinks.capture;
|
||||
breadcrumbSink = sinks.breadcrumb;
|
||||
}
|
||||
|
||||
/** Expected-but-recordable failures. Breadcrumb only — never pages anyone. */
|
||||
export function logError(err: unknown, context?: ErrorContext): void {
|
||||
if (appEnv === "dev") {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[error]", err, context ?? {});
|
||||
}
|
||||
breadcrumbSink?.(err, context);
|
||||
}
|
||||
|
||||
/** Unexpected failures the user may not see. Always surfaces somewhere. */
|
||||
/** Unexpected failures the user may not see. Always captured. */
|
||||
export function reportError(err: unknown, context?: ErrorContext): void {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("[error]", err, context ?? {});
|
||||
captureSink?.(err, context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user