services.AddGrpc(opt =>
{
opt.EnableDetailedErrors = true;
opt.Interceptors.Add<LogInterceptor>();
});
public class LogInterceptor : Interceptor
{
private readonly ILogger<LogInterceptor> _logger;
private AppConfig _appConfig;
public LogInterceptor(ILogger<LogInterceptor> logger, IOptionsSnapshot<AppConfig> appConfig)
{
_logger = logger;
_appConfig = appConfig.Value;
}
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request,
ServerCallContext context,
UnaryServerMethod<TRequest, TResponse> continuation)
{
try
{
var response = await continuation(request, context);
if (_appConfig.ShowRequestLog)
{
_logger.LogInformation($"Started call Method: { context.Method}. Request: {request}. Response: {response}. Status: { context.Status}");
}
return response;
}
catch (System.Exception ex)
{
_logger.LogError(ex, $"异常 Call Method: { context.Method}. Request: {request}");
}
return null;
}
}
###第一种注入方式
services.AddGrpcClient<Client>(o =>
{
o.Address = new System.Uri("http://localhost:5002");
}).EnableCallContextPropagation(o => o.SuppressContextNotFoundErrors = true)
.AddInterceptor<ErrorInterceptor>();
###第二种注入方式
readonly CallInvoker _grpcChannel;
public ClassNameGrpc(IOptionsMonitor<ApiConfig> apiConfig, ErrorInterceptor errorInterceptor)
{
_grpcChannel = GetGrpcChannel(errorInterceptor, apiConfig.CurrentValue.Api.Address);
}
public CallInvoker GetGrpcChannel(ErrorInterceptor errorInterceptor, string url)
{
var defaultMethodConfig = new MethodConfig
{
Names = { MethodName.Default },
RetryPolicy = new RetryPolicy
{
MaxAttempts = 2,
InitialBackoff = TimeSpan.FromSeconds(1),
MaxBackoff = TimeSpan.FromSeconds(5),
BackoffMultiplier = 1.5,
RetryableStatusCodes = { StatusCode.Unavailable }
}
};
var grpcChannel = GrpcChannel.ForAddress(url, new GrpcChannelOptions
{
ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } },
HttpClient = new System.Net.Http.HttpClient()
{
Timeout = TimeSpan.FromSeconds(10)
}
});
return grpcChannel.Intercept(errorInterceptor);
}
###客户端拦截器
using Grpc.Core;
using Grpc.Core.Interceptors;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace MallWin.Live.GrpcClient.Core
{
public class ErrorInterceptor : Interceptor
{
private readonly ILogger<ErrorInterceptor> _logger;
public ErrorInterceptor(ILogger<ErrorInterceptor> logger)
{
_logger = logger;
}
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(
TRequest request,
ClientInterceptorContext<TRequest, TResponse> context,
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
var call = continuation(request, context);
return new AsyncUnaryCall<TResponse>(HandleResponse(context.Method, request, call.ResponseAsync), call.ResponseHeadersAsync, call.GetStatus, call.GetTrailers, call.Dispose);
}
private async Task<TResponse> HandleResponse<TRequest, TResponse>(Method<TRequest, TResponse> method, TRequest request, Task<TResponse> responseTask)
{
try
{
var response = await responseTask;
return response;
}
catch (RpcException ex)
{
_logger.LogError(ex, $"LiveApi调用GRPC异常 Call Method:{method.FullName} Request: {request}");
return System.Activator.CreateInstance<TResponse>();
}
}
}
}