-
Notifications
You must be signed in to change notification settings - Fork 27.1k
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
Improve with-sentry example #5727
Conversation
I think I'll replace session cookie with ip address so there are less packages in example |
or never mind, I'll still need to persist ip_address in cookies to client so errors are properly reported if next is failing to load somehow, so the complexity will be the same |
Sentry working properly is a critical requirement before going to production with Next.js. I can't thank you enough for the time you put into this for the community. |
It took a week or two but I'm pretty happy with error reporting now :) For sure there are some things to improve:
I also recommend my targets-webpack-plugin so next.js websites are properly rendered by google bot (chrome 41) and legacy browsers (mobile browsers and internet explorer). |
❤️ Excited to try this! |
Thanks a ton, for the time you put into this. Super excited to try this, this has stumped me for quite some time |
@sheerun are errors happening in getInitialProps on the server reported correctly for you? With this code for me they are still only reported the first time they are happening. subsequent errors of the same type get lost until i restart the server. Everything works perfectly with this setup |
Is anyone else experiencing huge memory leaks on the node server (v: 10.13.0) with this example as long as it uses the sentry request and error handlers? Not sure if this is sentry related or because of interaction between sentry and next. I observed this using memwatch
|
Maybe they are not reported because sentry ignores duplicated errors? |
@sheerun can you elaborate on the need for targets-webpack-plugin? If nextjs isn't properly rendering for googlebot that seems like a serious problem. I am curious if there are already nextjs issues open about that so we can work towards making nextjs work perfectly out of the box? |
I don't know. By default it works with google bot but when you install practically any modern package it stops. The solution is to transcompile final bundles instead of each file individually. |
I just double checked, it should not be because of duplicate errors. But client side error catching works perfectly now for us. I had to remove the sentry-handlers as they cause huge memory-leaks for us |
For next week I won't have time to improve this PR to fix this so maybe someone else wants to |
|
||
server.use(cookieParser()) | ||
|
||
server.use((req, res, next) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this part is needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? it's needed for tracking users for errors in sentry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very least I don't think it should use an express middleware but use getInitialProps instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it won't work if next.js crashes before of while excuting getIntialProps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I can't use getInitialProps because session id for user won't be preserved at all cases (e.g. when someone does full refresh of webpage). It would require reimplementing cookies in local storage.
// This attaches request information to sentry errors | ||
server.use(Sentry.Handlers.requestHandler()) | ||
|
||
server.use(cookieParser()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's needed for tracking users so we get same user id on client and on server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also to preserve the same session id for different requests so users count for given error is not artificially high
|
||
server.get('*', (req, res) => handle(req, res)) | ||
|
||
// This handles errors if they are thrown before raching the app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// This handles errors if they are thrown before raching the app | |
// This handles errors if they are thrown before reaching the app |
pageProps = await Component.getInitialProps(ctx) | ||
} | ||
} catch (e) { | ||
captureException(e, ctx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to _error.js instead, we use something like this for zeit.co:
static getInitialProps({ res, err }) {
console.log({err})
const statusCode = res ? res.statusCode : err ? err.statusCode : null
Sentry.captureException(err)
return { statusCode }
}
Also passing ctx
is dangerous when server errors happen, as it holds req
and res
, which can hold auth token cookies etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really work and results in Synthetic errors. ctx is passed to 1st party captureException from which relevant data is extracted. I don't see how it's security issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried lots of different ways to integrate sentry in the _error.js but all of them resulted in Synthetic errors
when i did the same steps i get
|
I tried this out and it seems to work great. No synthetic errors! I did also comment out the server.js sentry-handlers out of fear of the memory leak and everything on the test page still seems to work. I guess they are not really needed?
|
@Enalmada Don't say that. server.js role is twofold:
Discovering memory leaks in sentry is saddening (getsentry/sentry-javascript#1762) but it doesn't disqualify this PR as proper solution for error handling. I hope Sentry will resolve these issues soon so we can merge this. As for catching middleware errors this is proper solution for now (after memory leaks are fixed by sentry). If you don't like it you can iterate on it in the future by e.g. having next.js manage custom server code and only allow to inject middleware in next.config.js. This way next.js would be able to catch any errors even if they happened in custom server code. As for tracking users for errors - there's no another way to implement this for now. Only using cookies guarantees that I can see all errors that happened to single user if he/she received errors in more than one page - it's not possible to track state between different requests without cookies. Not to mention even if using getInitialProps for setting sessionId somehow preserved sessionId between requests (as suggested by @timneutkens), it won't always work because of complexity of code that has to execute for this feature to work: successful getInitialProps, serialization, app initialization and then rehydration (and also because errors can happen in custom server code). In contrast setting cookie can happen by just setting header in middleware, and reading it is handled by browser itself - there's practically nothing that can break this process, and browser automatically cares to send session cookie for all future requests. It just makes no sense to reimplement this behavior in next.js using e.g. localStorage |
Ah, thank you for the great explanation about how these two lines (which I prematurely commented out of memory leak fear) actually do more than I realized: @abraxxas issue notes that the memory leak only happens on node 10.x so this issue should still be merged asap, just with a strong README warning to use node 8.x until that sentry issue is resolved. The existing sentry example already has the sentry and request handler so merging this with a note to use node 8 is just one more way this pull request could help everyone. Let's get this merged because it is so much better than current example and then we can continue to work with next to fundamentally improve the situation (middleware support, etc). |
I just implemented this in typescript and according to the types there are a few issues with this PR. React.ErrorInfo only contains one key called componentStack and the request object does not have a params or query key |
@abraxxas Maybe you want to send PR to this PR? |
sure will do that as soon as i have some time today, just wanted to notify
everyone
…----------------------------------------
*Sebastian Dumbs*
Tel: 0699/19012945
Email:[email protected]
Am Do., 6. Dez. 2018 um 11:43 Uhr schrieb Adam Stankiewicz <
[email protected]>:
@abraxxas <https://github.com/abraxxas> Maybe you want to send PR to this
PR?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#5727 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AIbrNhvevDJTJ0pk3MHcsNuJ8uorpcl9ks5u2PTPgaJpZM4Ytx8n>
.
|
remove nonexisting keys from request and update errorInfo handling
I've merged @abraxxas PR to this PR so we should be fine now, thank you! |
I'm going to merge this but I think it would still be beneficial to have a lightweight version of this without a custom server / cookies / etc for if you only want to catch the errors that are rendering in _error.js (all user-side errors in Next.js), for example that's what we do for zeit.co. |
@timneutkens Maybe something like |
Maybe getInitialProps could be made the place but currently it suffers from few problems:
|
Changes from this pr have been lost in merge commit 163830c |
Feel free to resubmit a PR @Yankovsky |
In response to #1852
Is it complicated? Yes. Is it necessary for proper production error handling, also yes.
I propose you merge this and I could extract this into plugins when next.js supports creating plugins for Server and App