故事是同事在某個有參照 log4net 的古蹟 ASP.NET 網站專案想用 log4net 寫 Log,從其他可正常使用 log4net 網站 web.config 複製了 RollingFileAppender 設定,卻怎麼也無法產生 Log,設定檔看了又看,權限查了再查,沒有就是沒有。

我不愛 log4net,嫌它又老又囉嗦( XML 設定又臭又長)(延伸閱讀:高負載 .NET Logging 議題與 NLog 極端效能調校),除非維護舊專案,都是用 NLog。但既然負責修古蹟,就要能處理這堆老東西。

最後查出問題是這個 Web Site 小專案雖有參照 log4net.dll,但並未真的使用,因此缺少一個重要步驟:在 Global.asax void Application_Start(object sender, EventArgs e) 呼叫 log4net.Config.XmlConfigurator.Configure(); (若是 Web Apllication Porject 可改在 AssemblyInfo.cs 宣告 [assembly: log4net.Config.XmlConfigurator(Watch = true)]),少了這一步,不會出現任何錯誤,log4net 會對 web.config 裡的 log4net/appender 視而不見。

說來是個低級錯誤,但如果不熟 log4net,沒在全新專案用過,又把 NLog 自己找設定的行為視為理所當然,就可能漏掉這步。

這次射茶包的過程我學到兩則 log4net 設定除錯技巧,未來也許不會再用到,但還是寫下來吧。

  1. 要檢查 log4net 初始化及載入設定的 Log,可在 web.config 加入以下設定:

    <appSettings>
        <add key="log4net.Internal.Debug" value="true"/>
    </appSettings>
    <system.diagnostics>
        <trace autoflush="true">
            <listeners>
                <add name="textWriter" type="System.Diagnostics.TextWriterTraceListener" initializeData="D:\Logs\debug\log4net.txt"/>
            </listeners>
        </trace>
    </system.diagnostics>    
    

    配合 <log debug="true"> 可採收蠻詳細的 Log:

  2. 想知道目前使用的 Appender、實際 Log 檔路徑,以及設定檔讀取過程的 Log,可以寫支小程式:

    <%@Page Language="C#"%>
    <%@Import Namespace="log4net"%>
    <%@Import Namespace="System.Linq"%>
    
    <script runat="server">
    	static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Page));
    	void Page_Load(object sender, EventArgs e)
    	{
    		Response.ContentType = "text/plain";
    		var loggers = LogManager.GetCurrentLoggers();
    		Response.Write("# GetCurrentLoggers.Count = " + loggers.Length);
    		foreach (var logger in loggers)
    		{
    			Response.Write("\n  * Logger.Name = " + logger.Logger.Name);
    			foreach (var appender in logger.Logger.Repository.GetAppenders())
    			{
    				Response.Write("\n    - Appender.Name = " + appender.Name);
    				var fileAppender = appender as log4net.Appender.FileAppender;
    				if (appender != null)
    				{
    					Response.Write("\n      - File: " + fileAppender.File);
    				}
    			}
    		}
    		Response.Write("\n ConfigurationMessages:");
    		foreach (var msg in log4net.LogManager.GetRepository().ConfigurationMessages.Cast<log4net.Util.LogLog>())
    			Response.Write("\n " + msg);
    		Response.End();
    	}
    </script>
    

    This post explains troubleshooting log4net configuration issues in an old ASP.NET project. The key problem was missing the log4net.Config.XmlConfigurator.Configure() call in Application_Start. Useful debugging techniques include enabling internal debug logs in web.config and writing a small program to list active appenders and log paths.


Comments

Be the first to post a comment

Post a comment