More sentry monitoring
This commit is contained in:
@@ -1 +1 @@
|
|||||||
v22.20.0
|
v24.14.0
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
56
app/root.tsx
56
app/root.tsx
@@ -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);
|
||||||
|
|||||||
@@ -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
2990
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user