摘要:Logging Application Block可以使开发人员在其应用程序中集成日志监测功能,看看随着2.0的推出给我们带来了哪些改变。<?XML:NAMESPACE PREFIX = O />

一.改进的地方

1Logging Application Block首先带来的是名称上的改变,在1.1下它的全称应该是Logging and Instrumentation Application Block,一般把它翻译为日志和检测应用程序块,而2.0下却完全变成了日志应用程序块。

2.在1.1下,每个LogEntry只能被记录到一个Sink,而这种情况在2.0下已经不复存在,对于每个LogEntry对象,我们都可以通过Category指定很多的Sink。回忆一下在1.1时记录一个日志项:
None.gifLogEntry logEntry = new LogEntry();
None.giflogEntry.EventId 
= 100;
None.giflogEntry.Priority 
= 2;
None.giflogEntry.Message 
= "Informational message";
None.gif
//只能设置一个
None.gif
logEntry.Categorys = "UI Events";
None.gif
None.gifLogger.Write(logEntry);
2.0下可以添加多次:

None.gifLogEntry logEntry = new LogEntry();
None.giflogEntry.EventId 
= 100;
None.giflogEntry.Priority 
= 2;
None.giflogEntry.Message 
= "Informational message";
None.gif
//设置多个Category
None.gif
logEntry.Categories.Add("Trace");        
None.giflogEntry.Categories.Add(
"UI Events");
None.gif
None.gifLogger.Write(logEntry);

3.可以在代码中查询哪些日志项将被过滤,例如:
None.gifLogEntry logEntry = new LogEntry();
None.giflogEntry.Priority 
= 2;
None.giflogEntry.Categories.Add(
"Trace");
None.giflogEntry.Categories.Add(
"UI Events");
None.gif
None.gif
if (Logger.ShouldLog(logEntry))
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will be logged according to currently configured filters.
ExpandedBlockEnd.gif
}

None.gif
else
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will not be logged. 
ExpandedBlockEnd.gif
}

4.配置文件的改变。在1.1下关于Logging & Instrumentation  Application Block的信息记录在loggingconfiguration.config文件中,2.0下所有的信息都放在了Web.configApp.config中,如:

None.gif<configuration>
None.gif    
<configSections>
None.gif        
<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
None.gif    
</configSections>
None.gif    
<loggingConfiguration tracingEnabled="true" defaultCategory="General">
None.gif        
<logFilters>
None.gif            
<add
None.gif                
name="Category"
None.gif                type
="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
None.gif                categoryFilterMode
="AllowAllExceptDenied">
None.gif        
<categoryFilters>
None.gif          
<add name="UI Events" />
None.gif        
</categoryFilters>
None.gif            
</add>
None.gif            
<add
None.gif                
name="Priority"
None.gif                type
="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.PriorityFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
None.gif                minimumPriority
="2"
None.gif                    
/>
None.gif      
<add name="LogEnabled Filter"
None.gif        type
="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
None.gif        enabled
="true" 
None.gif           
/>
None.gif    
</logFilters>
None.gif
</loggingConfiguration>
None.gif
</configuration>
二.记录日志信息

1.添加相关的引用

None.gifusing Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
None.gif
using Microsoft.Practices.EnterpriseLibrary.Logging;
None.gif
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
None.gif
using Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
None.gif
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;

2.创建一个日志项

None.gifLogEntry log = new LogEntry();
None.giflog.EventId 
= 300;
None.giflog.Message 
= "Sample message";
None.giflog.Categories.Add(
"UI Events");
None.giflog.Severity 
= TraceEventType.Information;
None.giflog.Priority 
= 5;

3.调用Logger.Write()方法
None.gifLogger.Write(log);

三.记录日志项的扩展属性

使用基于泛型的Dictionary来记录,如下

None.gif// Create the dictionary to hold the extra information, and populate it
None.gif
// with managed security information.  
None.gif
Dictionary<stringobject> dictionary = new Dictionary<stringobject>();
None.gifManagedSecurityContextInformationProvider informationHelper 
= new ManagedSecurityContextInformationProvider();
None.gif
None.gifinformationHelper.PopulateDictionary(dictionary);
None.gif
None.gif
// Add a custom property for screen resolution
None.gif
int width = Screen.PrimaryScreen.Bounds.Width;
None.gif
int height = Screen.PrimaryScreen.Bounds.Height;
None.gif
string resolution = String.Format("{0}x{1}", width, height);
None.gif
None.gifdictionary.Add(
"Screen resolution", resolution);
None.gif
None.gif
// Write the log entry that contains the extra information
None.gif
Logger.Write("Log entry with extra information", dictionary);
 
四.跟踪活动并记录上下文信息

1.调用DoDataAccess方法,完成后释放Trace对象

None.gifusing (new Tracer("Trace"))
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    DoDataAccess();
ExpandedBlockEnd.gif}
 
2.创建DoDataAccess方法

None.gifprivate void DoDataAccess()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
using (new Tracer("Data Access Events"))
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
// Peform work here
InBlock.gif
InBlock.gif        
// Assume an error condition was detected - perform some troubleshooting.
InBlock.gif
        DoTroubleShooting();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
 
3.创建另一个方法DoTroubleShooting,并在其中创建LogEntry
None.gifprivate void DoTroubleShooting()
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
string logMessage = "Simulated troubleshooting message for Logging QuickStart. " +
InBlock.gif      
"Current activity=\"" + Trace.CorrelationManager.ActivityId + "\"";
InBlock.gif
InBlock.gif    LogEntry logEntry 
= new LogEntry();
InBlock.gif
InBlock.gif    logEntry.Categories.Clear();
InBlock.gif    logEntry.Categories.Add(
"Troubleshooting");
InBlock.gif    logEntry.Priority 
= 5;
InBlock.gif    logEntry.Severity 
= TraceEventType.Error;
InBlock.gif    logEntry.Message 
= logMessage;
InBlock.gif
InBlock.gif    Logger.Write(logEntry);
ExpandedBlockEnd.gif}

 

五.检测日志项是否被记录

创建一个日志项并设置它的信息,调用Logger.ShouldLog()方法

None.gifLogEntry logEntry = new LogEntry();
None.giflogEntry.Priority 
= 2;
None.giflogEntry.Categories.Add(
"Trace");
None.giflogEntry.Categories.Add(
"UI Events");
None.gif
None.gif
if (Logger.GetFilter<CategoryFilter>().ShouldLog(logEntry))
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will be logged according to currently configured filters.
InBlock.gif  
// Perform operations (possibly expensive) to gather additional information 
InBlock.gif  
// for the event to be logged. 
ExpandedBlockEnd.gif
}

None.gif
else
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will not be logged. Your application can avoid the performance
InBlock.gif  
// penalty of collecting information for an event that will not be
InBlock.gif  
// logged.
ExpandedBlockEnd.gif
}
 

None.gifLogEntry logEntry = new LogEntry();
None.giflogEntry.Priority 
= 2;
None.giflogEntry.Categories.Add(
"Trace");
None.giflogEntry.Categories.Add(
"UI Events");
None.gif
None.gif
if (Logger.ShouldLog(logEntry))
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will be logged according to currently configured filters.
ExpandedBlockEnd.gif
}
None.gif
else
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif  
// Event will not be logged. 
ExpandedBlockEnd.gif
}
 
六.创建自定义的Trace Listener

1.添加特性ConfigurationElementType,需要继承自CustomTraceListener

None.gif[ConfigurationElementType(typeof(CustomTraceListenerData))]
None.gif
public class DebugTraceListener : CustomTraceListener
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
//
ExpandedBlockEnd.gif
}
 
2.覆写TraceData方法

None.gifpublic override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
if (data is LogEntry && this.Formatter != null
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.WriteLine(this.Formatter.Format(data as LogEntry));
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
this.WriteLine(data.ToString());
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
 
3.覆写Write()WriteLine()方法

ExpandedBlockStart.gifContractedBlock.gif/**//// <summary>
InBlock.gif
/// Writes a message to the debug window 
InBlock.gif
/// </summary>
ExpandedBlockEnd.gif
/// <param name="message">The string to write to the debug window</param>

None.gifpublic override void Write(string message)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    Debug.Write(message);
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
/**//// <summary>
InBlock.gif
/// Writes a message to the debug window 
InBlock.gif
/// </summary>
ExpandedBlockEnd.gif
/// <param name="message">The string to write to the debug window</param>

None.gifpublic override void WriteLine(string message)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    Debug.WriteLine(message);
ExpandedBlockEnd.gif}
 
七.创建自定义的Formatter

1.在自定义的类上添加特性ConfigurationElementType,并实现接口ILogFormatter

None.gif[ConfigurationElementType(typeof(CustomFormatterData))]
None.gif
public class MyFormatter : ILogFormatter
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
//
ExpandedBlockEnd.gif
}
 
2.构造函数接受一个类型为NameValueCollection的参数

None.gifpublic MyFormatter (NameValueCollection attributes)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
//
ExpandedBlockEnd.gif
}
 
3.添加Format方法,它接受一个LogEntry的参数

None.gifpublic string Format(LogEntry log)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
//
ExpandedBlockEnd.gif
}

 

八.使用场景

如果你的应用程序需要挟日志到Event Log, E-mail, Database, Message Queue, Windows Management Instrumentation (WMI), TextFile,你就应该考虑使用日志组件来提供这些功能,特别如果你需要基于分类和优先级来过滤日志消息,需要格式化消息,或者需要不改动代码的情况下改变消息的目的地。日志组件同时被设计成可扩展的,包括方便的创建客户订制的FormatterTraceListener

 
参考资料:Enterprise Libaray –January 2006帮助文档