2012-01-30 20 views
20

在基類中聲明一個記錄器並調用LogManager.GetLogger似乎更清晰,這樣每個正在繼承的人都可以使用它。然而,在log4net的網站和其他博客就像this blog post它指出,最好是每類中聲明一個記錄器,因爲:我應該爲每個類或基類聲明log4net記錄器嗎?

您可以使用記錄器這種方式在你的對象隔離日誌關切,我完全推薦你這樣做。這將使您能夠使用log4net的分層配置機制來限制和指導單個記錄器的日誌輸出。

這是否意味着如果我把它放在基類中,它會使記錄器成爲瓶頸?

如果是這樣,還有其他解決方案,還是我只需要創建每個類的記錄器?

回答

0

通常您應該有一個記錄器類,您可以使用單例模式,並確保您的應用程序只有一個記錄器實例。

編輯:使它現在線程安全,感謝您的意見。

public class Logger 
    { 
     private static object syncRoot = new Object(); 
     private static Logger instance=null; 
     // private constructor 
     private Logger() 
     { 
     } 
     /// <summary> 
    /// Gets an instance with default parameters based upon the caller 
    /// </summary> 
    /// <returns></returns> 
    public static Logger GetInstance() 
    { 
     // make sure you return single instance 
     if (instance == null) 
     { 
      lock (syncRoot) 
      { 
      instance=new Logger(); 
      } 
     } 
     return instance; 
    } 
    } 

希望這有助於

+0

OP正在使用log4net。雖然記錄器類是單例模式很有用的罕見情況之一,但爲每類使用不同的記錄器可以極大地增強故障診斷能力:您可以非常詳細地配置分別記錄每個類的消息級別。您還可以將來自不同記錄器的消息輸出到不同的目標(文本文件,事件日誌,電子郵件)。我強烈建議使用這樣的庫。如果記錄器是靜態實例化的(每種類型一次),性能差異可以忽略不計。 (不是我的downvote,但是) – Groo 2012-01-30 22:40:38

+0

你的單例不是線程安全的,所以你最終可能會有不同的Logger實例(在記錄器的情況下可能不是一個大問題,但值得注意)。另外,對於日誌記錄,你可能不希望這種模式的分數慢一些(因爲它必須執行額外的空檢查......可能不是什麼大事,但值得注意)。 – 2012-01-30 22:41:30

+0

不熟悉log4net? – 2012-01-30 22:42:14

1

提供的聲明並未提及到了一個瓶頸。在基類中聲明您的記錄器會限制您對派生類中日誌記錄的控制。如果您的A類和B類來自同一個包含記錄器的基類,則您在類A和類B中所做的所有日誌記錄都將保留相同的日誌記錄設置。

log4net允許您根據類配置記錄器或它們的創建名稱空間,使您能夠對記錄的內容進行非常嚴格的控制。例如,將A級日誌記錄在信息級別,將B級日誌記錄在調試級別。

將一行代碼添加到您希望記錄的每個類中,對於它提供的靈活性來說是一個非常小的負擔。

20

的職位沒有具體告訴你使用一個不同的記錄器在每個派生類,而是一般每類類型不同的記錄。您可以,但不必在每個派生類中使用新的記錄器實例。

查看它的一種方法是,可能會讓兩個獨立的記錄器同時實例化(因爲基本的記錄器仍然存在)可能會令人困惑,特別是如果您使用相同的記錄器名稱隱藏基本記錄器。您的基類方法(未覆蓋)仍將引用基本靜態記錄器,並且覆蓋的方法將使用不同的方法。

此外,文章實例這樣的記錄:

static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

而稍微簡單的辦法可能是使用:

static readonly ILog Log = LogManager.GetLogger(typeof(YourClass)); 

首先,它標誌着readonly,這意味着你贏了」一旦初始化,就能夠意外改變場地。使用該類型的方式與反射相同,但稍快(在編譯時解析)。Visual Studio也將自動更新類名稱,如果您選擇重命名它(它不是你使用字符串重載)。

+0

你也可以使用反射而不是'typeof(YourClass)'。通過反射,您可以複製粘貼樣板代碼,而且您不必面對某人複製粘貼記錄器並忘記更改'typeof(YourClass)'的情況。然後調用看起來像:'LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()。DeclaringType);' – 2015-02-12 11:24:18

3

通常的做法是每個類都有一個記錄器,而不是基類。這樣您可以啓用/禁用每個班級的日誌記錄。

我也可能建議看看使用Common Logging 2.0,http://netcommon.sourceforge.net/

當前正在使用的.NET有多種日誌記錄實現,log4net,企業庫日誌記錄,NLog等,這些都是最流行的。具有不同實現的缺點是它們不共享通用接口,因此對庫的用戶強加特定的日誌記錄實現。

Common.Logging庫引入了一個簡單的抽象,允許您在運行時選擇特定的日誌記錄實現。因此,您可以推遲決定使用什麼特定的日誌庫直到部署。適配器用於將特定的日誌記錄系統插入Common.Logging。

0

我使用基類的一個靜態辭典,鍵連接在類型名稱:

private static readonly Dictionary<string, ILog> _loggers = new Dictionary<string, ILog>(); 

隨着方法(在基類)返回一個記錄器:

private ILog GetLogger(){ 
     var tn = this.GetType().FullName; 
     if (!_loggers.ContainsKey(tn)) { 
      _loggers.Add(tn,LogManager.GetLogger(this.GetType())); 
     } 
     return _loggers[tn]; 
    } 

我在基礎類別上也有測井方法:

public void Log(string msg, params object[] args) { 
     GetLogger().InfoFormat(msg, args); 
    } 

我assu我會這樣允許我爲每種類型配置日誌記錄(儘管我不這樣做),並且GetLogger方法可能暴露給派生類,因此他們可以執行自己的日誌記錄。

+0

看起來你只是向你的基類轉發記錄器已存在的某些行爲。 – 2014-12-04 23:28:26

相關問題