mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 16:15:39 +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
35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
import type { Frame } from './stack';
|
|
|
|
/** How many of the top frames make up a fingerprint. */
|
|
export const FINGERPRINT_FRAMES = 5;
|
|
|
|
/**
|
|
* 64-bit FNV-1a as 16 hex digits. Synchronous and the same in the browser and
|
|
* on the server; not for security, only for grouping.
|
|
*/
|
|
export function hash64(text: string): string {
|
|
let h1 = 0x811c9dc5;
|
|
let h2 = 0xcbf29ce4;
|
|
for (let i = 0; i < text.length; i++) {
|
|
const c = text.charCodeAt(i);
|
|
h1 = Math.imul(h1 ^ c, 0x01000193) >>> 0;
|
|
h2 = Math.imul(h2 ^ c ^ (h1 >>> 7), 0x01000193) >>> 0;
|
|
}
|
|
return h1.toString(16).padStart(8, '0') + h2.toString(16).padStart(8, '0');
|
|
}
|
|
|
|
/**
|
|
* The fingerprint of an error: its name, the top frames (file without origin,
|
|
* line, column) and the Bulwark version. The same error in another release is
|
|
* another fingerprint, because its frames point into other chunks anyway.
|
|
* `code` is one of Bulwark's fixed error codes (a JMAP error type), for
|
|
* errors that are all raised from the same place.
|
|
*/
|
|
export function fingerprint(name: string, frames: readonly Frame[], version: string, code?: string): string {
|
|
const top = frames
|
|
.filter((frame) => frame.path !== '[other]')
|
|
.slice(0, FINGERPRINT_FRAMES)
|
|
.map((frame) => `${frame.path}:${frame.line ?? ''}:${frame.column ?? ''}`);
|
|
return hash64([name, code ?? '', ...top, version].join('|'));
|
|
}
|