一.改进的地方
1
.Logging Application Block首先带来的是名称上的改变,在1.1下它的全称应该是Logging and Instrumentation Application Block,一般把它翻译为日志和检测应用程序块,而2.0下却完全变成了日志应用程序块。
2
.在1.1下,每个LogEntry只能被记录到一个Sink,而这种情况在2.0下已经不复存在,对于每个LogEntry对象,我们都可以通过Category指定很多的Sink。回忆一下在1.1时记录一个日志项:
下可以添加多次:
LogEntry logEntry
=
new
LogEntry();
logEntry.EventId = 100 ;
logEntry.Priority = 2 ;
logEntry.Message = " Informational message " ;
// 只能设置一个
logEntry.Categorys = " UI Events " ;
Logger.Write(logEntry);
logEntry.EventId = 100 ;
logEntry.Priority = 2 ;
logEntry.Message = " Informational message " ;
// 只能设置一个
logEntry.Categorys = " UI Events " ;
Logger.Write(logEntry);
2.0
.可以在代码中查询哪些日志项将被过滤,例如:
.配置文件的改变。在1.1下关于Logging & Instrumentation Application Block的信息记录在loggingconfiguration.config文件中,2.0下所有的信息都放在了Web.config或App.config中,如:
LogEntry logEntry
=
new
LogEntry();
logEntry.EventId = 100 ;
logEntry.Priority = 2 ;
logEntry.Message = " Informational message " ;
// 设置多个Category
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
Logger.Write(logEntry);
logEntry.EventId = 100 ;
logEntry.Priority = 2 ;
logEntry.Message = " Informational message " ;
// 设置多个Category
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
Logger.Write(logEntry);
3
LogEntry logEntry
=
new
LogEntry();
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
}
else
{
// Event will not be logged.
}
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
}
else
{
// Event will not be logged.
}
4
<
configuration
>
< configSections >
< section name ="loggingConfiguration" type ="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
</ configSections >
< loggingConfiguration tracingEnabled ="true" defaultCategory ="General" >
< logFilters >
< add
name ="Category"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
categoryFilterMode ="AllowAllExceptDenied" >
< categoryFilters >
< add name ="UI Events" />
</ categoryFilters >
</ add >
< add
name ="Priority"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.PriorityFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
minimumPriority ="2"
/>
< add name ="LogEnabled Filter"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
enabled ="true"
/>
</ logFilters >
</ loggingConfiguration >
</ configuration >
< configSections >
< section name ="loggingConfiguration" type ="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
</ configSections >
< loggingConfiguration tracingEnabled ="true" defaultCategory ="General" >
< logFilters >
< add
name ="Category"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
categoryFilterMode ="AllowAllExceptDenied" >
< categoryFilters >
< add name ="UI Events" />
</ categoryFilters >
</ add >
< add
name ="Priority"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.PriorityFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
minimumPriority ="2"
/>
< add name ="LogEnabled Filter"
type ="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"
enabled ="true"
/>
</ logFilters >
</ loggingConfiguration >
</ configuration >
二.记录日志信息
1
.添加相关的引用
.创建一个日志项
using
Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
2
.调用Logger.Write()方法
LogEntry log
=
new
LogEntry();
log.EventId = 300 ;
log.Message = " Sample message " ;
log.Categories.Add( " UI Events " );
log.Severity = TraceEventType.Information;
log.Priority = 5 ;
log.EventId = 300 ;
log.Message = " Sample message " ;
log.Categories.Add( " UI Events " );
log.Severity = TraceEventType.Information;
log.Priority = 5 ;
3
Logger.Write(log);
三.记录日志项的扩展属性
使用基于泛型的Dictionary来记录,如下
//
Create the dictionary to hold the extra information, and populate it
// with managed security information.
Dictionary < string , object > dictionary = new Dictionary < string , object > ();
ManagedSecurityContextInformationProvider informationHelper = new ManagedSecurityContextInformationProvider();
informationHelper.PopulateDictionary(dictionary);
// Add a custom property for screen resolution
int width = Screen.PrimaryScreen.Bounds.Width;
int height = Screen.PrimaryScreen.Bounds.Height;
string resolution = String.Format( " {0}x{1} " , width, height);
dictionary.Add( " Screen resolution " , resolution);
// Write the log entry that contains the extra information
Logger.Write( " Log entry with extra information " , dictionary);
// with managed security information.
Dictionary < string , object > dictionary = new Dictionary < string , object > ();
ManagedSecurityContextInformationProvider informationHelper = new ManagedSecurityContextInformationProvider();
informationHelper.PopulateDictionary(dictionary);
// Add a custom property for screen resolution
int width = Screen.PrimaryScreen.Bounds.Width;
int height = Screen.PrimaryScreen.Bounds.Height;
string resolution = String.Format( " {0}x{1} " , width, height);
dictionary.Add( " Screen resolution " , resolution);
// Write the log entry that contains the extra information
Logger.Write( " Log entry with extra information " , dictionary);
四.跟踪活动并记录上下文信息
1
.调用DoDataAccess方法,完成后释放Trace对象
using
(
new
Tracer(
"
Trace
"
))
{
DoDataAccess();
}
{
DoDataAccess();
}
2
.创建DoDataAccess方法
private
void
DoDataAccess()
{
using (new Tracer("Data Access Events"))
{
// Peform work here
// Assume an error condition was detected - perform some troubleshooting.
DoTroubleShooting();
}
}
{
using (new Tracer("Data Access Events"))
{
// Peform work here
// Assume an error condition was detected - perform some troubleshooting.
DoTroubleShooting();
}
}
3
.创建另一个方法DoTroubleShooting,并在其中创建LogEntry。
private
void
DoTroubleShooting()
{
string logMessage = "Simulated troubleshooting message for Logging QuickStart. " +
"Current activity=/"" + Trace.CorrelationManager.ActivityId + "/"";
LogEntry logEntry = new LogEntry();
logEntry.Categories.Clear();
logEntry.Categories.Add("Troubleshooting");
logEntry.Priority = 5;
logEntry.Severity = TraceEventType.Error;
logEntry.Message = logMessage;
Logger.Write(logEntry);
}
{
string logMessage = "Simulated troubleshooting message for Logging QuickStart. " +
"Current activity=/"" + Trace.CorrelationManager.ActivityId + "/"";
LogEntry logEntry = new LogEntry();
logEntry.Categories.Clear();
logEntry.Categories.Add("Troubleshooting");
logEntry.Priority = 5;
logEntry.Severity = TraceEventType.Error;
logEntry.Message = logMessage;
Logger.Write(logEntry);
}
五.检测日志项是否被记录
创建一个日志项并设置它的信息,调用Logger.ShouldLog()方法
LogEntry logEntry
=
new
LogEntry();
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.GetFilter < CategoryFilter > ().ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
// Perform operations (possibly expensive) to gather additional information
// for the event to be logged.
}
else
{
// Event will not be logged. Your application can avoid the performance
// penalty of collecting information for an event that will not be
// logged.
}
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.GetFilter < CategoryFilter > ().ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
// Perform operations (possibly expensive) to gather additional information
// for the event to be logged.
}
else
{
// Event will not be logged. Your application can avoid the performance
// penalty of collecting information for an event that will not be
// logged.
}
LogEntry logEntry
=
new
LogEntry();
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
}
else
{
// Event will not be logged.
}
logEntry.Priority = 2 ;
logEntry.Categories.Add( " Trace " );
logEntry.Categories.Add( " UI Events " );
if (Logger.ShouldLog(logEntry))
{
// Event will be logged according to currently configured filters.
}
else
{
// Event will not be logged.
}
六.创建自定义的Trace Listener
1
.添加特性ConfigurationElementType,需要继承自CustomTraceListener
[ConfigurationElementType(
typeof
(CustomTraceListenerData))]
public class DebugTraceListener : CustomTraceListener
{
//
}
public class DebugTraceListener : CustomTraceListener
{
//
}
2
.覆写TraceData方法
public
override
void
TraceData(TraceEventCache eventCache,
string
source, TraceEventType eventType,
int
id,
object
data)
{
if (data is LogEntry && this.Formatter != null)
{
this.WriteLine(this.Formatter.Format(data as LogEntry));
}
else
{
this.WriteLine(data.ToString());
}
}
{
if (data is LogEntry && this.Formatter != null)
{
this.WriteLine(this.Formatter.Format(data as LogEntry));
}
else
{
this.WriteLine(data.ToString());
}
}
3
.覆写Write()和WriteLine()方法
/**/
/// <summary>
/// Writes a message to the debug window
/// </summary>
/// <param name="message">The string to write to the debug window</param>
public override void Write( string message)
{
Debug.Write(message);
}
/**/ /// <summary>
/// Writes a message to the debug window
/// </summary>
/// <param name="message">The string to write to the debug window</param>
public override void WriteLine( string message)
{
Debug.WriteLine(message);
}
/// Writes a message to the debug window
/// </summary>
/// <param name="message">The string to write to the debug window</param>
public override void Write( string message)
{
Debug.Write(message);
}
/**/ /// <summary>
/// Writes a message to the debug window
/// </summary>
/// <param name="message">The string to write to the debug window</param>
public override void WriteLine( string message)
{
Debug.WriteLine(message);
}
七.创建自定义的Formatter
1
.在自定义的类上添加特性ConfigurationElementType,并实现接口ILogFormatter
[ConfigurationElementType(
typeof
(CustomFormatterData))]
public class MyFormatter : ILogFormatter
{
//
}
public class MyFormatter : ILogFormatter
{
//
}
2
.构造函数接受一个类型为NameValueCollection的参数
public
MyFormatter (NameValueCollection attributes)
{
//
}
{
//
}
3
.添加Format方法,它接受一个LogEntry的参数
public
string
Format(LogEntry log)
{
//
}
{
//
}
八.使用场景
如果你的应用程序需要挟日志到Event Log, E-mail, Database, Message Queue, Windows Management Instrumentation (WMI), TextFile,你就应该考虑使用日志组件来提供这些功能,特别如果你需要基于分类和优先级来过滤日志消息,需要格式化消息,或者需要不改动代码的情况下改变消息的目的地。日志组件同时被设计成可扩展的,包括方便的创建客户订制的Formatter和TraceListener。
参考资料:Enterprise Libaray –January 2006帮助文档