-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
proposal: add introspection support for service/method descriptors #489
Comments
I don't think you're missing anything, it's probably more of a lack of needing this use-case. The generated protos simply register their generated descriptor; they shouldn't export it necessarily. The grpc package could provide a method such as About inspecting custom |
@misberner Feel free to re-open this discussion if you think adding a method to the grpc package to do this is the wrong approach. |
I would personally like the ability to retrieve the file descriptors, and ideally the service descriptors too. I don't think this would be inconsistent with the current API, as messages (structs) already include a |
@paranoiacblack if I'm understanding correctly, the option of adding a method to the grpc package requires that a service already be registered with a grpc server. I would like to be able to inspect the The use case here is for doing introspection on the service, so that we can do things like:
In general though, having I made #516. It's a minimal PR to expose the |
Hi @mightyguava, you mention being able to inspect
I think accessing these fields via reflection is a bad idea, as you stated. #516 seems okay on the face of it, but it would be much better if you could show me code that demonstrates how you're using it to achieve your goal. I still don't think exporting these descriptors gets you very far because it does not answer any particular questions about your service; it just gives you a simpler way to query it. |
@alecthomas I agree that it is not inconsistent with current exposure of the |
@paranoiacblack For 1 and 2, you are right, in principle, that having an I'm sure there can be some way for all of this to be provided by the I think you make a good point that the On point 3, I phrased it poorly. By client I meant the client fo the grpc library and the end-user, not the grpc client. I am not referring to listing methods on the server. I am referring to listing the canonical name of the service and methods of the service. For my use case, I would like to, before registering a service dynamically with a server, know which methods this service will be adding. I don't need information on the server they are being registered against because the server hasn't been created yet and I have full knowledge of the parameters it will have. I can do this by directly inspecting either the ServiceDesc or ServiceDescriptor. The ServiceDesc provides at a higher level the properties of the service and methods. The ServiceDescriptor provides basically full information about the service. This information can be useful for logging and debugging when dynamically registering grpc services to a server. I don't really want to write out additional code here, since my use case is pretty context dependent and wouldn't make much sense outside my project, as would be many other uses of this feature, or grpc in general really. |
The third place the canonical names are listed, on a given server, is https://godoc.org/google.golang.org/grpc#Server.GetServiceInfo, which also would answer your questions about whether or not that service is registered or not as well as which methods the server claims exist. My understanding of your change is that you would just use the ServiceDesc to get a canonical name to lookup, rather than going through the ServiceInfo mapping to discover it. There's not unreasonable, but I'd like to demonstrate its use in some test code or something before moving forward on that change. If the way you were going to use this is different, please explain. I don't buy the argument that About information about services being exposed to clients, I thought that was the intention behind https://github.com/grpc/grpc/blob/master/doc/service_config.md, although it seems like you would be unable to use this if you are dynamically registering services and methods. So to your actual problem, you want to do this all a-priori, before there's any server running I suppose. I'd still like you to provide a unit test that demonstrates how to use this feature, though. If your use-case is context dependent, we can massage it a bit into a reasonable test case. To be clear, I think your request is reasonable and appreciate the clarification. Please move forward with a small example and we can try adding this. |
@dfawley Can you share any thoughts on the line between grpc's service introspection and what the grpc proto plugin can provide to the user. I'm on the line about this change because it isn't clear to me how this interacts with services that use interception or service/method renaming. It seems like regardless of what any given generated service descriptor might tell you, grpc is the only package that can tell you the true state of any given server. Am I missing something? |
Hey @paranoiacblack, thanks for reopening the issue. What I'm trying to do is definitely context-dependent. Not really sure what you are looking for in terms of a unit test. I couldn't find any tests for the grpc generator in this repo. Here's a test that demonstrates the use of the A practical use of the descriptor proto in code would be very context dependent and doesn't really add any value here. If the goal is correctness and regression testing, golden tests should suffice. If the goal is understanding further why someone would want to introspect a service descriptor before registering with a server, let me know what I can add here other than the comments above. |
In an ideal world, the grpc proto plugin should only need to generate the stubs the user needs to use grpc with protobufs in a type-safe and user-friendly way. It should not be relied upon to provide "core" proto functionality like introspection/reflection of proto definitions themselves -- operations that could be useful with all RPC services. I'm sure there's a good reason for this, but can we not export Short of that, I'm not really sure what the best path forward is. The default proto generator currently doesn't generate any symbols for services. The grpc plugin only generates interfaces for services, meaning we can't attach a I also would like to learn more about use cases 1 and 2, and see how these would work in code. For 3, in case you aren't already aware, gRPC offers a reflection service that can be used to retrieve |
Having I think you make a very key argument here, that exposing the descriptor allows "operations that could be useful with all RPC services."
I admit, these are more hypotheticals to make a case for exposing the
Exactly. I am aware of the reflection service. But it would be super roundabout to register an implementation of a service on a dummy server, then register the reflection service, just to get the descriptor proto. It kind of defeats the purpose of using protobuf at all. |
I am thinking maybe exposing the ServiceDesc would actually help the reflection service to be injectable, rather than relying on a registration pattern. Then this can also help to solve this If we have this simple example: s := grpc.NewServer()
pb.RegisterYourOwnServer(s, &server{})
reflection.Register(s)
s.Serve(lis) The reflection.Register can then call ServiceDesc to get the service descriptor. |
@dfawley Thanks for the feedback. We could export @awalterschulze I'm not really familiar about the intersection between proto reflection and service registration. But yes, this could be used to get partial information about the service, such as its canonical name and canonical method set, before the service is altered on registration. @mightyguava Let's move forward with your change in #516. I still haven't seen a compelling use-case for this feature and you haven't provided a demonstration of its utility because you say it's context-dependent. So I'm reluctant to be exporting yet another poorly understood feature in this library, but I'm willing to take on the technical debt for when we end up breaking it. Overall, it seems reasonable, even if I don't understand it. |
@paranoiacblack maybe we should chat more about this offline, but my hope was that by exporting the full @mightyguava in #516, why do also want access to |
@dfawley I want to be able to programmatically reference something that I can use to inspect the service. It doesn't matter as much whether this is a Did you guys end up chatting offline? I can see having list of |
Why not? The |
I would like to be able to directly reference |
I apologize for jumping into this discussion late in the game. I've been working on #364, which provides a behaviorally complete API for interfacing with proto messages. In order to do this, there needs to be an abstraction over the protobuf type system, which are encapsulated in proto as descriptors. As such, the API I'm working on fundamentally needs to involve some abstraction over the ProtoDescriptors. As I continue to work on this, it is becoming increasingly clear to me that Service and Method descriptors should be a part of the API that allows you to get the descriptors for all proto declarations. I understand there is a desire for this feature today, but perhaps it should wait until work on #364 is complete. I'd rather not add another function that we will likely mark as deprecated in the near future. |
It just occurred to me that this is entirely a subset of #293. Closing as duplicate. |
For the OP's question, here's a simple way to get custom method and service options: |
The former is an important part of this issue, and the latter is also functionality that would be very useful for things like interceptors that are used with multiple services/methods and might need access to their related options. |
tl;dr. Yes and Yes.
|
@dsnet - That all sounds great to me. Thanks! |
It seems to me that the generated Go code for a proto file with services does not allow a general way to obtain descriptors for services. As a consequence, there is no way of inspecting custom
ServiceOptions
orMethodOptions
extensions at runtime.The only exported symbols are the
Register...
method for the service side, andNew...Client...
methods for the client. Both are not suitable for obtaining a descriptor. While it maybe possible to get to that information via theFileDescriptorProto
, there likewise is no general way to obtain a file descriptor from the Go code generated from a proto file - after all, no messages might be declared in that same file.Am I missing something here? This seems to be a surprising omission.
The text was updated successfully, but these errors were encountered: