grpc / grpc-go

The Go language implementation of gRPC. HTTP/2 based RPC
https://grpc.io
Apache License 2.0
21.15k stars 4.4k forks source link

Feature Request: Add Support for Generating Full Method Names List for Service-Level gRPC Interceptors #7591

Open Elsharaky opened 2 months ago

Elsharaky commented 2 months ago

Feature Request: Add Support for Generating Full Method Names List for Service-Level gRPC Interceptors

Summary

I’m requesting a feature that generates a list of full method names for each gRPC service during code generation. This would enable developers to apply interceptors at the service level more easily, particularly when working with dynamic gRPC server implementations that host multiple microservices, each containing multiple gRPC services.

Use Case

In my setup, I manage a dynamic implementation of a gRPC server that handles multiple microservices. Each microservice contains several gRPC services, and I need to selectively apply interceptors to certain services rather than individual methods.

For example, if I want to enforce authentication for a specific service, I would need to mark every method within that service as authenticated. Currently, this requires manually handling each method or writing custom logic to map method names, which can be cumbersome and error-prone.

Having a statically generated list of full method names for each service would simplify this process by allowing for service-wide logic to be applied without manually specifying each method.

Current Limitations

While the FullMethod property in UnaryServerInfo and StreamServerInfo can dynamically provide the service and method name during runtime, this is not sufficient for my use case, which involves selectively applying interceptors to a specific service only. My goal is to have a pre-generated list that can be referenced in interceptors, making it easier to control entire services.

Proposed Solution

I propose that the code generation logic for gRPC services includes a feature that generates a list of full method names for each service. This list could be used in gRPC interceptors to apply consistent logic (e.g., authentication, logging, or rate-limiting) across all methods within a service.

This feature would:

Potential Concerns

Conclusion

This feature would be particularly valuable for developers working in multi-service gRPC environments who need to apply interceptors at the service level. I believe it could improve the clarity and maintainability of gRPC code in such scenarios.

I’m happy to discuss this further and refine the idea based on feedback from the community and maintainers.

Thank you for your consideration!

purnesh42H commented 2 months ago

@Elsharaky this info should be in the proto descriptor codegen already so you alternatively can use the reflection API at runtime to dynamically build the list of method names. However, computing the list of full method names should ideally be once during the startup phase.

The FileDescriptor (proto.FileDescriptior) for a gRPC service holds all the information about the service's structure. You can retrieve the method names for any service from the descriptor. Perhaps you can use Service Descriptor which represents the metadata for a specific service, including its methods.

Elsharaky commented 2 months ago

Thanks @purnesh42H for your response and suggestion! However, I noticed that the link you shared seems to be private and accessible only to Google developers. This might not be available for the broader gRPC community.

Regarding your suggestion of using the FileDescriptor and reflection API at runtime, I understand that it's a powerful tool for dynamically retrieving method names. However, my proposal aims to avoid runtime reflection for this specific use case. The full method names are already present in the generated code, so it feels unnecessary to require every developer to reflect on the proto definitions at runtime when the method names could be provided directly during code generation.

By generating a list of full method names alongside the service code, developers can immediately access this data at compile time, improving performance and simplifying the process. This also reduces the need for additional runtime reflection logic, which can become cumbersome in larger, more dynamic environments.

My suggestion is more about improving developer experience and reducing overhead, especially in multi-service environments, where pre-generated method lists could be a cleaner and more efficient solution.

I'd be happy to discuss further if needed!

purnesh42H commented 1 month ago

We will need to evaluate trade-offs between generating a list of method names at compile time versus using reflection at runtime. However, in case someone wants to retrieve such a information can use FileDescriptor and reflection at runtime.

Elsharaky commented 1 month ago

Thanks @purnesh42H for the follow-up! I understand that there’s a trade-off between generating method names at compile time versus using reflection at runtime. Reflection is indeed useful in dynamic contexts, but my suggestion is more about providing an option for developers who prefer compile-time solutions for performance and simplicity.

Since the full method names are already part of the generated code, exposing them directly at compile time would avoid the overhead of reflection for those who don’t need dynamic behavior. It can also provide a more straightforward, static approach for cases where services don’t change frequently. This would give developers the flexibility to choose between a runtime or compile-time solution based on their use case.

Of course, I agree that reflection remains a great fallback for dynamic use cases. I'd be happy to help evaluate these trade-offs further if needed!

github-actions[bot] commented 1 month ago

This issue is labeled as requiring an update from the reporter, and no update has been received after 6 days. If no update is provided in the next 7 days, this issue will be automatically closed.

purnesh42H commented 1 month ago

@Elsharaky would you be willing to contribute to this? We should also try do some research on other language libraries like java and c++ to see if they have something similar. However, considering that there is an alternate way to retrieve the information, it will be low priority for maintainers to implement.

Elsharaky commented 1 month ago

Thanks @purnesh42H for considering my proposal! I’d be happy to contribute to this. I can start by researching how other language libraries like Java and C++ handle this, to see if they provide similar functionality or offer other approaches. I understand that this may be a low priority for maintainers, but I believe it can add value for developers who prefer a compile-time solution.

I’ll get started on the research and can provide updates once I gather more information. Looking forward to working on this!

purnesh42H commented 1 month ago

Thanks @Elsharaky

isgj commented 3 weeks ago

Sorry for jumping in, if I understand this correctly you can already create the list of the methods by looping the methods and streams of the service description .

However, if you want to apply an interceptor to a specific service, instead of looping all its methods/streams, just check if the FullMethod starts with the service name, it's even faster. All the methods of a service start with the service name https://github.com/grpc/grpc-go/blob/master/examples/route_guide/routeguide/route_guide_grpc.pb.go#L36-L39