2015-05-29 23 views
6

Quando ho voluto utilizzare i diversi livelli di registrazione disponibili con log4net, ho scoperto che avevo bisogno di usare il metodo ILogger.Log, che assomiglia a questo:metodo ILogger.Log parametro DeclaringType

void Log(Type callerStackBoundaryDeclaringType, Level level, object message, Exception exception); 

Possiamo ottenere un riferimento di ILogger dal nostro consueto riferimento ILog per chiamare questo metodo e in genere viene suggerito di racchiudere questa chiamata in un metodo di estensione. Quello che otteniamo è il seguente:

//typical log4net ILog reference 
private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

//suggested extension method 
public static void Trace(this ILog logger, object message, Exception e) 
{ 
    logger.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, log4net.Core.Level.Trace, message, e); 
} 

Ho notato come la chiamata di riflessione per ottenere il tipo di dichiarazione sembra ridondante. Abbiamo già passato il tipo di dichiarazione a GetLogger quando abbiamo recuperato il nostro riferimento ILog. Perché abbiamo dovuto passare un altro riferimento di tipo al metodo Log, che stiamo invocando su un riferimento di ILogger che abbiamo recuperato dal nostro riferimento ILog. Ancora più importante, il tipo di dichiarazione nel metodo di estensione sarebbe la classe che contiene il metodo di estensione. La registrazione di tutti i registri di traccia con un nome di classe come Log4NetExtensions non avrebbe alcun senso. Infine, la riflessione dovrebbe essere costosa, anche se riflettere sul metodo attuale potrebbe essere più economico, chiamando il codice di riflessione ogni volta che il log non sembra corretto. Così ho deciso di fare una prova:

//I just created a logger 
var logger = logManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 

//and then I called Log with different type parameters 
logger.Logger.Log(MethodBase.GetCurrentMethod().DeclaringType, log4net.Core.Level.Info, "hello!", null); 
logger.Logger.Log(logger.GetType(), log4net.Core.Level.Info, "hello!", null); 
logger.Logger.Log(null, log4net.Core.Level.Info, "hello!", null); 
logger.Logger.Log(typeof(System.Console), log4net.Core.Level.Info, "hello!", null); 

E i log risultanti sembrava il seguente:

INFO 2015-05-29 11:06:57,200 [9] Foo.Program - hello! 
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello! 
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello! 
INFO 2015-05-29 11:06:57,207 [9] Foo.Program - hello! 

Così, sembra che il parametro di tipo a questo metodo viene ignorato. Questo è molto sconcertante. Qualcuno può confermare o negare questi risultati? Qualcuno sa perché questo funziona come fa? Intendo creare il mio metodo di estensione con null per questo parametro. Suggeriresti la stessa cosa? Mi sto perdendo qualcosa?

Di seguito sono domande le cui risposte suggerirei di usare il tipo di dichiarazione nel metodo di estensione:

Log4net creating custom levels

Why isn't there a trace level in log4Net?

Log4net, how to log a verbose message?

risposta

4

Il tipo si passa a LogManager.GetLogger viene utilizzato per assegnare un nome al logger restituita , motivo per cui tutte le chiamate di registrazione sono contrassegnate come "Foo.Program".

Il tipo passata a Logger.Log se è "Il tipo dichiara del metodo che è il confine pila nel sistema di registrazione per questa chiamata" e viene utilizzato per determinare dove interrompere la registrazione dello stack - che è richiesto internamente oppure la traccia dello stack includerebbe i metodi interni di log4net.

È possibile creare un metodo di estensione che superi il valore null come callerStackBoundaryDeclaringType, poiché verrà impostato automaticamente su typeof(Logger).

+0

questo: "come sarà internamente predefinito per il tipo di logger." Questo è quello che stavo cercando. Eventuali riferimenti? O qualche suggerimento su come testare? Quando log4net produce una traccia stack? Quando passo in un'eccezione? Ma le eccezioni non hanno le loro tracce di stack? –

+0

Hai ragione riguardo alle eccezioni che hanno una propria traccia dello stack: anche log4net [consente di includere la traccia dello stack nel pattern] (http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout. html) ma in retrospettiva che non è un caso d'uso comune - per quanto riguarda il riferimento, ho cercato nella fonte, [linee 428 e 725] (https://apache.googlesource.com/log4net/+/refs/heads/1.2.12 /src/Repository/Hierarchy/Logger.cs) – stuartd

0

Non si dovrebbe creare un metodo di estensione come da te suggerito.

Poiché ILog Logger è statico, non ha molto senso utilizzarlo come valore di parametro. Basta usare Log4Net seguente modo:

private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // that part was ok 

public static void Trace(object message, Exception e) 
{ 
    Logger.DebugFormat(message, e); // Use InfoFormat or something else if needed 
} 

se si utilizza la funzionalità appena normale, basta chiamare DebugFormat() (o qualcos'altro) direttamente:

try { 
    int i=7/0; 
} catch (Exception e){ 
    Logger.ErrorFormat("Looks like you are not Jon Skeet",e); 
} 

Non ha senso per creare il proprio " Trace "-Method se non aggiungi nulla.

Inoltre esso (di solito) non ha senso impostare il tipo quando si accede qualcosa, ma solo sulla parte superiore della classe quando initializig Logger

+0

Il metodo di estensione verrà utilizzato da più classi, ognuna delle quali avrà i propri riferimenti ILog dichiarati nel solito modo suggerito. Inoltre, desidero registrare i messaggi con Level.Trace, che non ha un metodo standard fornito da ILog. –