Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | 7x 2x 1x 4x 6x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x | // Browser-side Sentry init for the marketplace. Loaded once via a module
// `<script>` in the shared layout, so it runs on every page.
//
// DSN + environment are build-time values inlined through the astro.config
// `define` block (PUBLIC_SENTRY_DSN / PUBLIC_ENVIRONMENT). With no DSN, or
// locally, this module does nothing and the SDK (~28 KB gzip) is never
// fetched: it is a dynamic import, split into its own chunk.
//
// While the SDK loads, uncaught errors and unhandled rejections are queued and
// replayed into Sentry once it is up, so the first moments of a page are
// still covered.
//
// Errors + browser tracing only (no Session Replay): the marketplace is
// LCP-sensitive and Replay roughly doubles the client SDK weight. Add
// `Sentry.replayIntegration()` here if replay is later prioritized.
import type { BrowserOptions } from "@sentry/browser";
type SentrySdk = typeof import("./sentry-sdk");
// Through a re-export module, not import("@sentry/browser") itself: a dynamic
// import of the package namespace can't be tree-shaken (it pulled in ~146 KB
// gzip with Replay; destructuring the import still left ~48 KB).
const loadSdk = (): Promise<SentrySdk> => import("./sentry-sdk");
export function tracesSampleRate(environment: string): number {
switch (environment) {
case "production":
return 0.1;
case "preview":
return 0.5;
default:
return 1.0;
}
}
/**
* Build the Sentry browser init options (minus SDK-built integrations), or
* `null` when Sentry should stay disabled (no DSN, or running locally). Pure +
* exported so the gating logic is unit-testable without loading the SDK.
*/
export function sentryClientOptions(
dsn: string | undefined,
environment: string,
): BrowserOptions | null {
if (!dsn || environment === "local") return null;
return {
dsn,
environment,
tracesSampleRate: tracesSampleRate(environment),
};
}
/**
* Queue early errors, load the SDK, init it with browser tracing, then replay
* the queue. `load` is injectable for tests.
*/
export async function initSentryClient(
options: BrowserOptions,
load: () => Promise<SentrySdk> = loadSdk,
): Promise<void> {
const early: unknown[] = [];
const onError = (e: ErrorEvent) => early.push(e.error ?? e.message);
const onRejection = (e: PromiseRejectionEvent) => early.push(e.reason);
window.addEventListener("error", onError);
window.addEventListener("unhandledrejection", onRejection);
try {
const Sentry = await load();
Sentry.init({
...options,
integrations: [Sentry.browserTracingIntegration()],
});
for (const err of early) Sentry.captureException(err);
} finally {
window.removeEventListener("error", onError);
window.removeEventListener("unhandledrejection", onRejection);
}
}
const options = sentryClientOptions(
import.meta.env.PUBLIC_SENTRY_DSN as string | undefined,
(import.meta.env.PUBLIC_ENVIRONMENT as string | undefined) || "local",
);
Iif (options) void initSentryClient(options).catch(() => {});
|