阅读本文之前,请先阅读:Enterprise Library 2.0 -- Logging Application Block (上)
上一篇中我们介绍了如何去配置Logging Application Block,本文将主要介绍Logging Application Block 的基本操作以及Formatter和Trace Listeners 的自定义方法,首先我们来看如何将一个事件日志写入到一个文本文件中。
假设我们按照上一篇的操作配置了Logging Application Block,那么配置文件中的信息如下:
<
loggingConfiguration
name
="Logging Application Block"
tracingEnabled
="true"
defaultCategory
="General"
logWarningsWhenNoCategoriesMatch
="true"
>
<
listeners
>
<
add
fileName
="trace.log"
header
="----------------------------------------"
footer
="----------------------------------------"
formatter
="SHY520 Formatter"
listenerDataType
="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData,
![None.gif](/Images/OutliningIndicators/None.gif)
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
traceOutputOptions
="None"
type
="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener,
![None.gif](/Images/OutliningIndicators/None.gif)
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name
="SHY520 Listeners"
/>
<
add
source
="Enterprise Library Logging"
formatter
="Text Formatter"
log
="Application"
machineName
=""
listenerDataType
="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData,
![None.gif](/Images/OutliningIndicators/None.gif)
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
traceOutputOptions
="None"
type
="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener,
![None.gif](/Images/OutliningIndicators/None.gif)
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name
="Formatted EventLog TraceListener"
/>
</
listeners
>
<
formatters
>
<
add
template
="Timestamp: {timestamp} Message: {message} Category: {category} Priority: {priority} EventId:
![None.gif](/Images/OutliningIndicators/None.gif)
{eventid} Severity: {severity} Title:{title} Machine: {machine} Application Domain: {appDomain} Process Id:
![None.gif](/Images/OutliningIndicators/None.gif)
{processId} Process Name: {processName} Win32 Thread Id: {win32ThreadId} Thread Name: {threadName} Extended Properties:
![None.gif](/Images/OutliningIndicators/None.gif)
{dictionary({key} - {value} )}"
type
="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0,
![None.gif](/Images/OutliningIndicators/None.gif)
Culture=neutral, PublicKeyToken=null"
name
="Text Formatter"
/>
<
add
template
="Timestamp: {timestamp} Message: {message} Category: {category} Priority: {priority} EventId:
![None.gif](/Images/OutliningIndicators/None.gif)
{eventid} Severity: {severity} Title:{title} Machine: {machine} Application Domain: {appDomain} Process Id:
![None.gif](/Images/OutliningIndicators/None.gif)
{processId} Process Name: {processName} Win32 Thread Id: {win32ThreadId} Thread Name: {threadName} Extended Properties:
![None.gif](/Images/OutliningIndicators/None.gif)
{dictionary({key} - {value} )}"
type
="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0,
![None.gif](/Images/OutliningIndicators/None.gif)
Culture=neutral, PublicKeyToken=null"
name
="SHY520 Formatter"
/>
</
formatters
>
<
logFilters
>
<
add
categoryFilterMode
="AllowAllExceptDenied"
type
="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter,
![None.gif](/Images/OutliningIndicators/None.gif)
Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
name
="Category Filter"
/>
</
logFilters
>
<
categorySources
>
<
add
switchValue
="All"
name
="General"
>
<
listeners
>
<
add
name
="SHY520 Listeners"
/>
</
listeners
>
</
add
>
</
categorySources
>
<
specialSources
>
<
allEvents
switchValue
="All"
name
="All Events"
/>
<
notProcessed
switchValue
="All"
name
="Unprocessed Category"
/>
<
errors
switchValue
="All"
name
="Logging Errors & Warnings"
>
<
listeners
>
<
add
name
="Formatted EventLog TraceListener"
/>
</
listeners
>
</
errors
>
</
specialSources
>
</
loggingConfiguration
>
下面我们来看如何将日志写入到文本文件:
[TestMethod]
public
void
DoLog()
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
//创建一个日志条目
LogEntry log = new LogEntry();
//指定该日志所属类别
log.Categories.Add("General");
//日志标题
log.Title = "SHY520's Tests";
log.Message = "there is log information";
//优先级
log.Priority = 0;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
Logger.Write(log);
}
上面的代码中,我们为该日志指定所属类别为General,在配置文件中我们可以看到General这个类别使用的Trace Listener是SHY520 Listeners,SHY520 Listeners是一个Flat File Trace Listener,它指定了我们的日志信息输出的地方(trace.log),我用的测试项目,运行测试后,该文件在TestResult/out目录中,如果是一般的Web项目或Consle项目,该文件则在Bin/Debug目录下,下面我们来看一下输出的日志信息:
![671.gif](https://i-blog.csdnimg.cn/blog_migrate/ebc23ccdf986021c450c193b71a69bf5.gif)
上图中,我们可以看到我们在程序中记录的一些日志信息,我们还可以记录一些额外的信息,这些信息是键值对应的,在1.0版本中我们用Hashtable,这里我们用的是一个泛型的Dictionary类型,代码如下:
[TestMethod]
public
void
LoggEntry()
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
LogEntry log = new LogEntry();
//事件ID
log.EventId = 2000;
//日志优先级
log.Priority = 2;
log.Message = "Test LogEntry 2";
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//日志类别
ICollection<string> coll = new List<string>();
coll.Add("General");
log.Categories = coll;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//添加额外信息
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("name", "SHY520");
dic.Add("sex","男");
dic.Add("age", "22");
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
log.ExtendedProperties = dic;
//写入日志
Logger.Write(log);
}
然后运行测试,在TestResult/Out目录下的trace.log文件中就能看到我们在程序中添加的额外信息了。
![672.gif](https://i-blog.csdnimg.cn/blog_migrate/d2559e94e1cc3eb366d8d7edd8421d87.gif)
下面我们来介绍一下过滤器的用法:
实现方法很简单,这里我们假设我们已经按照上一篇文章中的方法配置好了一个Category Filter,在Category Filter中我们可以设置要过滤掉哪种类别的事件日志,具体实现方式有两种,如下:
方法一:
[TestMethod]
public
void
TestFilter1()
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
LogEntry logEntry = new LogEntry();
logEntry.Priority = 2;
logEntry.Categories.Add("General");
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//ShouldLog()方法根据Filter配置返回是否需要记录日志
if (Logger.GetFilter<CategoryFilter>().ShouldLog(logEntry.Categories))
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//TODO:记录日志
Logger.Write(logEntry);
}
}
方法二:
[TestMethod]
public
void
TestFilter2()
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
LogEntry logEntry = new LogEntry();
logEntry.Priority = 2;
logEntry.Categories.Add("General");
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
if (Logger.ShouldLog(logEntry))
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Logger.Write(logEntry);
}
}
关于事件日志的过滤就说到这里,下面我们来看看如何创建一个自定义的Trace Listener,首先我们新建一个类(MyListener),并且继承与CustomTraceListener,同时不要忘了在为这个新建的类加上[ConfigurationElementType(typeof(CustomTraceListenerData))]的Attribute,最后重写基类的三个方法,在每个方法中加入自己需要的逻辑既可。完整的类的代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using
Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using
Microsoft.Practices.EnterpriseLibrary.Logging;
using
Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
Enterprise_Library_2
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
[ConfigurationElementType(typeof(CustomTraceListenerData))]
public class MyListener : CustomTraceListener
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id,
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
object data)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (data is LogEntry && this.Formatter != null)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.WriteLine(this.Formatter.Format(data as LogEntry));
}
else
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.WriteLine(data.ToString());
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public override void Write(string message)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//TODO:添加自己所需的逻辑
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public override void WriteLine(string message)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//TODO:添加自己所需的逻辑
}
}
}
然后我们在配置Trace Listener的时候选择Custom Trace Listener就可以了。
接下来我们来看看如何自定义Formatter,实现的方法和上面类似,首先新建一个类MyFormatter,继承ILogFormatter接口,同时加上[ConfigurationElementType(typeof(CustomFormatterData))]的Attribute,完整的代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Collections.Specialized;
using
Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using
Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using
Microsoft.Practices.EnterpriseLibrary.Logging;
using
Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
Enterprise_Library_2
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
[ConfigurationElementType(typeof(CustomFormatterData))]
public class MyFormatter : ILogFormatter
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public MyFormatter(NameValueCollection nv)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//注意:构造函数的参数必须是NameValueCollection类型的
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public string Format(LogEntry log)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string result = string.Empty;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//TODO:此处添加我们个性化的Formatter逻辑
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
return result;
}
}
}
到这里,关于Logging Application Block的有关问题已经都简单的介绍了一下,有遗漏错误的地方,请指正,谢谢!
希望对初学者有所帮助,同时也欢迎Enterprise Library学习者一起共同交流经验。
Email : pwei013@163.com