'gRPC intercept calls in C#

I'm using gRPC in C# (NETCore). I would like to log each single method call, and I expect to have some way of intercpt each call at once, instead of putting a log on each service method. Did not find how, but does not exist some interceptor strategy?



Solution 1:[1]

It's possible to define your custom interceptor for a client and a server side. In both cases, you need to create a new class which inherit from Interceptor class and override methods that you want to intercept. For a client-side interceptor is connected with the entire client class. In Server side interceptor is created only for a service definition - it means that if you want to have logging interceptor, you need to specify it for an every service definition. Additionally, for a client side, you can use an already available extended method with Func as a parameter that can be used for straightforward intercept scenarios (I will not show you a code for it because I don't' have access to it right now).

Below you have simple interceptor:

public class GlobalServerLoggerInterceptor : Interceptor
{
    private readonly ILogger logger;

    public GlobalServerLoggerInterceptor(ILogger logger)
    {
        this.logger = logger;
    }

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation)
    {
        logger.Debug($"{Environment.NewLine}GRPC Request{Environment.NewLine}Method: {context.Method}{Environment.NewLine}Data: {JsonConvert.SerializeObject(request, Formatting.Indented)}");

        var response = await base.UnaryServerHandler(request, context, continuation);

        logger.Debug($"{Environment.NewLine}GRPC Response{Environment.NewLine}Method: {context.Method}{Environment.NewLine}Data: {JsonConvert.SerializeObject(response, Formatting.Indented)}");

        return response;
    }
}

Initialiation of the interceptor for a server side (pseudo code):

   var server = new Grpc.Core.Server
            {
                Services =
                {

TestService.BindService(new TestImplementationService()).Intercept(IoC.Resolve<GlobalServerLoggerInterceptor>())
                },
                Ports = { new ServerPort("localhost", 1234, ServerCredentials.Insecure) }
            };

In the above example you may notice such statement:

.Intercept(IoC.Resolve<GlobalServerLoggerInterceptor>())

If your interceptor needs a reference to some other classes you need to initialize them before you run a server.

Solution 2:[2]

To create a client interceptor with Grpc.Core, you can do the following:

var clientInterceptor = new YourClientInterceptor();
var channel = new Channel($"localhost", ChannelCredentials.Insecure);
var interceptingInvoker = channel.Intercept(clientInterceptor);
var client = new YourServiceClient(interceptingInvoker);

Notice how channel.Intercept(clientInterceptor) returns a new call invoker for you to pass on to the client. A little unintuitive naming there, but that's what we have for now.

To intercept client calls, let your interceptor override/implement all the ...Call methods you need, for example BlockingUnaryCall(...) and AsyncUnaryCall(...).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adam ?epkowski
Solution 2 sergiol