通常的.net项目好比ASP.NET、控制台程序、Windows服务、桌面程序等都会有framework自带的全局异常捕获机制。ASP.NET的ExceptionFilterAttribute,控制台和Windos服务的AppDomain.CurrentDomain.UnhandledException。那么gRPC的异常捕获是如何实现的。框架
首先来讲一下我走的弯路。个人grpc服务端是依托于.net的控制台程序,同时使用TopShelf框架建立Windows服务。Topshelf有自带的全局异常内部实现也是对AppDomain.CurrentDomain.UnhandledException作了一些封装。可是通过测试发现这种方式是不能捕获gRPC内部的异常的。那么就判断了确定gRPC内部已经对全局的异常作了捕获,因此咱们在控制台使用UnhandledException是不能捕获到的。而后查看gRPC源码,发现gRPC内部的全部异常都会内部消化,而后记录到一个叫ILogger的日志接口,所以咱们只须要在控制台实现ILogger接口,在初始化gRPC服务的时候声明就能够了。工具
首先实现gRPC内部的Grpc.Core.Logging.ILogger接口测试
public class GrpcLogger : ILogger { public ILogger ForType<T>() { return this; } public void Debug(string message) { LogUtil.Debug(message); } public void Debug(string format, params object[] formatArgs) { LogUtil.Debug(format); } public void Error(string message) { LogUtil.Error(message); } public void Error(string format, params object[] formatArgs) { LogUtil.Error(format); } public void Error(Exception exception, string message) { LogUtil.Error($"{message}:{exception.ToString()}"); } public void Info(string message) { LogUtil.Info(message); } public void Info(string format, params object[] formatArgs) { LogUtil.Info(format); } public void Warning(string message) { LogUtil.Warn(message); } public void Warning(string format, params object[] formatArgs) { LogUtil.Warn(format); } public void Warning(Exception exception, string message) { LogUtil.Warn($"{message}:{exception.ToString()}"); } }
LogUtil是个人项目里面的日志系统工具类。此处就至关于把gRPC内部的异常日志所有记录到我本身实现的日志系统中,能够自行控制。this
ForType
第二步就是直接把这个GrpcLogger类在服务初始化以后,服务开启以前申明日志
GrpcEnvironment.SetLogger(new GrpcLogger());
便可。code