异常日志—— ESFramework 4.0 快速上手(03)
ESFramework框架(包括ESPlus、ESPlatform)实现时就内置了相对完整的日志功能,几乎所有的异常(Exception)和错误信息都会被记录到日志。通过查看日志记录,我们可以了解到程序在运行的过程中出现了哪些非正常的状况,并且,详细的日志记录可以帮我们迅速定位问题,并解决问题。(关于我对日志记录的更多认识,可以参看我的博文我的架构经验小结(五)-- 日志记录 )
一.IAgileLogger接口
首先,ESFramework框架使用ESBasic.Loggers.IAgileLogger接口来记录日志:
{
void Log(Exception ee, string location, ErrorLevel level);
void Log(string errorType, string msg, string location, ErrorLevel level);
注意,我们规定实现IAgileLogger接口的类不允许再抛出异常,也就是说ESFramework框架在调用IAgileLogger接口的Log方法时,是安全的,是不需要再try...Catch的。
二.EsfLogger属性
ESFramework框架内部有条隐藏的规则,即,所有需要用到日志记录的组件或类,必须暴露类型为IAgileLogger且名为"EsfLogger"的可写属性(setter),以表示该组件/类需要日志记录的支持。如:
private IAgileLogger esfLogger = new EmptyAgileLogger();
public IAgileLogger EsfLogger
{
set
{
if (value != null)
{
this.esfLogger = value ?? new EmptyAgileLogger();
}
}
}
#endregion
EmptyAgileLogger是采用nullobject模式的IAgileLogger接口实现,使用它,即表示不需要记录日志。
如果我们使用类似Spring这样的IOC容器来装配ESFramework的组件,那么就可以利用ESFramework框架的这条规则来快速的一次性为所有组件的EsfLogger属性赋值,而不是手动地去一个组件一个组件的赋值。像下面这样:
{
IList<object> objList = new List<object>();
string[] names = SpringContext.GetObjectDefinitionNames();
foreach (string name in names)
{
objList.Add(SpringContext.GetObject(name));
}
//从容器中找出用于日志记录的IAgileLogger对象
IAgileLogger logger = (IAgileLogger)SpringContext.GetObject("esfLogger");
//遍历集合中的每个组件实例,如果其有EsfLogger属性,则将日志记录对象赋值给它。
ESBasic.Helpers.ReflectionHelper.SetProperty(objList, "EsfLogger", logger);
}
三.ESFramework中用到日志记录的重要组件
ESFramework框架中有很多组件都用到了日志记录器,其中最重要的有如下几个组件:网络引擎组件(包括服务端引擎、客户端引擎、TCP引擎、UDP引擎、二进制引擎、文本引擎)、消息分派器组件、用户管理器组件。我们一一做简单解释。
1、网络引擎组件
所有的网络引擎都继承自INetEngine接口,而该接口中就定义了"EsfLogger"的可读写属性:
网络引擎主要在什么情况下使用日志记录器了?
(1)当接收到格式不正确的消息时。
比如,当使用文本协议时,接收到的消息的起始标识符不正确。这种情况下,网络引擎就认为收到了错误或恶意的消息,将记录消息来源IP、消息的内容到日志中。如果是TCP引擎,引擎还会断开对应的TCP连接。
(2)当从网络读数据或往网络写数据发声异常时。通常有两种情况:一是正在读写数据的时候网络断开;二是网络状况不好,写数据超时。
2.消息分派器组件 MessageDispatcher
当网络引擎接收到正确的消息后,会交给消息分派器去分派消息。
(1)当消息分派器根据消息的类型找不到对应的消息处理器(IMessageProcesser)时,将会记录日志。
我们可以根据日志发现哪些类型的消息没有被处理。这种情况很少出现,因为通常在消息协议的设计阶段,我们就为每种类型的消息设定了正确的消息处理器。除非,是消息的类型配置出错了。
(2)当消息分派器调用消息处理器处理消息时,消息处理器的方法抛出了异常,这个异常会被消息分派器记录到日志。
消息处理器是由应用实现的,交由框架回调。消息处理器抛出异常,通常说明我们的业务逻辑处理有bug,这样的日志需要引起我们的高度重视,找到bug并解决bug。
3.用户管理器组件 IUserManager
用户管理器使用日志记录器记录用户的上下线、超时掉线、被挤掉线等事件。并且其提供了AppLogEnabled属性用于控制是否记录这些日志,对于大型系统来说,这个属性通常是关闭的。
四.快速引擎的日志记录
如果你使用的是ESFramework 4.0 快速上手一文中介绍的RapidServerEngine和RapidPassiveEngine,那么这两个引擎的内部在组装各组件时,已经为重要的组件实例装配了日志记录器(使用ESBasic.Loggers.FileAgileLogger类),这些日志记录器都是将日志内容记录到运行目录下的EsfLog.txt文件。
你不需要在运行目录下手动创建EsfLog.txt,因为当框架需要记录日志时,是会自动创建这个文件的。你可以定期检查EsfLog.txt文件的内容,以了解程序现在的运行状态,以便及时发现异常情况。
ESFramework 4.0 概述 (文末包含最新版本的ESFramework4.0以及相关demo、帮助文档下载)