对比log4net,EntLib 的可视化配置以及完善的文档实在是占了挺大的优势,但两者在文件日志方面都存在着相同的问题,就是不能根据Category(log4net里面是logger name)自动分类存放(所有的日志都记在一个日志文件里,当查看日志时会相对比较麻烦),如果想实现分类存放,那就需要在config文件里写上一大堆的配置,作为懒人,这肯定是不能接受的,当然是写的越少越好:P
在code之前先描述下设计思路:
首先说下前提,EntLib 的Logging Application Block支持SpecialSources,它包含三部分AllEvents、LoggingErrorsAndWarnings以及Unprocessed,这里面的Unprocessed对应的就是Unprocessed Category,所有未定义过的Categories都会被分配到此部分,如果Unprocessed没设置TraceListener,那就会由LoggingErrorsAndWarnings来处理这里日志
其次是思路,说白了很简单,就是根据Category动态创建新的RollingFlatFileTraceListener,然后在记录日志时,由Category对应的RollingFlatFileTraceListener来处理相应的日志,如果无法识别的日志,则由默认的RollingFlatFileTraceListener来处理
PS:由于还未实现对应的TraceListenerData,所以暂时还不支持通过配置文件来配置,只能通过编码方式添加,后续会将此部分补上
以下是具体code
using System.IO;
using System.Collections.Concurrent;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Common.Utility;
/// <summary>
/// 根据Category自动分类保存日志
/// </summary>
public class AutoCategoryRollingFlatFileTraceListener : CustomTraceListener
{
private ConcurrentDictionary<string, RollingFlatFileTraceListener> _dic = new ConcurrentDictionary<string, RollingFlatFileTraceListener>();
private RollingFlatFileTraceListener _defaultListener;
private readonly string _directory;
private readonly string _extension;
private readonly string _header;
private readonly string _footer;
private readonly int _rollSizeKB;
private readonly string _timeStampPattern;
private readonly RollFileExistsBehavior _rollFileExistsBehavior;
private readonly RollInterval _rollInterval;
private readonly int _maxArchivedFiles;
/// <summary>
/// Initializes a new instance of the <see cref="RollingFlatFileTraceListener"/> class.
/// </summary>
/// <param name="fileName">The filename where the entries will be logged.</param>
/// <param name="header">The header to add before logging an entry.</param>
/// <param name="footer">The footer to add after logging an entry.</param>
/// <param name="formatter">The formatter.</param>
/// <param name="rollSizeKB">The maxium file size (KB) before rolling.</param>
/// <param name="timeStampPattern">The date format that will be appended to the new roll file.</param>
/// <param name="rollFileExistsBehavior">Expected behavior that will be used when the roll file has to be created.</param>
/// <param name="rollInterval">The time interval that makes the file rolles.</param>
/// <param name="maxArchivedFiles">The maximum number of archived files to keep.</param>
public AutoCategoryRollingFlatFileTraceListener(string fileName,
string header = RollingFlatFileTraceListener.DefaultSeparator,
string footer = RollingFlatFileTraceListener.DefaultSeparator,
ILogFormatter formatter = null,
int rollSizeKB = 0,
string timeStampPattern = "yyyy-MM-dd",
RollFileExistsBehavior rollFileExistsBehavior = RollFileExistsBehavior.Overwrite,
RollInterval rollInterval = RollInterval.None,
int maxArchivedFiles = 0)
{
Guard.ArgumentNotNullOrEmpty(fileName, "fileName");
this._directory = Path.GetDirectoryName(fileName);
this._extension = Path.GetExtension(fileName);
this._header = header;
this._footer = footer;
this._rollSizeKB = rollSizeKB;
this._timeStampPattern = timeStampPattern;
this._rollFileExistsBehavior = rollFileExistsBehavior;
this._rollInterval = rollInterval;
this._maxArchivedFiles = maxArchivedFiles;
this.Formatter = formatter;
this._defaultListener = new RollingFlatFileTraceListener(fileName, this._header, this._footer,
this.Formatter, this._rollSizeKB, this._timeStampPattern,
this._rollFileExistsBehavior, this._rollInterval, this._maxArchivedFiles);
}
public override void Write(string message)
{
this._defaultListener.Write(message);
}
public override void WriteLine(string message)
{
this._defaultListener.WriteLine(message);
}
public override void Flush()
{
this._defaultListener.Flush();
}
/// <summary>
/// Delivers the trace data to the underlying file.
/// </summary>
/// <param name="eventCache">The context information provided by <see cref="System.Diagnostics"/>.</param>
/// <param name="source">The name of the trace source that delivered the trace data.</param>
/// <param name="eventType">The type of event.</param>
/// <param name="id">The id of the event.</param>
/// <param name="data">The data to trace.</param>
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{
if (this.Filter == null || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
{
var listener = this._defaultListener;
if (data is LogEntry)
{
((LogEntry)data).Categories.ForEach((category) =>
{
var tmpListener = this.GetTraceListener(category);
tmpListener.TraceData(eventCache, source, eventType, id, data);
tmpListener.Flush();
});
return;
}
listener.TraceData(eventCache, source, eventType, id, data);
listener.Flush();
}
}
private RollingFlatFileTraceListener GetTraceListener(string category)
{
RollingFlatFileTraceListener listener = this._defaultListener;
if (!string.IsNullOrWhiteSpace(category))
{
category = category.ToLower().Trim();
if (this._dic.ContainsKey(category))
{
return this._dic[category];
}
else
{
try
{
string fileName = Path.Combine(this._directory, category, string.Format("{0}{1}", category, this._extension));
var tmpListener = new RollingFlatFileTraceListener(fileName, this._header, this._footer,
this.Formatter, this._rollSizeKB, this._timeStampPattern,
this._rollFileExistsBehavior, this._rollInterval, this._maxArchivedFiles);
this._dic.TryAdd(category, tmpListener);
listener = tmpListener;
}
catch
{
}
}
}
return listener;
}
}Logger.Writer.Configure(config =>
{
AutoCategoryRollingFlatFileTraceListener acListener = new AutoCategoryRollingFlatFileTraceListener("../applog/auto/auto.log", rollFileExistsBehavior: RollFileExistsBehavior.Increment,
rollInterval: RollInterval.Minute, timeStampPattern: "yyyyMMddHHmm");
config.SpecialSources.Unprocessed.AddAsynchronousTraceListener(acListener);//异步执行
});Logger.Write(string.Format("Get Single Product By ID:{0}", id), "Product");//Product在config中有配置
Logger.Write(string.Format("Get Single Product By ID:{0}", id), "ProductU");//ProductU在config中未配置
Logger.Write(string.Format("Get Single Product By ID:{0}", id), new List<string>() { "ProductX", "ProductXX" });//ProductX、ProductXX在config中未配置
EntLib6 Logging Application Block 通过CustomTraceListener实现自动按Category建立不同的log文件
原文:http://blog.csdn.net/starfd/article/details/43051803