Enterprise Library2.0研究(二)日志组件的开发说明
2使用日志组件进行开发
2.1添加配置信息
待添加
2.2增加准备的工作
首先,是使用日志组件的准备。
(1) 添加对Microsoft.Practices.EnterpriseLibrary.Logging.dll,
Microsoft.Practices.EnterpriseLibrary.Common.dll
的引用。
(2) 在代码中添加:
using Microsoft.Practices.EnterpriseLibrary.Logging;
(3) 如果要使用extra information helper类和filter类,在代码中添加:
using Microsoft.Practices.EnterpriseLibrary.Logging.ExtraInformation;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
(4) 额外信息提供者收集那些有用但不是必要的上下文信息,因为收集它们需要很大的花费。例如栈迹信息和COM+信息。ExtraInformation提供者将信息加到字典中。你可以选择任何的提供者,并将结果的字典添加到LogEntry的extendedProperties属性中。
(5) 过滤器是可选的。如果你想引用一个制定的过滤器,只需要引入Microsoft.Practices.EnterpriseLibrary.Logging.Filters命名空间。
(6) 如果要使用FormatterDatabaseTraceListener类,则添加
Microsoft.Practices.EnterpriseLibrary.Logging. Database.dll命名空间,并使用数据访问组件。
2.3关键场景
这些场景如下:
l Populating and Rasing Events from Code:这个场景阐述了如何订制需被记录的数据,连同分类和优先级。
l Populating a log message with additional context information:这个场景阐述了如何组装包涵客户信息的字典到log entry中。
l Tracing activities and propagating context information:这个场景阐述如何日志化一个活动的开始和结束,并记录其中的关键活动点。
l Creating custom Trace listeners:这个场景阐述如何创建一个客户TraceListener来发送日志消息到可改变的位置。
l Checking Filter Status Before Constructing log Messages:这个场景阐述了如何避免漏掉没有被配置需记录的日志信息。
从代码中产生事件是日志组件的基本功能。
目标
在这个场景,你需要定制分类和有优先级的数据被日志化,这样能记录事件到合适的trace listener。
解决方案
使用配置管理工具配置使用到的分类和Trace listeners。创建被提交的消息到LogEntry对象。调用Logger的write方法。
Note:Logger类包含了重写的方法使你传递事件而不用创建LogEntry对象。这个场景仅仅演示了Logger类提供的重写方法。
创建LogEntry
LogEntry logEntry = new LogEntry();
logEntry.EventId = 100;
logEntry.Priority = 2;
logEntry.Message = "Informational message";
logEntry.Categories.Add("Trace");
logEntry.Categories.Add("UI Events");
Logger.Write(logEntry);
使用注意点:
如果信息没有被写入配置制定的目的地,信息会被写入“error”侦听者。
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.
如果写日志时,客户订制的日志不存在,那么日志组件会试图创建一个日志。为了正确的创建事件日志,组件必须有合适的特权。特别的,它必须有进入注册表项HKLM\System\CurrentControlSet\Service\EventLog的完全权限。如果没有,事件日志会通过运行有该权限的帐户下的安装程序
开发者需要在日志中添加上下文信息。这种信息不是自动添加的,例子中的信息是堆栈和COM+的信息。
目标
在这个场景中,你可以添加收集的一些关于当前日志的信息。这些信息是有关特定的应用程序的上下文。例如:需要添加安全相关的属性,如当前用户的windows的id和authentication。
解决方案
实现IExtraInformationProvider接口,使用ExtenderProperties属性。
ComPlusInformationProvider
这个类组装了COM+的诊断信息:
· Activity ID
· Application ID
· Transaction ID
· Direct caller account name
· Original caller account name
DebugInformationProvider
这个类组装了当前堆栈的信息。
ManagedSecurityContextInformationProvider
这个类组装了安全相关的诊断信息。
· Authentication type
· Current identity name
· Authentication status
UnmanagedSecurityContextInformationProvider
这个类组装了非托管的安全相关的信息。
组装上下文信息
Hashtable dictionary = new Hashtable();
ManagedSecurityContextInformationProvider informationHelper = new ManagedSecurityContextInformationProvider();
informationHelper.PopulateDictionary(dictionary);
下面的代码显示如何添加用户指定的信息。
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);
下面的代码显示将收集的属性添加到logentry中。
logEntry.ExtendedProperties = dictionary;
在一些情况下,你需要记录某个活动的开始和结束信息,如时间。而且,可以跟踪给活动在某些时间点上的栈迹。通过分类和优先级可以控制写入活动上下文的事件。
目标
解决方案
指定跟踪活动开始和结束时间的分类。创建tracer类的实例。
using (new Tracer("Log Category"))
{
// Perform processing to be timed here
}
注意:上面的代码的结果是一个可以为活动生成唯一id的Tracer对象。你可以使用这个id来关联某个活动的所有log entry。还有一种选择,你可以在代码中为tracer指定id。使用CorrelationManager来保存这个id。
上下文信息的繁殖
与Tracer关联的分类与trace对象的生命周期一样。这意味着每个tracer的分类都被包含在分类的列表中。所以logger.Write会包含所有在列表中的分类。
using (new Tracer("UI Events"))
{
// The following message will be associated with the categories
// "UI Events" and "Debug"
Logger.Write("My message", "Debug");
}
日志组件使得开发者通过一系列的方法的调用跟踪活动的过程。你可以通过实例化嵌套的tracer来创建包含公共活动id的log entry。嵌套的tracer对象会创建含有相同id的log entry。
当跟踪一个活动,你可以在最外面的tracer中指定活动的id。如果不指定id,日志组件会为你创建一个。使用CorrelationManager.ActivityID属性来保存活动的id。
为嵌套Tracer对象创建的LogEntry对象属于为嵌套对象指定的分类,同样也属于父Tracer对象的分类。如下面的代码中。
// The LogEntry created for the Tracer to category "A"
using (new Tracer("A"))
{
// The LogEntry created for this Tracer belongs to both category "A"
// and category "B"
using (new Tracer("B"))
{
}
}
下面代码中的log entry有相同的活动id。并属于三个分类。
using (new Tracer("UI Events"))
{
using (new Tracer("Data Access Events"))
{
LogEntry logEntry = new LogEntry();
logEntry.Categories.Add("Troubleshooting");
Logger.Write(logEntry);
}
}
使用说明
多个tracer对象可以同时存在。然而,他们必须以他们创建的相反的顺序被销毁。
下面的代码是错误的。
Tracer tracer1 = new Tracer();
Tracer tracer2 = new Tracer();
tracer1.dispose(); // Should dispose tracer2 before tracer1
tracer2.dispose();
日志组件让你可以过滤器状态来决定日志消息是否应该按照配置来记录。
目标
如前所述。
解决方案
创建要被提交的消息。调用GetFilter方法。调用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. You application can avoid the performance
// penalty of collecting information for an event that will not be
// logged.
}
有些时候你需要创建自己的sink来满足需求。
解决方案
从CustomTraceListener继承我们的自定义的类,重写TraceData方法,确保它实现了记录日志的行为。使用配置工具来创建一个自定义的traceListener。创建或修改现存的分类来使用这个tracelistener作为目标。