Enterprise Library Step By Step系列(八):日志和监测应用程序块——进阶篇

 写在前面:最近一段时间项目比较紧,所以这篇随笔出来的晚一些。今天写的是在日志里面包含名-值对的字典,跟踪活动并记录上下文信息,过滤事件,定制日志消息的格式,自定义Sink,自定义Formatter等。

一.在日志里面包含名-值对的字典:

在日志消息里面,我们可以包含名-值对这样的字典。这时首先需要创建一个Hashtable,通过Key-Value的方式把要记录的内容传入。示例代码如下:

 1///创建一个日志项
 2            LogEntry log = new LogEntry();
 3            
 4            ///创建名-值对
 5            Hashtable logtable = new Hashtable();
 6            logtable["key1"= "value1";
 7            logtable["key2"= "value2";
 8            logtable["key3"= "value3";
 9            
10            log.Message = this.txt_LogMessage.Text;
11            log.Category = Category.General;
12            log.Priority = Priority.Normal;
13            
14            ///写入日志
15            Logger.Write(log,logtable);

输出后的文本:在这里我们用了Text Formatter


二.跟踪活动并记录上下文信息:

跟踪应用系统的活动是一项常见的功能,我们需要把活动的起始时间和结束时间以及活动的其他的信息记录下来。日志和监测应用程序块支持通过活动ID来跟踪一项活动,活动ID可以在代码中指定,也可以通过程序块来自动生成,程序块自动记录活动的起始时间和结束时间。活动跟踪由Tracer类来提供。示例代码如下:

1using(new Tracer("UI Events"))
2            {
3                Logger.Write("Troubleshooting message");
4            }

输出后的文本:同样我们用了Text Formatter

三.过滤事件:

在日志和监测应用程序块里面,支持两种方式的过滤事件:基于优先级过滤事件和基于类别过滤事件。过滤的过程发生在日志项传递给分发策略之前。在入门篇里我们知道,每个日志消息都会有一个优先级,我们可以在代码中指定或默认值为-1。我们可以通过配置 Client Setting使低于某个优先级的消息被过滤掉,只记录某个类别的消息或者过滤掉具有某个类别的日志项。

在下面的图中,日志项为01的消息将不被记录。


Client Setting
CategoryFilterSettings属性决定某个类别的日志是被记录还是被过滤掉。我们可以自行进行设置:


在下图中,
”UI Events”类别的日志将不被记录。


四.定制日志消息的格式:

Formatter接受一个日志项的并返回一个格式化的字符串,应用程序块格式化将字符串传给SinkText Formatter 使用模版生成格式化字符串,在应用配置中可以有多个 Text Formatters,每个有自己的模版同时我们也可以定制自己的 Formatter

日志项根据其类别导向到目的地目的地规定了 Formatter 和接收格式化日志项的 Sink


Text Formatter
有一个模版配置属性。

模版编辑器定制日志项的格式, {参数}由日志项的值填充。


五.创建和使用自定义
Sink

在日志和监测应用应用程序块里面,允许我们自定义一个Sink,而且使用方法要比其它的应用程序块中的自定义简单的多。下面我们具体看一下:

1.添加对应用程序块的引用:

Microsoft.Practices.EnterpriseLibrary.Configuration.dll

Microsoft.Practices.EnterpriseLibrary.Logging.dll

2.添加命名空间:

1using Microsoft.Practices.EnterpriseLibrary.Configuration;
2using Microsoft.Practices.EnterpriseLibrary.Logging;
3using Microsoft.Practices.EnterpriseLibrary.Logging.Sinks;
4using Microsoft.Practices.EnterpriseLibrary.Logging.Distributor.Configuration;

3.编写代码:

我们的自定义Sink要继承LogSink这个基类,同时要重载Initialize()和SendMessageCore()这两个抽象方法

 1using System;
 2using Microsoft.Practices.EnterpriseLibrary.Configuration;
 3using Microsoft.Practices.EnterpriseLibrary.Logging;
 4using Microsoft.Practices.EnterpriseLibrary.Logging.Sinks;
 5using Microsoft.Practices.EnterpriseLibrary.Logging.Distributor.Configuration;
 6
 7namespace EnterpriseLogging
 8{
 9    /// <summary>
10    /// 功能说明:自定义Sink
11    /// </summary>

12    public class ConsoleSink:  LogSink
13    {
14        private LoggingConfigurationView configView;
15 
16        public override void Initialize(ConfigurationView configurationView)
17        {
18            this.configView = configurationView as LoggingConfigurationView;
19        }
 
20 
21        protected override void SendMessageCore(LogEntry logEntry)
22        {
23            CustomSinkData sinkData;
24            sinkData = (CustomSinkData) this.configView.GetSinkData(this.ConfigurationName); 
25 
26            /// Delimit each log entry
27            Console.WriteLine((string) sinkData.Attributes["delimiter"]); 
28 
29            /// Write the formatted log entry to the Console
30            Console.WriteLine(FormatEntry(logEntry));
31        }
 
32    }

33}

34

4.打开配置工具,并打开配置文件。在Sink节点上,我们选择Custom Sink。同时起名为Console Sink


5
.单击TypeName右边的省略号,打开Type Selector对话框。单击Load an Assembly …,并浏览选择我们工程文件的DLL。最后选择Console Sink类。


6
.单击Attributes 打开NameValueItem Collection Editor。单击Add创建一个新的NameValueItem,起名为delimiter,并设置它的Value值(这个值可以随意设置,比如我们设置************************)。


7.选择General,创建一个Destination,并设置下列属性:

·   Formatter = Text Formatter,

·   Name = Console Destination

·   Sink = Console Sink

8.把程序输出的方式设为控制台的方式,运行程序。

六.创建和使用自定义Formatter

1.添加如下的命名空间:

1using System.Globalization;
2using System.IO;
3using System.Xml;
4using Microsoft.Practices.EnterpriseLibrary.Configuration;
5using Microsoft.Practices.EnterpriseLibrary.Logging;
6using Microsoft.Practices.EnterpriseLibrary.Logging.Distributor.Configuration;
7using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;

2.以Hands On Lab里面的XmlFormatter为例,在自定义Formatter时我们需要继承ConfigurationProvider类和实现 IlogFormatter接口,并且需要重载Initialize()这个抽象方法。

 1using System;
 2using System.Globalization;
 3using System.IO;
 4using System.Xml;
 5using Microsoft.Practices.EnterpriseLibrary.Configuration;
 6using Microsoft.Practices.EnterpriseLibrary.Logging;
 7using Microsoft.Practices.EnterpriseLibrary.Logging.Distributor.Configuration;
 8using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
 9
10namespace LoggingSink
11{
12    /// <summary>
13    /// 功能说明:自定义Formatter
14    /// </summary>

15    public class XmlFormatter : ConfigurationProvider, ILogFormatter
16    {
17        private LoggingConfigurationView configView = null;
18 
19        public override void Initialize(ConfigurationView configurationView)
20        {
21            this.configView = (LoggingConfigurationView) configurationView;
22        }
 
23 
24        public string Format(LogEntry log)
25        {
26            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
27            {
28                XmlTextWriter w = new XmlTextWriter(sw);
29                w.Formatting = Formatting.Indented;
30                w.Indentation = 2
31                w.WriteStartDocument(true);
32                w.WriteStartElement("logEntry");
33                w.WriteAttributeString("Category", log.Category);
34                w.WriteAttributeString("Priority", log.Priority.ToString(CultureInfo.InvariantCulture)); 
35                w.WriteElementString("Timestamp", log.TimeStampString);
36                w.WriteElementString("Message", log.Message);
37                w.WriteElementString("EventId", log.EventId.ToString(CultureInfo.InvariantCulture));
38                w.WriteElementString("Severity", log.Severity.ToString(CultureInfo.InvariantCulture));
39                w.WriteElementString("Title", log.Title);
40                w.WriteElementString("Machine", log.MachineName);
41                w.WriteElementString("AppDomain", log.AppDomainName);
42                w.WriteElementString("ProcessId", log.ProcessId);
43                w.WriteElementString("ProcessName", log.ProcessName);
44                w.WriteElementString("Win32ThreadId", log.Win32ThreadId);
45                w.WriteElementString("ThreadName", log.ManagedThreadName);
46                w.WriteEndElement();
47                w.WriteEndDocument(); 
48                return sw.ToString();
49            }

50        }
 
51    }

52}

53

对于自定义的Formatter我们就介绍到这儿了,它的使用和一般的Formatter没有大的区别,只不过在创建Formatter时我们需要创建一个Custom Formatter,在这里我就不多写了。

 结束语:这篇日志和监测应用程序块的进阶篇文章就到这里了,希望能给初学的朋友一些帮助。后面我会写缓存应用程序块的使用。

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2005-11-08 09:13 TerryLee 阅读(5526) 评论(36)  编辑 收藏 所属分类: Enterprise Library

  回复  引用  查看    
#1楼 2005-11-08 09:33 |       
等很久了,呵呵,谢谢!先看看。。。。
  回复  引用  查看    
#2楼 [楼主]2005-11-08 09:43 | Terrylee      
@杰
不好意思,让大家久等了

最近实在是太忙了

已经一个月没有周末了,呵呵:)
  回复  引用    
#3楼 2005-11-08 09:54 | 过路人 [未注册用户]
支持一下:) 期待你的后继文章
  回复  引用  查看    
#4楼 [楼主]2005-11-08 10:08 | Terrylee      
@过路人
谢谢,谢谢

我会尽快地写后面的文章:)

  回复  引用    
#5楼 2005-11-08 14:34 | osoods [未注册用户]
楼主的精神可嘉啊。。继续期待你下次的文章。。
  回复  引用  查看    
#6楼 [楼主]2005-11-08 14:39 | Terrylee      
@osoods
过奖:)

谢谢你的支持!
  回复  引用  查看    
#7楼 2005-11-08 17:35 | wayfarer      
在发表文章的时候,可以选择团队选项,这样你的文章就可以同时在Design & Pattern团队的主页上显示了。

已经post的文章,也可以通过修改的方式,使其发表在团队主页上。
  回复  引用  查看    
#8楼 [楼主]2005-11-08 21:01 | Terrylee      
@wayfarer

多谢指导!

我一直以为只有与Design&Pattern有关的文章才可以发布在团队的主页:)

我明天修改一下,呵呵!
  回复  引用  查看    
#9楼 2005-11-11 16:52 | wayfarer      
呵呵,你的认为是正确的,不过我们对Design的定义不可太狭隘。微软的Enterprise Library在设计上颇有可取之处,因而发表在我们团队主页上,是完全可以的。
  回复  引用  查看    
#10楼 [楼主]2005-11-12 10:18 | Terrylee      
@wayfarer

谢谢:)
  回复  引用    
#11楼 2005-11-30 14:46 | funidudu [未注册用户]
能相信讲一下怎么用msmq来记录吗?
  回复  引用  查看    
#12楼 [楼主]2005-11-30 16:01 | Terrylee      
@funidudu

我现在没有MSMQ的例子

等有空我写一篇这样的随笔吧^_^
  回复  引用    
#13楼 2005-12-01 14:16 | funidudu [未注册用户]
@Terrylee
多谢了。。
  回复  引用  查看    
#14楼 [楼主]2005-12-01 16:58 | Terrylee      
 
请参考我今天写的这篇随笔
 
 
由于我对MSMQ也没有做过很深的研究
 
有问题请多多包涵:)

  回复  引用  查看    
#15楼 2005-12-06 11:03 | 栖息的熊      
If you have configured the "All Events" special source, the event information will be written to that source as well as the sources associated with the categories specified in the LogEntry object。
这句话怎么理解,主要是the "All Events" special source不太懂什么意思。
  回复  引用  查看    
#16楼 [楼主]2005-12-06 11:22 | Terrylee      
@栖息的熊

我的英文不是很好
 
这句话可能要结合上下文来理解
 
单看这句话看不出什么来

  回复  引用    
#17楼 2006-11-09 18:11 | 钱老庄 [未注册用户]
日志能不能按格式记录在数据库里呢?
  回复  引用  查看    
#18楼 [楼主]2006-11-12 16:59 | TerryLee      
@钱老庄
可以啊,参看我的Enterprise Library 2.0 技巧系列中有一篇专门讲记录到数据库:)
  回复  引用    
#19楼 2007-01-09 12:02 | 无名[匿名] [未注册用户]
使用文件记录日志后可不可以更换文件名呢?比如一天生成一个日志文件?

怎么样操作?谢谢
  回复  引用    
#20楼 2007-01-09 12:09 | 无名[匿名] [未注册用户]
补充个问题:我输出到文件的日志日期怎么都是不正确的?
如:
上午12:06分发的日志,到文件中变成:Timestamp: 2007-1-9 4:06:15
  回复  引用  查看    
#21楼 [楼主]2007-01-15 08:48 | TerryLee      
@无名[匿名]
这个可能需要用程序来控制配置了,参加我写的一篇有关2.0的文章
  回复  引用    
#22楼 2007-03-21 10:12 | 1 [未注册用户]
@无名[匿名]

日志记录的是GMT时间,不是服务器的本地时间。
blogs.msdn.com/tomholl/archive/2006/01/22/516055.aspx
  回复  引用  查看    
#23楼 2007-07-24 17:45 | 老夫子系      
我有一个疑问: 如果日志的文件大了怎么办?
  回复  引用    
#24楼 2007-11-22 13:47 | 过客kevin.w [未注册用户]
找不到不支持的理由!谢谢!
  回复  引用  查看    
#25楼 2007-11-28 13:45 | RyanYu      
学习中,感谢楼主的文章
  回复  引用  查看    
#26楼 2008-07-29 17:43 | 柳生飘絮      
你好博主能够告诉我日志模块中的category sources 和 special sources这两部分有什么区别?这两个是做什么用的?谢谢
  回复  引用  查看    
#27楼 [楼主]2008-07-30 00:59 | TerryLee      
@柳生飘絮
好像也没什么大的区别,有点忘记了这个。。

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-11-08 13:12 编辑过


相关链接: