More sentry monitoring

This commit is contained in:
2026-03-11 04:02:33 -04:00
parent 703510afa7
commit c2251ecfd4
7 changed files with 1633 additions and 1510 deletions

View File

@@ -1 +1 @@
v22.20.0 v24.14.0

View File

@@ -2,16 +2,20 @@ import { CacheProvider } from "@emotion/react";
import { ClientStyleContext } from "./context.js"; import { ClientStyleContext } from "./context.js";
import createEmotionCache from "./createEmotionCache.js"; import createEmotionCache from "./createEmotionCache.js";
import { hydrateRoot } from "react-dom/client"; import { hydrateRoot } from "react-dom/client";
import { RemixBrowser } from "@remix-run/react"; import { RemixBrowser, useLocation, useMatches } from "@remix-run/react";
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/remix";
import { type ReactNode, StrictMode, useState } from "react"; import { type ReactNode, StrictMode, useEffect, useState } from "react";
Sentry.init({ Sentry.init({
dsn: dsn:
document.querySelector("meta[name='dsn']")?.getAttribute("content") ?? document.querySelector("meta[name='dsn']")?.getAttribute("content") ??
undefined, undefined,
integrations: [ integrations: [
Sentry.browserTracingIntegration(), Sentry.browserTracingIntegration({
useEffect,
useLocation,
useMatches,
}),
Sentry.replayIntegration(), Sentry.replayIntegration(),
], ],
replaysOnErrorSampleRate: 1, replaysOnErrorSampleRate: 1,

View File

@@ -5,6 +5,7 @@ import { type EntryContext } from "@remix-run/cloudflare";
import { RemixServer } from "@remix-run/react"; import { RemixServer } from "@remix-run/react";
import { renderToString } from "react-dom/server"; import { renderToString } from "react-dom/server";
import { ServerStyleContext } from "./context.js"; import { ServerStyleContext } from "./context.js";
import * as Sentry from "@sentry/remix";
export default function handleRequest( export default function handleRequest(
request: Request, request: Request,
@@ -39,3 +40,5 @@ export default function handleRequest(
status: responseStatusCode, status: responseStatusCode,
}); });
} }
export const handleError = Sentry.sentryHandleError;

View File

@@ -18,6 +18,7 @@ import {
Scripts, Scripts,
useLoaderData, useLoaderData,
useRouteError, useRouteError,
useRouteLoaderData,
} from "@remix-run/react"; } from "@remix-run/react";
import { type ErrorResponse } from "@remix-run/router"; import { type ErrorResponse } from "@remix-run/router";
import { LinksFunction } from "@remix-run/cloudflare"; import { LinksFunction } from "@remix-run/cloudflare";
@@ -26,13 +27,14 @@ import Navigation from "../components/Navigation.js";
import { type ReactNode, StrictMode, useContext, useEffect } from "react"; import { type ReactNode, StrictMode, useContext, useEffect } from "react";
import theme from "../theme.js"; import theme from "../theme.js";
import { withEmotionCache } from "@emotion/react"; import { withEmotionCache } from "@emotion/react";
import { captureRemixErrorBoundaryError, withSentry } from "@sentry/remix";
export function ErrorBoundary() { export function ErrorBoundary() {
const error = useRouteError() as ErrorResponse; const error = useRouteError() as ErrorResponse;
if (!isRouteErrorResponse(error)) if (!isRouteErrorResponse(error))
return getMarkup( return (
{ hide: true }, <DocumentWrapper loaderData={{ hide: true }}>
<Container maxW="container.lg" pt="8vh" textAlign="left"> <Container maxW="container.lg" pt="8vh" textAlign="left">
<Heading size="4xl">???</Heading> <Heading size="4xl">???</Heading>
<br /> <br />
@@ -46,24 +48,34 @@ export function ErrorBoundary() {
<Link color="#646cff" onClick={() => location.reload()}> <Link color="#646cff" onClick={() => location.reload()}>
Refresh Refresh
</Link> </Link>
</Container>, </Container>
</DocumentWrapper>
); );
const { status } = error; const { status } = error;
const loaderData = useRouteLoaderData<typeof loader>("root") || {};
switch (status) { switch (status) {
case 303: case 303:
return ""; return "";
case 401: case 401:
return getMarkup({ hide: true }, <Login />); return (
<DocumentWrapper loaderData={loaderData}>
<Login />
</DocumentWrapper>
);
case 403: case 403:
return getMarkup({ hide: true }, <Forbidden />); return (
<DocumentWrapper loaderData={loaderData}>
<Forbidden />
</DocumentWrapper>
);
case 404: case 404:
return getMarkup( return (
{ hide: true }, <DocumentWrapper loaderData={loaderData}>
<Container maxW="container.lg" pt="8vh" textAlign="left"> <Container maxW="container.lg" pt="8vh" textAlign="left">
<Heading size="4xl">404</Heading> <Heading size="4xl">404</Heading>
<br /> <br />
@@ -74,12 +86,14 @@ export function ErrorBoundary() {
<Link color="#646cff" onClick={() => history.go(-1)}> <Link color="#646cff" onClick={() => history.go(-1)}>
Go back Go back
</Link> </Link>
</Container>, </Container>
</DocumentWrapper>
); );
default: default:
return getMarkup( captureRemixErrorBoundaryError(useRouteError());
{ hide: true }, return (
<DocumentWrapper loaderData={loaderData}>
<Container maxW="container.lg" pt="8vh" textAlign="left"> <Container maxW="container.lg" pt="8vh" textAlign="left">
<Heading size="4xl">500</Heading> <Heading size="4xl">500</Heading>
<br /> <br />
@@ -90,7 +104,8 @@ export function ErrorBoundary() {
<Link color="#646cff" onClick={() => location.reload()}> <Link color="#646cff" onClick={() => location.reload()}>
Reload Reload
</Link> </Link>
</Container>, </Container>
</DocumentWrapper>
); );
} }
} }
@@ -123,10 +138,11 @@ export function meta() {
return [{ title: "Car Crushers" }]; return [{ title: "Car Crushers" }];
} }
function getMarkup( function DocumentWrapper(props: {
loaderData: { [k: string]: any }, loaderData: { [k: string]: any };
child: ReactNode, children: ReactNode;
): JSX.Element { }) {
const { children: child, loaderData } = props;
const Document = withEmotionCache( const Document = withEmotionCache(
({ children }: { children: ReactNode }, emotionCache) => { ({ children }: { children: ReactNode }, emotionCache) => {
const serverStyleData = useContext(ServerStyleContext); const serverStyleData = useContext(ServerStyleContext);
@@ -207,8 +223,14 @@ function getMarkup(
return <Document>{child}</Document>; return <Document>{child}</Document>;
} }
export default function () { function App() {
const loaderData = useLoaderData<typeof loader>(); const loaderData = useLoaderData<typeof loader>();
return getMarkup(loaderData, <Outlet />); return (
<DocumentWrapper loaderData={loaderData}>
<Outlet />
</DocumentWrapper>
);
} }
export default withSentry(App);

View File

@@ -1,5 +1,6 @@
import getPermissions from "./permissions.js"; import getPermissions from "./permissions.js";
import { jsonError } from "./common.js"; import { jsonError } from "./common.js";
import * as Sentry from "@sentry/cloudflare";
async function constructHTML(context: RequestContext) { async function constructHTML(context: RequestContext) {
const { pathname } = new URL(context.request.url); const { pathname } = new URL(context.request.url);
@@ -354,6 +355,10 @@ async function setTheme(context: RequestContext) {
} }
export const onRequest = [ export const onRequest = [
Sentry.sentryPagesPlugin((context: RequestContext) => ({
dsn: context.env.DSN,
sendDefaultPii: true,
})),
setAuth, setAuth,
refreshAuth, refreshAuth,
setTheme, setTheme,

2990
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -16,17 +16,18 @@
"@remix-run/cloudflare": "^2.17.4", "@remix-run/cloudflare": "^2.17.4",
"@remix-run/cloudflare-pages": "^2.17.4", "@remix-run/cloudflare-pages": "^2.17.4",
"@remix-run/react": "^2.17.4", "@remix-run/react": "^2.17.4",
"@sentry/react": "^10.40.0", "@sentry/cloudflare": "^10.43.0",
"@sentry/remix": "^10.43.0",
"aws4fetch": "^1.0.20", "aws4fetch": "^1.0.20",
"dayjs": "^1.11.19", "dayjs": "^1.11.19",
"framer-motion": "^12.34.3", "framer-motion": "^12.35.2",
"react": "^18.3.1", "react": "^18.3.1",
"react-big-calendar": "^1.19.4", "react-big-calendar": "^1.19.4",
"react-dom": "^18.3.1" "react-dom": "^18.3.1"
}, },
"devDependencies": { "devDependencies": {
"@remix-run/dev": "^2.17.4", "@remix-run/dev": "^2.17.4",
"@types/node": "^24.10.13", "@types/node": "^24.12.0",
"@types/react": "^18.3.28", "@types/react": "^18.3.28",
"@types/react-big-calendar": "^1.16.3", "@types/react-big-calendar": "^1.16.3",
"@types/react-dom": "^18.3.7", "@types/react-dom": "^18.3.7",
@@ -35,7 +36,7 @@
"typescript": "^5.9.3" "typescript": "^5.9.3"
}, },
"overrides": { "overrides": {
"@cloudflare/workers-types": "^4.20260304.0" "@cloudflare/workers-types": "^4.20260310.1"
}, },
"prettier": { "prettier": {
"endOfLine": "auto" "endOfLine": "auto"