在進行web開發時,有時候需要動態調試系統的處理流程,更有甚者需要把這個跟蹤直接輸出到http response中,這樣可以直接調試而不是在執行完畢後再去查看log4net的跟蹤日誌。能不能讓log4net直接把日誌寫到用戶的web請求中呢?答案是肯定的,那就是自己創建一個 TextWriter。 log4net是 支持動態修改和配置的。(原文鏈接 http://ddbiz.com/?p=114)
看如下代碼:
public static void RedirectLogger2Response()
{
Hierarchy hierarchy = LogManager.GetRepository() as Hierarchy;
ResponseAppender responseAppender = null;
foreach (log4net.Appender.IAppender adr in hierarchy.GetAppenders())
{
if (adr is ResponseAppender)
{
responseAppender = (ResponseAppender)adr;
break;
}
}
if (responseAppender == null)
{
responseAppender = new ResponseAppender();
responseAppender.ActivateOptions();
log4net.Config.BasicConfigurator.Configure(responseAppender);
hierarchy.Root.AddAppender(responseAppender);
hierarchy.Root.Level = log4net.Core.Level.All;
hierarchy.Configured = true;
hierarchy.RaiseConfigurationChanged(EventArgs.Empty);
}
else
{
responseAppender.InitAppender();
}
Logger = LogManager.GetLogger("OnlineResponse");
}
RedirectLogger2Response 就是把當前的Logger 重定向到Http的Response中,關鍵在於使用自己定義的一個 Appender : ResponseAppender,ResponseAppender的定義很簡單,如下:
internal sealed class ResponseAppender : log4net.Appender.TextWriterAppender
{
public ResponseAppender():base()
{
base.Name = "OnlineResponseAppender";
base.Layout =
new log4net.Layout.PatternLayout()
{
ConversionPattern = "%message%newline"
};
base.ImmediateFlush = true;
base.AddFilter(new log4net.Filter.LoggerMatchFilter() { LoggerToMatch = "OnlineResponse", AcceptOnMatch=true });
base.AddFilter(new log4net.Filter.DenyAllFilter() { });
InitAppender();
}
public void InitAppender()
{
base.Writer = new System.IO.StreamWriter(System.Web.HttpContext.Current.Response.OutputStream);
}
}
每次需要使用ResponseAppender時,把 HttpContext的Current Response的輸出流綁定到 Writer上,就是這麼簡單。
因爲每次web請求時,處理的線程會不同,response使用的是不同的response,所以有必要每個請求都重新綁定一個輸出流:
public void InitAppender()
{
base.Writer = new System.IO.StreamWriter(System.Web.HttpContext.Current.Response.OutputStream);
}
處理過程中,唯一需要注意的是,動態綁定的Logger,是附加在 root上的,hierarchy.Root.AddAppender(responseAppender); 就定義了使輸出能夠在 Root級的設置中發生作用。如果log4net.xml.cfg 的配置中對 Root 的輸出做了限定,如 <<priority value="OFF" />,那麼還要打開這個設置爲你需要的輸出級別:
hierarchy.Root.Level = log4net.Core.Level.All;
然後從新激活 log4net的配置即可。當然這樣有可能會看到一些不需要的輸出,或者不是本線程的輸出,那麼我們還需要在 ResponseAppender中增加一個過濾裝置,僅僅出書我們需要調試的內容:
base.AddFilter(new log4net.Filter.LoggerMatchFilter() { LoggerToMatch = "OnlineResponse", AcceptOnMatch=true });
base.AddFilter(new log4net.Filter.DenyAllFilter() { });
值得提醒的一點是,這種修改方式是單線程的,只對一個用戶的請求有效(static 方法),所以它是 非線程安全的。好在我們僅僅是需要調試,而不是讓多個用戶來使用。(原文鏈接 http://ddbiz.com/?p=114)