動態修改log4net的輸出設置: HttpResponse

在進行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)

發佈了143 篇原創文章 · 獲贊 0 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章