Skip to content

Commit 5fe9a97

Browse files
committed
Sentry WIP
1 parent 74808d7 commit 5fe9a97

File tree

14 files changed

+967
-39
lines changed

14 files changed

+967
-39
lines changed

apps/webapp/app/entry.server.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from "./components/primitives/OperatingSystemProvider";
1717
import { singleton } from "./utils/singleton";
1818
import { bootstrap } from "./bootstrap";
19+
import { wrapHandleErrorWithSentry } from "@sentry/remix";
1920

2021
const ABORT_DELAY = 30000;
2122

@@ -170,9 +171,21 @@ function handleBrowserRequest(
170171
});
171172
}
172173

173-
export function handleError(error: unknown, { request, params, context }: DataFunctionArgs) {
174-
logError(error, request);
175-
}
174+
export const handleError = wrapHandleErrorWithSentry((error, { request }) => {
175+
if (request instanceof Request) {
176+
logger.error("Error in handleError", {
177+
error,
178+
request: {
179+
url: request.url,
180+
method: request.method,
181+
},
182+
});
183+
} else {
184+
logger.error("Error in handleError", {
185+
error,
186+
});
187+
}
188+
});
176189

177190
Worker.init().catch((error) => {
178191
logError(error);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { type DataFunctionArgs } from "@remix-run/node";
2+
import { requireUser } from "~/services/session.server";
3+
4+
export async function loader({ request }: DataFunctionArgs) {
5+
const user = await requireUser(request);
6+
7+
if (!user.admin) {
8+
throw new Response("You must be an admin to perform this action", { status: 403 });
9+
}
10+
11+
throw new Error("Test error");
12+
}

apps/webapp/app/services/logger.server.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import { Logger } from "@trigger.dev/core/logger";
33
import { sensitiveDataReplacer } from "./sensitiveDataReplacer";
44
import { AsyncLocalStorage } from "async_hooks";
55
import { getHttpContext } from "./httpAsyncStorage.server";
6+
import { captureMessage } from "@sentry/remix";
67

78
const currentFieldsStore = new AsyncLocalStorage<Record<string, unknown>>();
89

910
export function trace<T>(fields: Record<string, unknown>, fn: () => T): T {
1011
return currentFieldsStore.run(fields, fn);
1112
}
1213

14+
Logger.onError = (message, ...args) => {
15+
captureMessage(message, {
16+
level: "error",
17+
});
18+
};
19+
1320
export const logger = new Logger(
1421
"webapp",
1522
(process.env.APP_LOG_LEVEL ?? "debug") as LogLevel,

apps/webapp/instrument.server.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import * as Sentry from "@sentry/remix";
2+
import { eventLoopBlockIntegration } from "@sentry/node-native";
3+
4+
if (process.env.SENTRY_DSN) {
5+
console.log("🔭 Initializing Sentry");
6+
7+
Sentry.init({
8+
dsn: process.env.SENTRY_DSN,
9+
release: process.env.BUILD_GIT_SHA,
10+
11+
// Adds request headers and IP for users, for more info visit: and captures action formData attributes
12+
// https://docs.sentry.io/platforms/javascript/guides/remix/configuration/options/#sendDefaultPii
13+
sendDefaultPii: false,
14+
15+
skipOpenTelemetrySetup: true,
16+
registerEsmLoaderHooks: false,
17+
disableInstrumentationWarnings: true,
18+
19+
maxBreadcrumbs: 0,
20+
shutdownTimeout: 10,
21+
22+
serverName: process.env.SERVICE_NAME,
23+
environment: process.env.NODE_ENV,
24+
25+
integrations: [eventLoopBlockIntegration({ threshold: 1000 })],
26+
});
27+
}

apps/webapp/package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
"version": "1.0.0",
55
"sideEffects": false,
66
"scripts": {
7-
"build": "run-s build:**",
7+
"build": "run-s build:** && pnpm run upload:sourcemaps",
88
"build:db:seed": "esbuild --platform=node --bundle --minify --format=cjs ./prisma/seed.ts --outdir=prisma",
99
"build:remix": "remix build",
10-
"build:server": "esbuild --platform=node --format=cjs ./server.ts --outdir=build",
10+
"build:server": "esbuild --platform=node --format=cjs ./server.ts --outdir=build --sourcemap",
11+
"build:instrument": "esbuild --platform=node --format=cjs ./instrument.server.ts --outdir=build --sourcemap",
1112
"dev": "cross-env PORT=3030 remix dev -c \"node ./build/server.js\"",
1213
"dev:worker": "cross-env NODE_PATH=../../node_modules/.pnpm/node_modules node ./build/server.js",
1314
"format": "prettier --write .",
@@ -19,10 +20,7 @@
1920
"db:seed:local": "ts-node prisma/seed.ts",
2021
"build:db:populate": "esbuild --platform=node --bundle --minify --format=cjs ./prisma/populate.ts --outdir=prisma",
2122
"db:populate": "node prisma/populate.js --",
22-
"generate:sourcemaps": "remix build --sourcemap",
23-
"clean:sourcemaps": "run-s clean:sourcemaps:*",
24-
"clean:sourcemaps:public": "rimraf ./build/**/*.map",
25-
"clean:sourcemaps:build": "rimraf ./public/build/**/*.map",
23+
"upload:sourcemaps": "bash ./upload-sourcemaps.sh",
2624
"test": "vitest --no-file-parallelism",
2725
"eval:dev": "evalite watch"
2826
},
@@ -103,6 +101,8 @@
103101
"@remix-run/serve": "2.1.0",
104102
"@remix-run/server-runtime": "2.1.0",
105103
"@remix-run/v1-meta": "^0.1.3",
104+
"@sentry/node-native": "^9.40.0",
105+
"@sentry/remix": "^9.40.0",
106106
"@slack/web-api": "7.9.1",
107107
"@socket.io/redis-adapter": "^8.3.0",
108108
"@splinetool/react-spline": "^2.2.6",
@@ -142,7 +142,6 @@
142142
"express": "4.20.0",
143143
"framer-motion": "^10.12.11",
144144
"graphile-worker": "0.16.6",
145-
"highlight.run": "^7.3.4",
146145
"humanize-duration": "^3.27.3",
147146
"input-otp": "^1.4.2",
148147
"intl-parse-accept-language": "^1.0.0",

apps/webapp/server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import "./instrument.server";
2+
13
import { createRequestHandler } from "@remix-run/express";
24
import { broadcastDevReady, logDevReady } from "@remix-run/server-runtime";
35
import compression from "compression";

apps/webapp/upload-sourcemaps.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
if [ -n "$SENTRY_ORG" ] && [ -n "$SENTRY_PROJECT" ] && [ -n "$SENTRY_AUTH_TOKEN" ]; then
3+
sentry-upload-sourcemaps --org $SENTRY_ORG --project $SENTRY_PROJECT --buildPath ./build
4+
else
5+
echo "Skipping sourcemap upload: Missing required environment variables"
6+
echo "Required: SENTRY_ORG, SENTRY_PROJECT, SENTRY_AUTH_TOKEN"
7+
fi

packages/core/src/logger.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export class Logger {
2323
#jsonReplacer?: (key: string, value: unknown) => unknown;
2424
#additionalFields: () => Record<string, unknown>;
2525

26+
// Add a static "onError" method that will be called when an error is logged
27+
static onError: (message: string, ...args: Array<Record<string, unknown> | undefined>) => void;
28+
2629
constructor(
2730
name: string,
2831
level: LogLevel = "info",
@@ -67,6 +70,10 @@ export class Logger {
6770
if (this.#level < 1) return;
6871

6972
this.#structuredLog(console.error, message, "error", ...args);
73+
74+
if (Logger.onError) {
75+
Logger.onError(message, ...args);
76+
}
7077
}
7178

7279
warn(message: string, ...args: Array<Record<string, unknown> | undefined>) {

0 commit comments

Comments
 (0)