grpc-dotnet icon indicating copy to clipboard operation
grpc-dotnet copied to clipboard

Method level Interceptors

Open cosullivan opened this issue 4 years ago • 6 comments

Hi,

Are there any plans to add support for method level interceptors?

I have a project which I have created a custom IServiceMethodProvider<> implementation for service discovery and would like the ability here to add interceptors for specific methods in the service. These interceptors would then be combined with any global or service level interceptors.

I have tested this functionality on a fork by adding it just for Unary methods and it is fairly straight forward to pass this through.

Thanks, Cain.

cosullivan avatar Sep 17 '19 14:09 cosullivan

None at the moment. This is the first time it has been requested. Right now configuration, including interceptors can be customized per-service.

JamesNK avatar Sep 17 '19 22:09 JamesNK

Hi,

I am happy to contribute a PR if you are OK with the idea of method level options/interceptors.

I have implemented it for Unary calls only in my fork as that's what I was interested in and the changes look like this;

Manual configuration:

services.AddGrpc().AddServiceOptions<GreeterServer>(serviceOptions => 
{
    serviceOptions.AddMethodOptions(nameof(GreeterService.SayHello), methodOptions =>                    
    { 
        methodOptions.Interceptors.Add<TracingInterceptor>();
    });    
})

To support configuration via IServiceMethodProvider<> I have changed the ServiceMethodProviderContext<TService> so the options can be modified during discovery time.

public void AddUnaryMethod<TRequest, TResponse>(Method<TRequest, TResponse> method, IList<object> metadata, UnaryServerMethod<TService, TRequest, TResponse> invoker, Action<GrpcServiceMethodOptions> configure)

Let me know your thoughts.

Thanks, Cain.

cosullivan avatar Sep 18 '19 15:09 cosullivan

Interesting feature! I want to be careful about adding this because it has a lot of public API.

Some things to consider:

  1. What about setting the other properties on a service against a method
  2. Would configuring interceptors and other options using attributes be better?

JamesNK avatar Sep 24 '19 00:09 JamesNK

I made the change on a fork to minimize breakage to the public API, but there might be some better ways to do it.

In regards to your considerations,

  1. Yes, I think a lot of settings could be added on a method level and it would make sense to do so. I would imaging that method level takes preference over service level over global.

  2. Configuring via attributes is actually what I was wanting this change for. I have a custom IServiceMethodProvider which configures a service based entirely on attributes, similar to how a Controller can be configured with routes in MVC.

I have it working with Unary methods only at the moment but this is what it looks like;

[GrpcService("Health")]
public class HealthService
{
    [GrpcMethod]
    [Interceptor(typeof(TracingInterceptor))]
    [Interceptor(typeof(UnhandledExceptionInterceptor))]
    [Interceptor(typeof(TransactionScopeInterceptor))]
    public Task<PingResponse> Ping(
        [FromService] ITransaction transaction,
        [FromUserState("SomethingStateName")] string name,
        PingRequest request,
        ServerCallContext context)
    {
        return Task.FromResult(new PingResponse());
    }
}

It should be pretty easy for a gRPC method type to be discovered based on it's parameters and this doesn't require the base service implementation to be used either.

At the moment I've built this into the IServiceMethodProvider but if there was a way to introduce a separate provider interface for configuring a method then the methods and configuration could be provided separately.

For example, in the case where the service implemented the gRPC generated base service then the method discovery would work as it currently does but the configuration of methods could be done externally to that. However, in my case I would want the method discovery to be done via attributes but that could then use the same method configuration provider if that makes sense?

Thanks, Cain.

cosullivan avatar Sep 24 '19 00:09 cosullivan

Besides method level interceptors, service level ones (which is supported by grpc c# lib) are also very helpful. A server can host multiple services that implements different interception logic

hanabi1224 avatar Feb 26 '20 06:02 hanabi1224

You can already do that by configuring inteceptors against a service.

https://docs.microsoft.com/en-us/aspnet/core/grpc/configuration?view=aspnetcore-3.1#configure-services-options

JamesNK avatar Feb 26 '20 07:02 JamesNK