'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 |