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

handlers_user: Include db err in the internal error #984

Merged
merged 1 commit into from
Sep 22, 2023

Conversation

jhrozek
Copy link
Contributor

@jhrozek jhrozek commented Sep 19, 2023

Errors like these are what we would print e.g. when adding a duplicate
user:

{"level":"error","Resource":{"service":"mediator.v1.UserService","method":"CreateUser"},"Attributes":{"http.code":"Internal","http.content-type":["application/grpc"],"http.duration":"550.55325ms","http.user_agent":["grpc-go/1.58.1"],"exception.message":"rpc
error: code = Internal desc = failed to create
user"},"Timestamp":1695131280165826000}

Now we get:

{"level":"error","Resource":{"service":"mediator.v1.UserService","method":"CreateUser"},"Attributes":{"http.code":"Internal","http.content-type":["application/grpc"],"http.duration":"547.674ms","http.user_agent":["grpc-go/1.58.1"],"exception.message":"rpc
error: code = Internal desc = failed to create user: pq: duplicate key
value violates unique constraint
\"users_organization_id_username_lower_idx\""},"Timestamp":1695131520115208000}

The user still gets just an internal error in the CLI, but at least we
see what's going on in the server logs.

@@ -156,25 +156,25 @@ func (s *Server) CreateUser(ctx context.Context,
FirstName: *stringToNullString(in.FirstName), LastName: *stringToNullString(in.LastName),
IsProtected: *in.IsProtected, NeedsPasswordChange: needsPassPtr})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to create user")
return nil, status.Errorf(codes.Internal, "failed to create user: %s", err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

We can use %w instead.

Copy link
Member

Choose a reason for hiding this comment

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

(also, error implements strings.Stringer, so you could use %s if you just wanted the error string. But Ozz's suggestion is better)

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'm not sure we can use %w here because status.Errorf (not to be confused with stdlib's fmt.Errorf) uses fmt.Sprintf internally which IIUC doesn't support the %w formatter.

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 wasn't sure about %w from the top of my head, but a quick go playground experiment seems to agree.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(also, error implements strings.Stringer, so you could use %s if you just wanted the error string. But Ozz's suggestion is better)

Does it? I'm seriously questioning my Go-fu now, but I thought that error only ever had to implement the Error method and that errors were handled internally in the formatter by calling Error in the fmt module.

Anyway, calling Error explicitly is not needed and I'll drop it (even though it would be nice to be consistent, there's a bunch of places where we call Error explicitly)

@evankanderson
Copy link
Member

I'm also wondering if just returning err in these cases would be sufficient, given that the log message will include the method name. But I don't feel strongly either way.

@jhrozek
Copy link
Contributor Author

jhrozek commented Sep 22, 2023

I'm also wondering if just returning err in these cases would be sufficient, given that the log message will include the method name. But I don't feel strongly either way.

I thought the point was to carry the grpc error code along with the returned error.

Errors like these are what we would print e.g. when adding a duplicate
user:
```
{"level":"error","Resource":{"service":"mediator.v1.UserService","method":"CreateUser"},"Attributes":{"http.code":"Internal","http.content-type":["application/grpc"],"http.duration":"550.55325ms","http.user_agent":["grpc-go/1.58.1"],"exception.message":"rpc
error: code = Internal desc = failed to create
user"},"Timestamp":1695131280165826000}
```

Now we get:
```
{"level":"error","Resource":{"service":"mediator.v1.UserService","method":"CreateUser"},"Attributes":{"http.code":"Internal","http.content-type":["application/grpc"],"http.duration":"547.674ms","http.user_agent":["grpc-go/1.58.1"],"exception.message":"rpc
error: code = Internal desc = failed to create user: pq: duplicate key
value violates unique constraint
\"users_organization_id_username_lower_idx\""},"Timestamp":1695131520115208000}
```

The user still gets just an internal error in the CLI, but at least we
see what's going on in the server logs.
@jhrozek jhrozek merged commit 02f9e25 into mindersec:main Sep 22, 2023
12 checks passed
@evankanderson
Copy link
Member

I'm also wondering if just returning err in these cases would be sufficient, given that the log message will include the method name. But I don't feel strongly either way.

I thought the point was to carry the grpc error code along with the returned error.

I think if you return error, it will map to codes.Internal unless you have a different error type. Also, unless you use util.UserVisibleError, the message text will be hidden from the RPC reply by code in the SanitizingInterceptor in the same file.

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

Successfully merging this pull request may close these issues.

3 participants