mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 16:12:02 +00:00
Admins had logs and nothing else: client errors only reached the browser console. An admin can now set a Sentry-protocol address (DSN) for Bugsink, GlitchTip or Sentry under System > Monitoring, or with `ERROR_REPORTING_DSN`, `ERROR_REPORTING_DSN_FILE`, `ERROR_REPORTING_SAMPLE_RATE` and `ERROR_REPORTING_ENVIRONMENT`. Bulwark Lite reads the same from `errorReporting` in policy.json. Everything stays off while no address is set. - browsers report errors from the error boundaries, window.onerror, unhandled rejections and failed JMAP requests (method and error type only), with route and JMAP method breadcrumbs and the chunks' debug IDs - the server reports what Next hands to onRequestError and what routes log with logger.error - every report is scrubbed first: quoted text, addresses, URLs, file names, tokens and the rest after the first line are removed, and the server scrubs what browsers post to /api/errors again - reports are deduplicated and rate-limited per session and process - errors are counted per day for "errors today" on the admin page - startup messages and audit entries go through the logger, so `LOG_FORMAT=json` covers them
31 lines
1006 B
TypeScript
31 lines
1006 B
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { usePathname } from "next/navigation";
|
|
import { fetchConfig } from "@/hooks/use-config";
|
|
import { installGlobalHandlers, recordNavigation } from "@/lib/error-reporting/client";
|
|
|
|
/**
|
|
* Starts browser error reporting: window.onerror and unhandled rejections,
|
|
* and a breadcrumb per route change (the route's area only, never the URL).
|
|
* Whether anything is sent is decided by the config (/api/config, or Lite's
|
|
* policy.json); until it arrives, reports wait, and with reporting off they
|
|
* are dropped. Renders nothing.
|
|
*/
|
|
export function ErrorReportingRoot() {
|
|
const pathname = usePathname();
|
|
|
|
useEffect(() => {
|
|
installGlobalHandlers();
|
|
// Cached after the first fetch; this only makes sure it happens on pages
|
|
// that don't read the config themselves (admin, setup).
|
|
void fetchConfig().catch(() => undefined);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (pathname) recordNavigation(pathname);
|
|
}, [pathname]);
|
|
|
|
return null;
|
|
}
|