Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: setup sentry #379

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ APP_SESSION_SECRET=d30eed9c045e6f54377860da2a8384341d3125623b3a5fa02c88d8bc3753e
# recaptcha (https://www.google.com/recaptcha/admin)
APP_RECAPTCHA_CLIENT_KEY=xxx
APP_RECAPTCHA_SERVER_KEY=xxx

# sentry
APP_SENTRY_DSN=xxx
2 changes: 2 additions & 0 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";
import { registerServiceWorker } from "./misc/register-service-worker.client";
import { initializeConfigClient } from "./utils/config";
import { initializeSentryBrowser } from "./utils/sentry-utils.client";

function main() {
registerServiceWorker();
initializeConfigClient();
initializeSentryBrowser();
hydrateRoot(window.document, <RemixBrowser />);
}

Expand Down
2 changes: 2 additions & 0 deletions app/misc/initialize-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import {
initializeDrizzleClient,
} from "../db/drizzle-client.server";
import { initializeConfigServer } from "../utils/config";
import { initializeSentryServer } from "../utils/sentry-utils.server";
import { initializeSessionStore } from "../utils/session.server";

export const initializeServer = once(async () => {
installGlobals();
initializeConfigServer();
initializeSentryServer();
initializeSessionStore();
await initializeDrizzleClient();
});
Expand Down
31 changes: 13 additions & 18 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ import type { UserTable } from "./db/models";
import { $R, R } from "./misc/routes";
import { HideRecaptchaBadge } from "./routes/users/register";
import { trpc } from "./trpc/client";
import { publicConfig } from "./utils/config";
import { ConfigPlaceholder } from "./utils/config-placeholder";
import { CONFIG_SCRIPT_PLACEHOLDER, publicConfig } from "./utils/config";
import { useFlashMessages } from "./utils/flash-message-hook";
import { RootLoaderData, useRootLoaderData } from "./utils/loader-utils";
import { makeLoader } from "./utils/loader-utils.server";
Expand Down Expand Up @@ -73,10 +72,19 @@ export default function DefaultComponent() {
</title>
<Meta />
<Links />
<ConfigPlaceholder />
<ThemeScript />
<HideRecaptchaBadge />
<script dangerouslySetInnerHTML={{ __html: `` }} />
<script
suppressHydrationWarning
dangerouslySetInnerHTML={{ __html: CONFIG_SCRIPT_PLACEHOLDER }}
/>
<script
dangerouslySetInnerHTML={{
__html: `\
globalThis.__themeStorageKey = "ytsub:theme";
${require("@hiogawa/utils-experimental/dist/theme-script.global.js?loader=text")}
`,
}}
/>
</head>
<body className="h-full">
{/* TODO: default position="top" is fine? */}
Expand All @@ -99,19 +107,6 @@ export default function DefaultComponent() {
);
}

function ThemeScript() {
return (
<script
dangerouslySetInnerHTML={{
__html: `\
globalThis.__themeStorageKey = "ytsub:theme";
${require("@hiogawa/utils-experimental/dist/theme-script.global.js?loader=text")}
`,
}}
/>
);
}

function Root() {
const data = useRootLoaderData();
useFlashMessages(data.flashMessages);
Expand Down
16 changes: 0 additions & 16 deletions app/utils/config-placeholder.tsx

This file was deleted.

35 changes: 27 additions & 8 deletions app/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as process from "process";
import { once, tinyassert } from "@hiogawa/utils";
import process from "process";
import { once } from "@hiogawa/utils";
import { z } from "zod";
import { uninitialized } from "./misc";

Expand All @@ -25,16 +25,23 @@ const Z_SERVER_CONFIG = z.object({
const Z_PUBLIC_CONFIG = z.object({
APP_RECAPTCHA_CLIENT_KEY: z.string().default("6Lc79AcgAAAAAOdPnmAZfQqhVwL7mJngRndTyG19"),
APP_RECAPTCHA_DISABLED: z.coerce.boolean(),
APP_SENTRY_DSN: z.string().optional(),
VERCEL_ENV: z.string().optional(),
});

// prettier-ignore
const Z_BUILD_CONFIG = z.object({
GIT_COMMIT_REF: z.string().optional(),
});

export let serverConfig = uninitialized as z.infer<typeof Z_SERVER_CONFIG>;

export let publicConfig = uninitialized as z.infer<typeof Z_PUBLIC_CONFIG>;

export const CONFIG_SCRIPT_ID = "__configScript";
export let buildConfig = uninitialized as z.infer<typeof Z_BUILD_CONFIG>;

export const CONFIG_SCRIPT_PLACEHOLDER = "@@__configScriptPlaceholder@@";
// esbuild injects BUILD_CONFIG_DEFINE on server release build
declare let BUILD_CONFIG_DEFINE: unknown;

//
// server
Expand All @@ -43,12 +50,25 @@ export const CONFIG_SCRIPT_PLACEHOLDER = "@@__configScriptPlaceholder@@";
export const initializeConfigServer = once(() => {
serverConfig = Z_SERVER_CONFIG.parse(process.env);
publicConfig = Z_PUBLIC_CONFIG.parse(process.env);
buildConfig = Z_BUILD_CONFIG.parse(
typeof BUILD_CONFIG_DEFINE !== "undefined" ? BUILD_CONFIG_DEFINE : {}
);
});

// pass data to client via global script
declare let __publicConfig: any;
declare let __buildConfig: any;

export const CONFIG_SCRIPT_PLACEHOLDER = "/*@@INJECT_CONFIG_SCRIPT@@*/";

export function injectConfigScript(markup: string): string {
// TODO: should escape?
return markup.replace(
CONFIG_SCRIPT_PLACEHOLDER,
JSON.stringify(publicConfig)
`
globalThis.__publicConfig = ${JSON.stringify(publicConfig)};
globalThis.__buildConfig = ${JSON.stringify(buildConfig)};
`
);
}

Expand All @@ -57,7 +77,6 @@ export function injectConfigScript(markup: string): string {
//

export const initializeConfigClient = once(() => {
const el = document.querySelector("#" + CONFIG_SCRIPT_ID);
tinyassert(el);
publicConfig = JSON.parse(el.innerHTML);
publicConfig = __publicConfig;
buildConfig = __buildConfig;
});
13 changes: 13 additions & 0 deletions app/utils/sentry-utils.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { init } from "@sentry/browser";
import { buildConfig, publicConfig } from "./config";

// cf. default integrations
// https://github.com/getsentry/sentry-javascript/blob/b624bff35854ea0497f0ea07425719723a73a79b/packages/node/src/sdk.ts#L38-L57

export function initializeSentryBrowser() {
init({
dsn: publicConfig.APP_SENTRY_DSN,
environment: `${publicConfig.VERCEL_ENV ?? "local"}-client`,
release: buildConfig.GIT_COMMIT_REF ?? "local",
});
}
18 changes: 18 additions & 0 deletions app/utils/sentry-utils.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { CaptureConsole } from "@sentry/integrations";
import { init } from "@sentry/node";
import { buildConfig, publicConfig } from "./config";

// cf. default integration
// https://github.com/getsentry/sentry-javascript/blob/b624bff35854ea0497f0ea07425719723a73a79b/packages/browser/src/sdk.ts#L26-L35

export function initializeSentryServer() {
init({
dsn: publicConfig.APP_SENTRY_DSN,
environment: `${publicConfig.VERCEL_ENV ?? "local"}-server`,
release: buildConfig.GIT_COMMIT_REF ?? "local",
// auto report console.error e.g.
// - trpc error in app/routes/trpc/$trpc.tsx
// - remix loader/ssr error https://github.com/remix-run/remix/blob/410e9d8aac044b3453c1dddbeb0bcc1d53cdec68/packages/remix-server-runtime/server.ts#L169
integrations: [new CaptureConsole()],
});
}
13 changes: 13 additions & 0 deletions misc/build/bundle-vercel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { execSync } from "child_process";
import fs from "node:fs";
import esbuild from "esbuild";
import type { buildConfig } from "../../app/utils/config";

// used by scripts/vercel.sh to
// - bundle server app for simpler vercel deployment
Expand All @@ -9,6 +11,14 @@ import esbuild from "esbuild";
// - https://esbuild.github.io/plugins/
// - https://github.com/evanw/esbuild/issues/1685#issuecomment-944916409

const GIT_COMMIT_REF = execSync("git rev-parse HEAD", {
encoding: "utf8",
}).trim();

const BUILD_CONFIG_DEFINE: typeof buildConfig = {
GIT_COMMIT_REF,
};

esbuild.build({
logLevel: "info",
entryPoints: ["./build/remix/production/server/index.js"],
Expand All @@ -27,6 +37,9 @@ esbuild.build({
"pg-query-stream",
],
plugins: [noSourceMapNodeModulesPlugin()],
define: {
BUILD_CONFIG_DEFINE: JSON.stringify(BUILD_CONFIG_DEFINE),
},
});

// https://github.com/evanw/esbuild/issues/1685#issuecomment-944916409
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
"@remix-run/server-runtime": "1.15.0",
"@remix-run/v1-route-convention": "^0.1.1",
"@remix-run/vercel": "1.15.0",
"@sentry/browser": "^7.51.1",
"@sentry/integrations": "^7.51.2",
"@sentry/node": "^7.51.1",
"@tanstack/react-query": "^4.28.0",
"@tanstack/react-query-devtools": "^4.28.0",
"@tanstack/react-virtual": "3.0.0-beta.54",
Expand Down
Loading