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?
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? –
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