Replies: 7 comments 13 replies
-
Aside, I didn't even get to the point of discovery on webpack or versioning. I imagine it'll end up looking similar to Next.js in that regard. |
Beta Was this translation helpful? Give feedback.
-
Lastly, relevant GH issue is here for SDK support: #4894 |
Beta Was this translation helpful? Give feedback.
-
Hi @dcramer, thanks for taking a look at Remix. I'll do my best to help answer some of your questions here. I'll use the blues stack as a reference, though I'll also note that the purpose of the stacks is to show people one particular setup of Remix (running Express/node, hosted on fly.io, using Postgres as a db, etc.). There are actually many ways to use Remix with your fav host/framework/db/etc, but I'll leave that for another day. For now let's just get Sentry running in the blues stack. Instrumenting the serverLet's start with the server. You can think of Remix like most typical React server-side rendering (SSR) setups. The server side goes like this:
Remix gives you direct access to both your server entry point and your React entry point for doing SSR. For purposes of instrumentation, you want the server entry point since this is the first code that runs when the server boots. From your guides on using Sentry with Node.js and with Express, just add the Since you're running on node, you have full access to import * as Sentry from "@sentry/node";
import "@sentry/tracing";
Sentry.init({
dsn: process.env.SENTRY_DSN
// ...
});
const app = express();
app.use(Sentry.Handlers.requestHandler()); Data loaders and actionsYour data loaders and actions also run server side in node, so capturing errors from them is the same as manually instrumenting any other node app. // In one of your route modules...
export async function loader() {
try {
// talk to your db...
} catch (error) {
Sentry.captureException(error);
}
} Instrumenting the browserThe flow in the browser is a React hydrate workflow, which is standard when doing SSR in React. It goes like this:
As you noted above, there is a bit of extra work required to expose server environment variables to the client. Remix is unapologetically explicit here, not because we believe that "secrets are dangerous" but because we believe it's better to be explicit about exposing environment variables to front end code than to abstract it away in a config somewhere. In other words, we could create Once you've done that (be sure to put your import { hydrate } from "react-dom";
import * as Sentry from "@sentry/react";
import { BrowserTracing } from "@sentry/tracing";
import { RemixBrowser } from "@remix-run/react";
Sentry.init({
dsn: window.ENV.SENTRY_DSN,
integrations: [new BrowserTracing()],
tracesSampleRate: 1.0,
});
hydrate(<RemixBrowser />, document); The Sentry docs use Re:
That is not correct. The code in And with that, you should be done! Again, this is all pretty typical for a React SSR setup, so I'm hopeful you can help me understand where our docs are unclear on this so we can try to avoid confusion in the future. |
Beta Was this translation helpful? Give feedback.
-
Quick update: I missed |
Beta Was this translation helpful? Give feedback.
-
We wanted to give you a little help getting this integration going. One of our engineers got started on a Remix + Sentry integration that supports good server stack traces, transactions, and individual loaders and actions. He setup a sample account to test things out. You can fork the repo here: https://github.com/jacob-ebey/remix-sentry Server stack traces: Transactions: Individual loader/action duration: Web vitals: The approach here is to take the compiled output of our server build and wrap things as needed. So e.g. the loaders and actions for an individual route can be wrapped so you can see how long they take and automatically capture errors. This is just the beginning of a Remix + Sentry integration, and we don't plan on working much more on this code. So I'd suggest you fork it or just learn from it and take what you learn to build your own integration. Hopefully this should get you moving in the right direction! |
Beta Was this translation helpful? Give feedback.
-
One last note, Remix is using
|
Beta Was this translation helpful? Give feedback.
-
We have made some progress on Sentry Remix SDK. And want to give an overview: Client-side Instrumentation [Implemented]: #5264
Server-side Instrumentation [Implemented]: #5269
Sourcemap Uploads [In Progress] We can't implement automated sourcemap uploads, like we do with Next.JS SDK, as we could not find anything to hook our release/upload process. Mainly because the inner But the default So we're planning to ship a mini CLI tool with Remix SDK, which uses Can look something like: $ sentry-upload-sourcemaps <release> options[--urlPrefix, --buildPath] That script will have defaults for Any input would be greatly appreciated! |
Beta Was this translation helpful? Give feedback.
-
I've been working on a small app in Remix, and as part of that I wanted to take the opportunity to explore what it'd take for Sentry to support Remix.
Remix is intended to be more of a blend vs a full on "do it exactly this way" framework. What that means is we may have a more difficult time supporting it in our typical low friction methods. There currently are not straight forward injection points for a variety of things we'd typically look for. I'll try to break down my findings and update this as needed.
First, the frontend feels somewhat doable, but the backend feels like it's going to be a lot more effort for end-users. Below I'm articulating some concerns I've found with approaching our normal routes to injecting an SDK.
We're required to inject
SENTRY_DSN
ourselves somehowThat comes from the fact that we cannot access
process.env
in the frontend build by default. I've talked w/ the Remix team and nudged them towards the needs here. AFAICT they took an approach that "secrets are dangerous", and so their first pass approach was to require use of them via server-side hydration only.The simplest approach to this today involves the user augmenting their
root.tsx
:A standard entrypoint happens after application logic could have defects
What this is doing is simply re-binding SENTRY_DSN as a global available via window. I then took this and initialized the SDK in
entry.client.tsx
. There are some issues with this approach as its already after application logic has begun to run, meaning we may not be able to capture all errors (which is not up to our standards):Server entry points sound like they need to be adapter specific
I'm still working through how we can implement server-side support, but it appears in the example app (the "Blues" stack) it is not reasonably doable. It's been suggested to me by the Remix team that people will generally stop using the built-in express server, and instead create their own, in which case we could register a Sentry middleware. I dont love this as it violates our low friction policy in Sentry. It's less of a problem if this was the only instrumentation they had to register, but when you combine it with the rest it starts to add up to a lot. I'm pushing for ways for us to avoid something similar to Next.js here which is very atypical for us given the amount of config we have to generate for the user.
What I have tried here, and has not achieved what was expected, was injecting into
entry.server.tsx
. As best I can tell this this is similar toentry.client.tsx
, but actually runs earlier in the lifecycle (more ideal). Specifically my understanding is this runs when React needs to hydrate the initial document. That's potentially great for letting us capture hydration errors, but it falls short of achieving full server-side instrumentation.Unclear solution to instrument loaders and actions
One big concern right now - and one I haven't yet been able to explore - is how we'd approach instrumenting the loaders (basically "fetch data" operations) and actions (basically "save data" operations). These are critical to Remix application development, and while our Error hooks likely would cover these (assuming we inject them early enough), I've yet to find a clean way to wrap these calls without hijacking Remix internals. Without this we will be unable to develop any kind of reasonable performance instrumentation.
Transaction names within react-router
On the client-side I was able to add a hook which - when referenced within
root.tsx
- allows a reliable transaction name for the current route to be assigned. This isn't working in all cases, and specifically I believe it is not currently working at all on the server-side. I need to do more work here yet.Unclear solution to client-side transactions
It's likely we will need to fully rely on whatever can be achieved within react-router's event system (this may be a blocker right now?) to obtain client-side transactions.
I will update this as I continue to poke around at this, but otherwise this will hopefully be helpful information to continue discussions within the community.
Beta Was this translation helpful? Give feedback.
All reactions