2015-05-29 4 views
6

Когда я хотел использовать различные уровни ведения журнала, доступные с log4net, я узнал, что мне нужно использовать метод ILogger.Log, который выглядит следующим образом:метод ILogger.Log DeclaringType параметр

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

Мы можем получите ссылку ILogger из нашей обычной ссылки ILOG, чтобы вызвать этот метод, и обычно рекомендуется обернуть этот вызов в методе расширения. Мы получаем следующее:

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

Я заметил, как вызов отражения для получения типа объявления выглядит излишним. Мы уже передали тип объявления GetLogger, когда мы получили ссылку на ILOG. Зачем нам нужно передать другую ссылку на метод Log, который мы вызываем по ссылке ILogger, которую мы получили из нашей ссылки ILOG. Что еще более важно, тип объявления в методе расширения будет классом, который содержит метод расширения. Ведение журнала всех журналов Trace с таким именем класса, как Log4NetExtensions, не имеет смысла. Наконец, отражение должно быть дорогостоящим, хотя отражение в текущем методе может быть дешевле, призывая код отражения каждый раз, когда мы регистрируемся, не звучит правильно. Поэтому я решил сделать тест:

//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); 

И результирующие журналы выглядели следующим образом:

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! 

Таким образом, кажется, что параметр типа к этому методу, игнорируется. Это очень озадачивает. Может ли кто-нибудь подтвердить или опровергнуть эти результаты? Кто-нибудь знает, почему это работает так, как оно есть? Я намерен создать мой метод расширения с нулевым значением для этого параметра. Вы предложили бы то же самое? Я что-то упускаю?

Ниже приведены вопросы, ответы на которые предлагают использовать объявляющий тип в методе расширения:

Log4net creating custom levels

Why isn't there a trace level in log4Net?

Log4net, how to log a verbose message?

ответ

4

типа вы передаете LogManager.GetLogger используется для именования возвращенного регистратор , поэтому все ваши вызовы регистрации помечены как «Foo.Program».

тип передается Logger.Log, хотя это «Заявляющая тип метода, который является границей стека в систему регистрации для этого вызова» и используется, чтобы определить, где, чтобы остановить запись трассировки стека - которая требуется внутренне , иначе трассировка стека будет включать внутренние методы log4net.

Вы можете, конечно, создать метод расширения, который принимает значение null как callerStackBoundaryDeclaringType, так как он будет внутренне по умолчанию typeof(Logger).

+0

это: «поскольку он будет внутренне по умолчанию для типа регистратора». Это то, что я искал. Любые ссылки? Или любое предложение о том, как тестировать? Когда log4net создает трассировку стека? Когда я перехожу в исключение? Но разве исключения не имеют собственных следов стека? –

+0

Вы правы в отношении исключений, имеющих собственную трассировку стека: log4net также [позволяет трассировку стека быть включенным в шаблон] (http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout. html), но в ретроспективе это не обычный случай использования - в отношении ссылки я посмотрел в источнике [строки 428 и 725] (https://apache.googlesource.com/log4net/+/refs/heads/1.2.12 /src/Repository/Hierarchy/Logger.cs) – stuartd

0

Вы не должны создать метод расширения, как вы предложили.

Поскольку ILog Logger является статическим, не имеет смысла использовать его в качестве значения параметра. Просто используйте Log4Net следующим образом:

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 
} 

, если вы используете только стандартные функции, просто называют DebugFormat() (или что-то другое) непосредственно:

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

Это не имеет смысла, чтобы создать свой собственный " Trace "-Method, если вы ничего не добавили к нему.

Кроме того, он (обычно) не имеет смысла, чтобы установить тип, когда вы что-то войти, но только на верхней части класса, когда initializig Logger

+0

Метод расширения будет использоваться несколькими классами, каждый из которых будет иметь свои собственные ссылки ILog, объявленные обычным способом, который вы также предложили. Кроме того, я хочу регистрировать сообщения с помощью Level.Trace, который не имеет стандартного метода, предоставляемого ILog. –

Смежные вопросы