Skip to content
This repository was archived by the owner on Dec 19, 2024. It is now read-only.

Sentry: Add resolved url tag #600

Merged
merged 6 commits into from
Aug 11, 2022
Merged

Conversation

masonmcelvain
Copy link
Contributor

Sometimes it's hard to tell which page a user was on when an error occurred, so adding it in a tag will be useful for debugging.

The resolved url is the url that the user requested (like /Parts/iPhone). This is different than context.req.url, which can be a link like /_next/data..., which is not the helpful for debugging.

QA

Throw an error on any page while running local dev. It should get reported to react-commerce-dev in sentry, and have a resolved_url tag.

Sometimes it's hard to tell which page a user was on when an error occurred, so adding it in a tag will be useful for debugging.

The resolved url is the url that the user requested (like /Parts/iPhone). This is different than `context.req.url`, which can be a link like /_next/data..., which is not the helpful for debugging.
@vercel
Copy link

vercel bot commented Aug 8, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
react-commerce ✅ Ready (Inspect) Visit Preview Aug 9, 2022 at 7:43PM (UTC)
react-commerce-prod ✅ Ready (Inspect) Visit Preview Aug 9, 2022 at 7:43PM (UTC)

@deltuh-vee
Copy link
Contributor

QA 🎬
Resolved URL tag is now present in Sentry.

@deltuh-vee deltuh-vee removed the QAing Under QA team review label Aug 8, 2022
};

export const setSentryPageContext = ({ url }: PageContextProps) => {
Sentry.setTag('resolved_url', url);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be inconsistent and flaky. We're in the context of a JS server that does a bunch of async work. This JS server has only one global context yet it may be serving several requests in parallel. I think we can kill two birds though. I'm gonna try something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be inconsistent and flaky. We're in the context of a JS server that does a bunch of async work. This JS server has only one global context yet it may be serving several requests in parallel.

I'm not sure I understand. What exactly are you worried about?

Feel free to push to this branch if you come up with something 👍🏻

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wowza I'm seeing a few issues/PR's on sentry-javascript about getting error reporting in getServerSideProps to work.

getsentry/sentry-javascript#5503
getsentry/sentry-javascript#3880

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow... looks like they already auto-inject code to wrap getServerSideProps() (given that pull request). But it seems (based on experimentation) that they don't capture the relevant url? I wonder if there's a mechanism (via config) to augment or add to the code that auto-wraps getServerSideProps().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it seems (based on experimentation) that they don't capture the relevant url?

That's what I had seen, but now that I'm testing this branch, I see the correct url tag.

image

I wonder if there's a mechanism (via config) to augment or add to the code that auto-wraps getServerSideProps().

Maybe via the middleware concept that @jarstelfox was talking about? #600 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great thanks for finding all that! Here's an example of a Sentry event from getServerSideProps that didn't get the url tag. But many other events from the server are. I can't explain what's causing the discrepancy, I agree with you that it seems like it should work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that it's setting the url, but it isn't setting resolvedUrl. Is there something in this code that makes you think we should be seeing resolvedUrl already?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I did some skimming and cross-referenced the example you linked above.

It looks like sentry hooks into the server and wraps a ton of logic. Most notably Next's Request Handler Factory which is what calls down to setting the url.

I still believe it should be working at the time of the error(even though it clearly is not).

Sentry is passing that data down to itself when a request handler is made. i.e. afterRouted

Maybe someone else can spy what's missing, but I think we should provide our own way of getting the data until we can find a reliable way for sentry to hook the url

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make sure we're all on the same page, this should only affect page loads where it uses next-link to load json. In those cases, we've seen url set as /_next/.... resolvedUrl will be the url of the page that we were really trying to link to. In the code I've read, I see sentry adding the url field, but I haven't seen them add the resolvedUrl field, so I wouldn't expect it to just work without some changes like in this pull.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, Sentry JS SDK maintainer here. Just stumbled onto this thread.

We're currently working on wrapping Next.js data fetching methods (including getServerSideProps) to improve instrumentation. Currently, the efforts mainly go into properly setting parameterized transaction names (transactions are part of the Sentry performance monitoring product and parameterization means that transactions won't show up as /user/42/post/1337 but rather as /user/[userId]/post/[postId], which is generally more useful).

We might explore adding the parameterized route + parameters to errors in some way (or at least provide a way for SDK user's to figure out what parameterized route they're in - maybe we can contribute this to the Next.js repo upstream).

We would love for you to try out the changes as soon as they land!

We want to generate a url from the current context in /frontend and in /packages/sentry. This lets us use it in both places.
Accepts the same param that is passed to `getServerSideProps` so that we can easily call it in each file in /frontend/pages.

Clears the Sentry scope before setting the tag, because this is going to be called on a JS server that handles many requests, and we don't want to accidentally include context from another request in a Sentry event.

Bumps @sentry/nextjs to 7.8.1, which is what we use in /frontend.

Uses the react-library tsconfig.json, because TS was complaining that we imported `urlFromContext()` from a .tsx file.
This approach makes us more confident that we won't accidentally include context from the wrong request in a Sentry event sent from the server (because the server can be handling multiple requests at once).
@masonmcelvain masonmcelvain force-pushed the sentry--add-resolved-url-tag branch from 54f373f to 7e1519e Compare August 9, 2022 19:10
@@ -0,0 +1,6 @@
import { GetServerSidePropsContext } from 'next';

export function urlFromContext(context: GetServerSidePropsContext): string {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI I didn't include this in @ifixit/helpers/nextjs because doing so would cause a cyclic dependency between @ifixit/sentry and @ifixit/helpers.

Comment on lines +3 to +6
export function urlFromContext(context: GetServerSidePropsContext): string {
const protocol = context.req.headers.referer?.split('://')[0] || 'https';
return `${protocol}://${context.req.headers.host}${context.resolvedUrl}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use the actual URL object. I know you may toString it later, but the class may be nice down the road

Suggested change
export function urlFromContext(context: GetServerSidePropsContext): string {
const protocol = context.req.headers.referer?.split('://')[0] || 'https';
return `${protocol}://${context.req.headers.host}${context.resolvedUrl}`;
}
export function urlFromContext(context: GetServerSidePropsContext): URL {
const protocol = context.req.headers.referer?.split('://')[0] || 'https';
return new URL(`${protocol}://${context.req.headers.host}${context.resolvedUrl}`);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but we use string urls throughout most of this app unfortunately, so this would be a more siginificant refactor if we were to do it right. I'd rather leave it to another pull.

@masonmcelvain
Copy link
Contributor Author

masonmcelvain commented Aug 9, 2022

Hmm the url is showing up as a sentry tag, but when I add arbitrary tags, they aren't showing up.

Nevermind I'm just blind

We were clearing the scope because we were worried that different requests might pollute each other's scopes on the server.

Howevever, it looks like Sentry handles this for us, so we don't need to risk blowing away valuable debugging info:

getsentry/sentry-javascript#3788
Copy link
Member

@danielbeardsley danielbeardsley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CR 👍

Man, crazy that sentry/next does the auto-wrapping of the getServerSideProps() function. Bummer that it doesn't seem to do the thing all the time.

@deltuh-vee deltuh-vee added the QAing Under QA team review label Aug 11, 2022
@deltuh-vee
Copy link
Contributor

Carry over QA 🎬

@deltuh-vee deltuh-vee removed the QAing Under QA team review label Aug 11, 2022
@danielbeardsley danielbeardsley merged commit c731d99 into main Aug 11, 2022
@danielbeardsley danielbeardsley deleted the sentry--add-resolved-url-tag branch August 11, 2022 22:09
@lobsterkatie
Copy link

Man, crazy that sentry/next does the auto-wrapping of the getServerSideProps() function. Bummer that it doesn't seem to do the thing all the time.

Weighing in as the other half of the team working on this project. So glad y'all are excited for this! It's still very much a WIP, so expect it to get better over the next few weeks.

Also, feel free to follow along on getsentry/sentry-javascript#5505. It's mostly just some notes I wrote up as I was planning the project, but if there are thoughts about it you want to share, that's a great place.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants