-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
GRPC reflection support #2160
GRPC reflection support #2160
Conversation
dd1c8db
to
b6fa782
Compare
7ba0243
to
e0ea261
Compare
Hey @mstoykov, can you elaborate on this? Could you share a code snippet for what you're proposing? |
@inancgumus , the current code there leads to metric emission for the reflect call. This, unfortunately:
|
Thanks, @mstoykov. OK, here are the notes of our call with Mihail:
|
I think there was some misunderstanding - I was talking about the fact the "reflect" connection get's closed at the end of the iteration instead of after it has finished, which is mostly based on the fact that it emits the metric at that time. You can check that at running the sample grpc reflect script with 1 iteration and 2 iteration and output metrics to a csv output for example in which case with 1 iteration there is 1
And in the other case there are 3
I have omitted the other samples emitted, but you can see how there is a So we either want this to not be emitted at all - perfectly fine for now.Or (in the future) to have some meaningful tags. |
But there is only one GRPC connection and the func (c *Client) reflect(ctxPtr *context.Context) error {
client := reflectpb.NewServerReflectionClient(c.conn) This is the one // Client represents a gRPC client that can be used to make RPC requests
type Client struct {
mds map[string]protoreflect.MethodDescriptor
conn *grpc.ClientConn // <----
} And that connection ( c.conn, err = grpc.DialContext(ctx, addr, opts...) Thanks for the other explanations. |
Then I guess we will need something else if the same connection is used 🤷 |
But you can add another context for the reflect "client" which seems to work from my quick test - it definitely didn't emit a metric as the context it will use for the
|
Thanks, @mstoykov, I'll try your patch, but I need to reproduce the issue here first. |
@inancgumus run with multiple iterations |
@mstoykov Do you mean the third This is for
This is for
There are also more of them, happens every time after the first iteration, interesting. |
@inancgumus - yes |
@mstoykov Whenever a GRPC request (receive) ends, the So:
Note: We can’t use another connection for this problem because Solution 1Canceling the context solves the problem. But as you said, it may create some other problems as I also witnessed. There happens many Solution 2Instead of canceling the context, we may transport a value in the context to let the type grpcContextKey int
const reflectionInProgress grpcContextKey = 1
func (c *Client) reflect(ctxPtr *context.Context) error {
*ctxPtr = context.WithValue(*ctxPtr, reflectiontInProgress, true)
...
} func (c *Client) HandleRPC(ctx context.Context, stat grpcstats.RPCStats) {
...
case *grpcstats.End:
inProgress, ok := ctx.Value(reflectionInProgress).(bool)
if ok && inProgress {
// prevent the metric emission from the reflect calls
return
}
...
} We can reset the context value to func (c *Client) Invoke(...) (*Response, error) {
*ctxPtr = context.WithValue(*ctxPtr, reflectionInProgress, false) Other Ideas
|
@inancgumus I'm not a fan of using the context to pass values like that or relying on some internal state, and would prefer the context cancellation approach if possible. Where did you see One behavior I noticed in the That said, I'm not sure if we should "hide" the fact another RPC call is made for the reflection. It makes sense to show metrics for that call as well, so we should only avoid emitting empty samples. |
@imiric Agreed. I didn't like it as well. It was emitting a metric because it was using a different context than the one the connection uses. So now there is no need to create and cancel another context. Fix: 927673d |
4abd4fc
to
d5c3620
Compare
Author: joshcarp <joshuacarpeggiani@gmail.com> Fix: Naming errors related with the new metric registry like: GRPCReqDurationName Co-Author: Inanc Gumus <m@inanc.io>
* reflect api error string * refactor reflect method * add more meaningful error messages
GRPC reflection was emitting empty metrics when enabled. This fixes the problem by using the same GRPC connection context with the reflection feature.
This commit removes the duplicated Invoke test from grpc reflection tests.
d5c3620
to
3492e3b
Compare
It's not in a super polished state but let's discover if it's good enough as it is. This work fixes some issues previously discussed (see the first comment of this PR). |
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.
LGTM, ❤️ the tests!
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.
LGTM
As I mention I still don't like the fact we don't return nil
when there are not tags, but the alternative change looks to be for HandleRPC to handle that, so I guess this is the lesser everl 🤷
@@ -33,7 +33,7 @@ func withTags(ctx context.Context, tags reqtags) context.Context { | |||
func getTags(ctx context.Context) reqtags { | |||
v := ctx.Value(ctxKeyTags{}) | |||
if v == nil { | |||
return nil | |||
return make(map[string]string) |
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 still don't like this change, but unfortunately by the looks of it - it will require some special handling in HandleRPC which likely will be the much more involved :(
This PR aims to fix some issues that happened in #1987.
Todo:
Invoke
tests (removed the duplication)k6 run
Connect()
plaintext
case*Client.reflect()
rb.Replacer.Replace
duplicationTestClient
table testassertResponse
for cross-platform testingConnectFloatTimeout
test backReflectBadParam
test