通常的.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