gRPC全局異常捕獲
引
一般的.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內部的異常日志全部記錄到我自己實現的日志系統中,可以自行控制。
ForType
第二步就是直接把這個GrpcLogger類在服務初始化之后,服務開啟之前申明
GrpcEnvironment.SetLogger(new GrpcLogger());
即可。