How to log the currentUser (from the context) for each graphQL request

Hello everyone.

I have a question about logging.

I added to my graphql handler these options :
image

It works fine and I can see the informations for each request in the logs in AWS CloudWatch.

Now I want to log, for each request, the currentUser.id from the context to know who is the user responsible for the request.

I saw this in the docs but it seems to be used for adding some information to the context in itself to be accessed in the services : GraphQL | RedwoodJS Docs

So I tried to access the context in the logger.ts file by importing it like this :
image

and using a child logger like this :
image

But the context is {}

How can I do this? Is there any way to add informations taken from the context to every request log?
Or is there any other way to know for each request who is the user making the request and logging it to AWS without needing to add logging calls in all services?

It seems like the grapqhQLhandler would be the best place to do it but I can’t find how.

Thank you for your help by advance :slight_smile:

In your createGraphQlHandler, you can set a “extraPlugins” attribute to add a Graphql Yoga plugin (doc). Any plugin in this list will be executed between auth plugin and your logger plugin (cf : related code), so you should be able to get the currentUser from the context and do what ever you want. If you want to extends (or just take a look at) the logger plugin you can find it there.

Thanks a lot for your answer.

It seems it would be quite easy to add in the useRedwoodLogger function what I need to log the currentUserId, but I am not sure how I can extend the function and just add the bit I need?

Should I try to duplicate it, rename it and modify it to only log the currentUser, then use it as an extraPlugin? Or is there any easy way to just add the few lines of code I would need in the current function?

But I am gald to know at least there seems to be a way to do this for each request in one place :slight_smile:

1 Like

I managed to do what I needed by copying the useRedwoodLogger function, modifying it for my use case and adding it in the extraPlugins attribute in my handler.

Thank you so much for your help :slight_smile:

While we are in the graphQL handler, do you know if there is any way to do something if a certain error occurs in any graphql request?

I want to logout the user automatically if the following error occurs in a request :
Error: Exception in getAuthenticationContext: The Authorization header is not valid.

It seems it would be logical to have this functionality in the graphQL handler so the error handling is in one place. Do you know how I could do this?

Or if there is any other way to do it? I found this : [Bug?]: No redirect to login, no token refresh after Azure Auth JWT expires (only status code 500 failure in cell) · Issue #8499 · redwoodjs/redwood · GitHub

I am kind of blocked because if I reduce the expiration time of the session cookie, I cannot handle these errors when the cookie is expired it in the app for now (I get this message in the interface)

image

Thanks again for your help.

in useRedwoodLogger you have access to the context:

You could then:

  • add an option to the logger to includeCurrentUserId
  • get the id but check for the type of the currentUser

  • add to options to log
  • update the packages/api-server/src/logFormatter/index.ts to format about output the currentUser
  • add tests
  • add docs to the docs/docs/logger.md for the new option

Would be a nice PR to be able to include it.

Up for a contriubution?

Thank you for your answer.

Yes I managed to do it by adding an extraPlugin and doing what you wrote in your answer. My question was not correctly written.

It should have been: is there any way to extend the useRedwoodLogger function without the need to modify the redwood package, make a PR, wait for it to be merged and then update redwood in my project?

The problem is mainly that I am on 4.2 and I have no interest to update to a later version… (and by this I mean my employer). I’m sorry I won’t be able to do a PR for the same reason (employer…) but I agree it would be a great contribution if someone needs it :slight_smile: I’m really sorry about this…

That’s why I did it the other way, even if it would be best to update the function direclty as it allows to have one log instead of two…

Do you have any idea about the logout on authentication error?

I see I can check for the error in the registerContextErrorHandler:
image

I guess I could then check in the “if error” if the error message includes :
image

But then I have no idea how to make the user log out automatically from the api side…

Ideally I would do a call to a function like : logoutUser() from this ErrorHandler but I don’t know if it is possible. Or maybe make the page refresh?

Do you know if it is doable?

Thanks for your answer and your time :slight_smile:

: is there any way to extend the useRedwoodLogger function without the need to modify the redwood package, make a PR, wait for it to be merged and then update redwood in my project?

Not really. Maybe patch package patch-package - npm but honestly, I don’t think it’s worth it. In your case, just make a custom plugin. But it would be nice for the logger to handle that currewntUser case.

Could you add a GitHub issue for this feature enhancement? Perhaps we can recruit someone else in the community to contribute. It’s a solid first PR and the Core Team may not get to it soon as busy on v7 roadmap items.

But then I have no idea how to make the user log out automatically from the api side…

There is no concept of being logged in or out on the api side. The auth context is valid and the token/session/ertc can be decoded – or it isn’t and it can’t.

Only the web side has the content of being logged in.

You might be able to check in a query or for an error and the error code in the graphql result extensions and logout with the useAuth hook. Just an idea, not 100% sure as not tried.

Or maybe in registerContextErrorHandler you create a custom Redwood GraphQL error with a code and a friendlier message and handle that on the web side.

See https://github.com/redwoodjs/redwood/blob/49d41f6f7c31cd76502efbe3b4778436de0f6d7c/packages/graphql-server/src/errors.ts#L24 for some examples of other errors you might be able to pattern from.

1 Like

Yeah I will just use the custom plugin as it is already done and it works. I will try to make an issue on github for an enhancement with the problem and solution (I guess I will copy your post as it is already the steps that needs to be followed).

It seems I can check in the Failure case of the cell if the error contains the authentication failure message, but the problem is I need to do it in every cell, and I also have some hooks that use directly the apollo useQuery without going through a cell… I was hoping to have this check somewhere unique for all requests.

Oh I guess it could work. It seems to be the best way to check in a unique place, and because the error is already handled (as seen in the image above, I just need a different message).
If I can throw something like an SessionExpiredError with a message like “You session is expired. Please log out and log in again.” it should be enough for my use case (I don’t care if they are logged out automatically, I just want them to know their session is expired).

Thank you for your suggestions, I will try to do it this way and report back :slight_smile:

It was quick and it seems to work :slight_smile:

I created a new error (I had already made a custom ProfileError so it was quick) :
image

And added in the handler:
image

I will just need to add a check on the error message before throwing the SessionExpiredError.

And now I have in the interface when the session is expired :

So I guess it is enough for my use case. I will just need to see how I can handle this in my useQuery calls in some hooks but it is already enough (because my hooks call are used to populate some data in the pages, so the page will show already the error from the cell query.

Do you see any drawbacks to doing it this way?

Thanks a lot for your help :slight_smile:

Actually, I think that’s not a bad compromise.

Though I can see that handling that on the web side might be more useful. I’ll give it some thought.

I think you can add a code in your SessionExpiredError and look for that in the result errors and extension.

Something like:

export class SessionExpiredError extends RedwoodGraphQLError {
  constructor(message: string) {
    super(message, { code: 'SESSION_EXPIRED' })

    Object.setPrototypeOf(this, SyntaxError.prototype)
  }
}

or add { code: 'SESSION_EXPIRED' } you the extensions in you code above.

That would be more convenient that checking an error message text in web side.

As for the api side … I think checking the message is the only way at the moment.

Oh good idea. So instead of just showing the message in the failure case of a cell, I could check the code and if the code is SESSION_EXPIRED I could log out the user automatically (and do the same when checking the error in my hooks using useQuery directly).

Is it what you meant ?

Yes, exactly!

1 Like

You are welcome, sorry for late answer and GG for the good work with dthyresson !