蛙蛙推荐:设计一个Tracing组件

蛙蛙推荐:设计一个Tracing组件
【需求】
wawaKM的数据访问,性能计数器,主键生成的公共组件都做好了,为了便于以后排查问题的方便,还得做一个Tracing的公共组件,罗列需求如下:
1、能把跟踪信息记录到各种记录器里,默认要实现文本和数据库的记录;
2、要有一个能记录EventLog的接口,以便记录重要的系统级别的跟踪信息;
3、记录器可以扩展,比如实现一个UDP记录器,以便可以在其它机器实时查看trace;
4、Tracing组件不能影响主业务性能;
5、跟踪信息可以分级别,Info,Warn,Error
6、可以单独给不同级别的跟踪信息配置记录器,比如所有Error的日志记录到一个SMTP的记录器里发到指定的收件箱
7、跟踪信息可以分类别,便于以后查找某类别的跟踪信息
8、跟踪信息要默认把当前所在的机器IP,所属类,进程、线程、AppDomain,时间等信息记录下来。
9、修改跟踪相关配置后即时生效,无需重启应用
【配置】
根据需求,指定配置文件大约如下
<WawaTrace
  
category="login;sync"
  enabled
="true"
  enabled_system_trace
="false"
  enabled_web_trace
="true">
  
<TextAppender enabled="true" level_filter="*" cate_filter="*"   console="true" trace_path=""></TextAppender>
  
<DbAppender enabled="true" Level_filter="error" cate_filter="login" connstr=""></DbAppender>
  
<UDPAppender enabled="true" enable_ip_filter="true">
    
<Observer ip="192.168.0.250" user="大碗豆浆" pwd="@_@-_-"/>
    
<Observer ip="192.168.0.111" user="千山一鸟" pwd="-_-@_@"/>
  
</UDPAppender>
</WawaTrace>

解释一下,
WawaTrace节点:category表示跟踪类别,多个分类用英文半角分号隔开;enabled表示是否启用跟踪,可取true和false。enabled_system_trace是否捕获System.Diagnostics.Trace的跟踪信息;enabled_web_trace写日志的时候是否同时也写入web的跟踪里。
TextAppender节点:enabled表示是否启用文本记录器,level_filter表示跟踪级别过滤器,如选*表示记录所有级别trace,如选error即只记录error级别的日志,可取*,error,warn,debug,info;cate_filter表示跟踪类别过滤器,可以取WawaTrace的category属性的值和*值,多个值用英文半角分号隔开,表示本记录器只记录某些类别的跟踪信息;console表示在输出到文本的时候是否同时输出到标注控制台输出;trace_path表示文本日志保存的目录。
DbAppender节点:enabled,Level_filter,cate_filter同TextAppender,connstr表示日志记录的数据库连接字符串,其中表名和字段名都应该是事先约定好的。
UDPAppender节点:enabled,Level_filter,cate_filter同TextAppender,enable_ip_filter属性表示是否启用IP过滤,如果不启用IP过滤,跟踪观察者只要有用户名和密码就可以查看跟踪信息。
UDPAppender/Observer节点:ip表示观察者所在的机器IP,当启用了enable_ip_filter的时候才起作用,user和pwd分别表示该ip上所允许的观察者的用户名和密码。
【接口设计】
要开发一个组件或者类库,要先要从使用者的角度去考虑,想想他们怎么去用你的组件感觉比较舒服,所以要先设计好用户的使用接口,考虑有哪些用户使用的场景。
1、获取一个默认跟踪器实例
static ITraceing _tracer = TracerFactory.GetTracer(typeof(MyClass));
其中MyClass是使用Tracer的类名
2、获取一个带类别的跟踪器实例
static ITraceing _tracer = TracerFactory.GetTracer(typeof(MyClass), MyTraceCate.Login);
其中MyTraceCate是一个保存所有类别信息的类,里面只有一些常量。
3、记录跟踪信息
_trace.Info("this is a test trace"); //记录一条日志
_trace.Info("{0}是个大坏蛋", name); //用string.Format记录日志
_trace.Error(ex,"here has a error"); //记录一个异常信息,其中ex是一个异常
4、记录一条系统日志
SystemEventLog.Info(GlobalUiti.ApplicationName, "application ia start"); //记录一条消息级别的系统日志
SystemEventLog.Wran(ex,GlobalUiti.ApplicationName, "application has an error"); //记录一条警告级别的系统日志,其中ex是一个异常
其中GlobalUiti.ApplicationName充当eventlog的事件源,SystemEventLog做成一个静态类
用户接口设计要尽量简单直观,方便使用,好的组件就应该是使用简单,配置灵活,好了,下一步,设计大框架。
【概要设计】
一般概要设计可以用文字描述,UML图,伪代码等来表达,其中伪代码最有表达力,不用像UML还要生成代码,也不用像文字描述那样有二义性,我们先用伪代码表达一下概要设计,然后再详细说一说每个类,代码如下
user interface and imp

enum and entity class

TraceAppender

Config

SystemTrace

Utilities

说明:
1、ITracer是用户使用的接口类,用户用它来进行日志记录,里面写了几个原型方法,当然还不全,每个方法应该都有一系列的重再方法。TracerImp是ITracer的实现,里面调用各种TraceWriter来写日志,这里面要用一个队列来缓存要记录的跟踪信息,然后用一个线程来论询扫描队列进行日志记录,这样可以防止直接对硬盘、数据库、网络的集中写操作。TracerFactory里有两个工厂方法,用来方便用户使用日志记录器,该类可以声明为静态类。
2、TracingLevel是跟踪级别,这里用枚举来表示,真实情况下应该用一个实现IComparable接口的类(有待推敲)。TraceItem表示一条跟踪消息,包含了一条跟踪消息所有的信息。
3、ITraceWriter是一个抽象类(命名成一个接口了,回头再改),它表示一个日志记录器,用它来把跟踪消息记录到各种存储器上,分别有跟踪级别,跟踪类别,是否启用几个属性,以及记录日志的方法。TextTraceWriter,DbTraceWriter,UDPTraceWriter分别是ITraceWriter的三个实现,分别实现文本,数据库和UDP的记录。
4、TraceConfig用来读取和缓存配置信息,对应于上面的XML配置,这里用了好多嵌套类,再详细设计的时候最好不要这样用。
5、SystemEventLog封装了EventLog的操作,让用户可以轻松访问系统日志。
6、MonitorUtilities是一个帮助类,用来把一个异常的详细信息,包括内部异常的信息,获取本机IP,当前线程,进程,应用程序域等信息,以及以安全的方式(不像string.format会抛出异常)格式化一个字符串。

【小节】
概要设计和伪代码有了,就要写测试用例和实现具体逻辑的代码了,测试用例就针对用户接口编写就行了。具体类的编码上就要考虑算法的细节,性能这些了,写的时候我再把细节整理一下,先写到这儿。
不用劝我有entlib.loger,log4net,nlog啥的这些东西,没必要自己实现一个,我就是闲着没事写着玩儿,自己写的是自己的,而且灵活,简单,自己懂,出错了自己好查。
本文主要写一个组件或者类库从需求到设计的这么一个过程,不涉及详细的技术细节,我接下来会实现这个设计。
posted @ 2007-11-04 13:11  蛙蛙王子  Views(2225)  Comments(10Edit  收藏  举报