2012-01-30 14 views
20

Sembra più pulito dichiarare un logger e chiamare LogManager.GetLogger in una classe base in modo che chiunque possa ereditarlo possa usarlo. Tuttavia, sul sito log4net e altri blog come in this blog post si afferma che è meglio dichiarare un logger per classe perché:Devo dichiarare logger log4net una volta per classe o in classe base?

È possibile utilizzare logger questo modo per isolare le preoccupazioni di registrazione attraverso gli oggetti, ed io tutto Consiglieresti fare così. Ciò consentirà di limitare e indirizzare l'output dei registri dai singoli logger utilizzando il meccanismo di configurazione gerarchica di log4net.

Questo significa che se lo metto in classe base, questo renderà il logger un collo di bottiglia?

Se sì, ci sono altre soluzioni o devo solo creare un logger per classe?

risposta

0

Di solito dovresti avere una sola classe di logger, potresti usare il modello singleton e assicurarti di avere una sola istanza di logger per la tua applicazione.

Modifica: reso sicuro thread ora, grazie per i commenti.

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; 
    } 
    } 

Spero che questo aiuti

+0

OP utilizza log4net. Sebbene una classe di logger sia una delle rare occasioni in cui è utile il pattern Singleton, l'utilizzo di un logger per classe migliora enormemente la risoluzione dei problemi: è possibile configurare, in modo molto dettagliato, il livello di messaggi da registrare separatamente per ogni classe. È inoltre possibile inviare messaggi da diversi logger a destinazioni diverse (file di testo, registro eventi, e-mail). Consiglio vivamente di utilizzare una libreria del genere. Se un logger viene istanziato staticamente (una volta per tipo), la differenza di prestazioni è trascurabile. (non il mio downvote, comunque) – Groo

+0

Il tuo singleton non è thread-safe in modo che tu possa finire con diverse istanze di Logger (nel caso di un logger probabilmente non è un grosso problema, ma vale la pena notare). Inoltre, per il logging probabilmente non vorrai questo pattern come il suo più lento (dato che deve fare un extra check nullo ... di nuovo probabilmente non è un grosso problema, ma vale la pena notare). –

+0

Non hai familiarità con log4net? –

1

la dichiarazione di cui non si riferisce ad un collo di bottiglia. Dichiarare il proprio logger in una classe base limita il controllo che si ha sulla registrazione nelle classi derivate. Se le classi A e B derivano dalla stessa classe base contenente il logger, si sono bloccate con le stesse impostazioni di registrazione per tutte le registrazioni eseguite nelle classi A e B.

log4net consente di configurare i logger in base alla classe o lo spazio dei nomi per cui sono stati creati, dandoti un controllo molto stretto su ciò che viene registrato. Ad esempio, avere un registro di classe A a livello di informazioni e un registro di classe B a livello di debug.

Aggiungere una singola riga di codice a ogni classe in cui si desidera registrare le informazioni è un onere molto limitato per la flessibilità che fornisce.

20

Il post non è specificamente dicendo di utilizzare un registratore diverso in ogni derivano classe, ma invece un registratore diverso per ogni tipo di classe in generale. È possibile, ma non è necessario utilizzare una nuova istanza del logger in ogni classe derivata.

Un modo per guardarlo è che potrebbe essere fonte di confusione avere due logger separati istanziati contemporaneamente (perché quello di base continuerà a esistere), specialmente se si nasconde quello di base usando lo stesso nome di logger. I tuoi metodi di classe base (non sovrascritti) faranno comunque riferimento al logger statico di base, e quelli sovrascritti ne useranno uno diverso.

Inoltre, l'articolo un'istanza del logger in questo modo:

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

mentre un modo un po 'più semplice potrebbe essere quella di utilizzare:

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

Prima di tutto, è segnato readonly, il che significa che hai vinto' essere in grado di cambiare accidentalmente il campo, una volta inizializzato. E l'uso del tipo funzionerà allo stesso modo del riflesso, ma leggermente più veloce (risolto in fase di compilazione).Visual Studio aggiornerà automaticamente anche il nome della classe se si sceglie di rinominarlo (che non sarebbe stato l'overload della stringa).

+0

Puoi anche usare il riflesso invece di 'typeof (YourClass)'. Con la riflessione, è possibile copiare e incollare il codice boilerplate e non è necessario affrontare una situazione in cui qualcuno ha copiato il logger e ha dimenticato di cambiare 'typeof (YourClass)'. La chiamata sarebbe quindi: 'LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod(). DeclaringType);' –

3

È prassi comune disporre di un logger per classe, NON di una classe base. In questo modo è possibile abilitare/disabilitare la registrazione su una base per classe.

Potrei anche suggerire di utilizzare Common logging 2.0, http://netcommon.sourceforge.net/.

Esistono numerose implementazioni di registrazione per .NET attualmente in uso, log4net, Enterprise Library Logging, NLog, per nominare i più popolari. Lo svantaggio di avere un'implementazione differente è che non condividono un'interfaccia comune e quindi impongono una particolare implementazione di registrazione agli utenti della tua libreria.

Common.Logging library introduce una semplice astrazione per consentire di selezionare un'implementazione di registrazione specifica in fase di esecuzione. Pertanto è possibile rinviare la decisione su quale libreria di registrazione particolare utilizzare fino alla distribuzione. Gli adattatori vengono utilizzati per collegare un particolare sistema di registrazione a Common.Logging.

0

Utilizzo un dizionario statica nella classe base, calettato nome del tipo:

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

Con un metodo (sulla classe di base) per restituire un logger:

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

I hanno anche i metodi di registrazione sulla classe base:

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

I assu me questo mi permetterebbe di configurare il logging per tipo (anche se non lo faccio) e il metodo GetLogger potrebbe essere esposto a classi derivate in modo che possano fare il proprio logging.

+0

Sembra che tu stia semplicemente inoltrando alla tua classe base determinati comportamenti del registratore che già esistono. –

Problemi correlati