-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
-
Hi there,
I'm trying to set up Sentry on my Next v14/App router. I've got it correctly logging errors to my Sentry installation, but I'm trying to add some user identifiers to the errors, so I can reference them to users in my DB.
I have used this successfully in the past on my _app.tsx file:
Sentry.setUser({
id: currentUser.id.toString() ?? undefined,
});
This worked on the Pages router, but it seems in App router (with RSC and all that) it doesn't work, and add the user to the error?
I have done a request to get the userId in my Layout RSC, and trying to attach it to the RootLayout at /app/layout.tsx as follows:
export default async function RootLayout({ children }: { children: React.ReactNode }) {
const currentUser = await fetchUserData();
if (currentUser) {
Sentry.setUser({
id: currentUser.id,
});
}
...
But it doesn't seem to carry through this id to the error that's logged within Sentry.
Is it because of server components somehow, and how they are now different to client components? Just trying to get my head around this, and how to keep the code clean - and how best to tackle this for errors within both server and client components!
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions
To add to my comment here: #10019 (reply in thread)
Server and client components are also separated logically. Meaning that when you call setUser() on the server, it is not propagated to the client. On the client you would also have to call the method.
Replies: 4 comments 5 replies
-
im also struggling with this:
image
flows is a client component, so it have the user context.
Beta Was this translation helpful? Give feedback.
All reactions
-
As of now, you would have to call Sentry.setUser() in each server component individually. That is because server components are separated logically.
Beta Was this translation helpful? Give feedback.
All reactions
-
😕 9
-
To add to my comment here: #10019 (reply in thread)
Server and client components are also separated logically. Meaning that when you call setUser() on the server, it is not propagated to the client. On the client you would also have to call the method.
Beta Was this translation helpful? Give feedback.
All reactions
-
❤️ 5
-
- Understood that setUser should be on every server component.
- For setUser on client components, is it:
- Set it one time somewhere (where?) and let it propagate?
- We must use useEffect() ?
Thanks
Beta Was this translation helpful? Give feedback.
All reactions
-
For the client you generally only have to set it once per pageload, so you can set it somewhere pretty high in a layout or something. And yes I would use useEffect for it. I do it like this in my side-project so that the user value gets updated when let's say somebody switches accounts:
useEffect(() => {
Sentry.setUser({ id: userId })
}, [userId])
Beta Was this translation helpful? Give feedback.
All reactions
-
🎉 4
-
Thank you!
Beta Was this translation helpful? Give feedback.
All reactions
-
❤️ 1
-
We are using this approach on the server but we have observed incorrect attribution occasionally. Sentry.setUser() sets a global state, is that correct? so using this in an async server-side scenario can lead to collisions:
- request 1 comes in,
Sentry.setUser()is called for user 1 - request 1 awaits some data request
- request 2 comes in,
Sentry.setUser()is called for user 2 - request 2 awaits some data request
- request 1 continues and hits an error, which gets attributed incorrectly to user 2
Am I correct that this can happen? Is there some way to prevent this?
Beta Was this translation helpful? Give feedback.
All reactions
-
setUser sets the user on the current isolation scope. where this applies depends on where you call it - but in most cases in Next.js this should be on a per-route basis and not leak to other routes. Could you share a code snippet (with file path) of where/how you are using setUser in a place where it leaks for you?
Beta Was this translation helpful? Give feedback.
All reactions
-
At the beginning of any given page/route handler/server action, we do:
- make async call to determine the user
- call
Sentry.setUser()
After that we execute the business logic, which involves multiple async calls typically. In general this works, but I have observed cases where a given Sentry issue has the wrong user set.
There's nothing particularly exotic about how we are calling it. A typical example would look like:
"use server";
export async function fooAction(...) {
const session = await getSession();
Sentry.setUser(session.user);
const data = await getData(...);
// some code which throws and triggers a sentry issue
}
Beta Was this translation helpful? Give feedback.