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

Remix SDK not reporting server errors to Sentry #6951

Closed
3 tasks done
oliversong opened this issue Jan 26, 2023 · 20 comments
Closed
3 tasks done

Remix SDK not reporting server errors to Sentry #6951

oliversong opened this issue Jan 26, 2023 · 20 comments

Comments

@oliversong
Copy link

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which package are you using?

@sentry/remix

SDK Version

7.33.0

Framework Version

1.8.2

Link to Sentry event

No response

SDK Setup

AFAICT, I've set up our code exactly as in the documentation and example vanguard app.

entry.client.tsx

Sentry.init({
  dsn: (window as any).ENV.SENTRY_DSN,
  environment: (window as any).ENV.NODE_ENV,
  tracesSampleRate: 1,
  integrations: [
    new Sentry.BrowserTracing({
      routingInstrumentation: Sentry.remixRouterInstrumentation(
        useEffect,
        useLocation,
        useMatches
      ),
    }),
  ],
});
entry.server.tsx

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV,
  tracesSampleRate: 1,
  integrations: [new Sentry.Integrations.Prisma({ client: prisma })],
});
root.tsx

export default withSentry(App);

I've double checked that the environment variables are being passed correctly on both the client and the server init calls.

Steps to Reproduce

  1. Load the app
  2. Purposely cause a client side error as suggested by the documentation:
<button
  type="button"
  onClick={() => {
    throw new Error("Sentry Frontend Error");
  }}
>
  Throw error
</button>
  1. Purposely cause a server side error as suggested by the documentation
export const action: ActionFunction = async ({ request }) => {
  throw new Error("Sentry Error");
};

Expected Result

Errors should show up in Sentry for both of these.

Actual Result

Error only appears for the client side error. The server side error never appears.

If I set an explicit captureException call in the error boundary in root.tsx, then that will be reported and show in Sentry.

export function ErrorBoundary({ error }: { error: any }) {
  Sentry.captureException(error);
  return (
    <html>
      <head>
        <title>Oh no!</title>
        <Meta />
        <Links />
      </head>
      <body>
        <Layout style={{ height: "100%" }}>
          <Header />
          <Layout className="ContentContainer">
            <Card>
              <h1>
                <WarningOutlined /> An error occurred - please try again.
              </h1>
            </Card>
          </Layout>
          <Footer />
        </Layout>
        <Scripts />
      </body>
    </html>
  );
}

I've also tried removing the error boundary in root.tsx entirely (thinking it may be conflicting), to no avail.
For whatever reason, I just cannot get sentry's default instrumentation on the server side to function at all.

@oliversong oliversong changed the title Remix SDK not Remix SDK not reporting server errors to Sentry Jan 26, 2023
@lforst
Copy link
Member

lforst commented Jan 27, 2023

Hi, if you add debug: true to the entry.server.tsx init call, do you see any suspicious output?

@timzchang
Copy link

Hello! I have virtually the same set up to @oliversong and I'm running into the same issue. Some additional details:

Which package are you using?

@sentry/remix

SDK Version

7.33.0

Framework Version

remix-run@1.11.0

Link to Sentry event

No response

SDK Setup

In an example app generated with this template, I followed the setup documentation like OP did. The only difference is this app uses a custom express server, so I wrapped createRequestHandler according to the docs.

const createSentryRequestHandler = wrapExpressCreateRequestHandler(createRequestHandler);

app.all('*', createSentryRequestHandler({build: require(BUILD_DIR)}));

Steps to Reproduce

Same as OP, I raise an error on the client and server side suggested by documentation

Expected Result

Errors should show up in Sentry for both of these.

Actual Result

Error only appears for the client side error. The server side error never appears.

In addition, setting captureException in the action similarly doesn't send any error to sentry.

export const action: ActionFunction = async ({ request }) => {
  try {
    throw new Error("Sentry Error");
  } catch (err) {
    Sentry.captureException(err);
  }
};

Notes

  • Adding the debug: true flag in the server init doesn't output anything.
  • I notice in the network tab that a network request to sentry for type event happens immediately upon an error on the client, but no network request happens for a server error.

@oliversong
Copy link
Author

I also tried debug: true in the server init and got no output whatsoever.

@uncle-samm
Copy link

uncle-samm commented Feb 16, 2023

I'm having the same issue, however I feel it has to do with lack of documentation personally, It seems like something is missing. I don't see how initing the sentry class is enough for it to work, but perhaps I got it wrong.

I'm using remix 1.12 and cloudflare pages

@github-actions
Copy link
Contributor

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@timzchang
Copy link

Bump: wondering if folks have had a chance to look at this issue?

@uncle-samm
Copy link

uncle-samm commented Mar 16, 2023

I've given up on the issue and implemented using the ErrorBoundary to report errors to me,

There were too many issues using cloudflare pages and sentry as is, so I've done all workarounds as I can.

  • It doesn't automatically log any error, I don't know why, it just doesn't.
  • Cloudflare pages (even without minifying js) does not seem to map with remix --source-maps so the stack is still unreadable. I'm sure there are solutions but as of now the documentation is just not there yet. As I couldn't find a good alternative for logging as we speak, I've just done it very hacky.

I work in a startup where speed of development is key, so I have no time to help out and debug the issue. I could get debug logs but they gave nothing that was unusual.

I hope a solution will be found and posted here. Or developer will extensively test this on cloudflare pages as it's one of remix' main partners.

Actually I'm lyiing, I did get this debug log:
"Remix SDK was unable to wrap your root because of one or more missing parameters."

here is my basic implementation:
entry.client.tsx

import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";
import * as Sentry from "@sentry/remix";
import { useLocation, useMatches } from "@remix-run/react";
import { useEffect } from "react";
import { env } from "./utils/env.client";



Sentry.init({
  dsn: env.SENTRY_DSN,
  tracesSampleRate: 1,
  integrations: [
    new Sentry.BrowserTracing({
      routingInstrumentation: Sentry.remixRouterInstrumentation(
        useEffect,
        useLocation,
        useMatches,
      ),
    }),
  ],
  debug: env.GIVEN_BUILD === "preview",
  release: env.CF_PAGES_COMMIT_SHA,
  environment: env.GIVEN_BUILD
});

hydrateRoot(document, <RemixBrowser />);

entry.server.tsx

Sentry.init({
  dsn: env.SENTRY_DSN,
  tracesSampleRate: 1,
  debug: env.GIVEN_BUILD === "preview",
  release: env.CF_PAGES_COMMIT_SHA,
  environment: env.GIVEN_BUILD
});

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const markup = renderToString(
    <RemixServer context={remixContext} url={request.url} />
  );

  responseHeaders.set("Content-Type", "text/html");

  return new Response("<!DOCTYPE html>" + markup, {
    status: responseStatusCode,
    headers: responseHeaders,
  });
}

root.tsx

... code above
export default withSentry(App)
... code below

It's also good to mention that cloudflare pages environment variables aren't readable without context (which you only get through loader or action function), would be nice if you found a solution for that.

For now during the build it'll create an environment variable it can read.

@cole-sanderson
Copy link

Bump, any update? I am also dealing with this issue.

@nmackey
Copy link

nmackey commented Apr 10, 2023

Bump, also running into this issue.

@AbhiPrasad
Copy link
Member

Hey folks - thanks for reaching out. We've escalated this so we can investigate further!

@AbhiPrasad
Copy link
Member

AbhiPrasad commented Apr 11, 2023

I attempted to reproduce this - but was unable to: https://github.com/AbhiPrasad/GH-6951-sentry-remix-express. Could anyone provide a reproduction that shows this not working?

Here's a super barebones example app I used. It uses an express server request handler like the OP posted.

With the example I could throw errors in actions, and in loaders and get resulting errors in Sentry. Important to note - we only support the remix server and express server adapters - everything else needs to be manually instrumented by you.

With that in mind Remix v2 is coming out though - and I think it makes sense for us to re-evaluate instrumenting remix from first principles. We've learned a lot from revamping our Next.js SDK and creating the SvelteKit SDK that we can bring back to the Remix SDK.

v2 support - #7810

@AbhiPrasad AbhiPrasad removed their assignment Apr 17, 2023
@KrisBraun
Copy link

I believe this is an issue with Sentry supporting Cloudflare Pages, as I'm having the same issue. It happens consistently both with miniflare locally and on deployment.

@AbhiPrasad
Copy link
Member

See #5610 on Cloudflare Workers support @KrisBraun

@AbhiPrasad
Copy link
Member

I'm going to close this because we haven't got a reproduction, and I can't see to understand how this is not working when you are using the remix server or express server adapters.

Please re-open or create a new issue if you can get a reproduction, thanks!

@jaankoppe
Copy link

@AbhiPrasad Your working demo got a lot more @sentry dependencies, than a regular setup + there are no versions but somekind of file:.yalc/ thing there:

"@sentry/core": "file:.yalc/@sentry/core",
"@sentry/node": "file:.yalc/@sentry/node",
"@sentry/react": "file:.yalc/@sentry/react",
"@sentry/remix": "file:.yalc/@sentry/remix",
"@sentry/types": "file:.yalc/@sentry/types",
"@sentry/utils": "file:.yalc/@sentry/utils",

But the default when installing sentry is only:

"@sentry/remix": "^7.52.1",

Using Remix Server and in the entry.server.jsx file having these lines related to Sentry:

import * as Sentry from "@sentry/remix";

Sentry.init({
  dsn: "_DSN_",
  debug: true,
  tracesSampleRate: 1.0,
});

In root.jsx:

export default withSentry(App, {
  errorBoundaryOptions: {
    fallback: <div>Something went wrong</div>,
  },
});

Client side works correctly, so not going to paste the client code here, but yes like lots of folks discussing here, that the server implementation is not working with Remix Server when trying to implement as described in the docs.

@MoSattler
Copy link

MoSattler commented May 25, 2023

Same here - client side working, server side is not reporting anything whatsoever.

@AbhiPrasad you repro only works cause you are explicitly catching errors. But unhandled errors are not getting reported to sentry.

If you remove the catch block (like in the official sentry example), you will be able to reproduce the issue.

@MoSattler
Copy link

I opened a new issue here: #6951

@richardhunghhw
Copy link

richardhunghhw commented Jun 14, 2023

I opened a new issue here: #6951

I think you meant to link this issue #8216 instead

@delivey
Copy link

delivey commented Jul 24, 2023

Adding this to entry.server.tsx solved it for me, but I presume this only fixes it if you're using v2.

export function handleError(
    error: unknown,
    { request }: DataFunctionArgs
): void {
    if (error instanceof Error) {
        Sentry.captureRemixServerException(error, "remix.server", request);
    } else {
        // Optionally capture non-Error objects
        Sentry.captureException(error);
    }
}

@AbhiPrasad
Copy link
Member

AbhiPrasad commented Jul 24, 2023

Yeah I think we should recommend using v2 error handling since they fixed a lot of things we no longer have to deal with, otherwise it's tricky getting the correct client/server separation.

docs: https://docs.sentry.io/platforms/javascript/guides/remix/#remix-v2-features

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests