ILogger.Log方法declaringType参数

时间:2015-05-29 08:53:39

标签: c# log4net

当我想使用log4net提供的不同日志记录级别时,我发现我需要使用ILogger.Log方法,如下所示:

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

我们可以从我们通常的ILog引用中获取ILogger引用来调用此方法,并且通常建议将此调用包装在扩展方法中。我们得到的是以下内容:

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

我注意到获取声明类型的反射调用看起来多余。当我们检索到ILog引用时,我们已经将声明类型传递给GetLogger。为什么我们需要将另一个类型引用传递给方法Log,我们在ILogger引用上调用它,我们已经从ILog引用中检索了它。更重要的是,扩展方法中的声明类型将是包含扩展方法的类。使用类似Log4NetExtensions的类名记录所有Trace日志是没有意义的。最后,反射应该是昂贵的,即使反映当前方法可能更便宜,每次我们记录时调用反射代码听起来都不对。所以我决定做一个测试:

//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!

因此,似乎忽略了此方法的类型参数。这非常令人费解。任何人都可以确认或否认这些结果吗?有谁知道为什么这样做的方式呢?我打算为此参数创建一个null的扩展方法。你会建议吗?我错过了什么吗?

以下是其答案建议在扩展方法中使用声明类型的问题:

Log4net creating custom levels

Why isn't there a trace level in log4Net?

Log4net, how to log a verbose message?

2 个答案:

答案 0 :(得分:5)

传递给LogManager.GetLogger的类型用于命名返回的记录器,这就是为什么所有记录调用都标记为'Foo.Program'。

传递给Logger.Log的类型虽然是“该方法的声明类型,即该调用的日志系统的堆栈边界”,用于确定停止录制的位置堆栈跟踪 - 内部需要,否则堆栈跟踪将包括log4net内部方法。

您当然可以创建一个将null作为callerStackBoundaryDeclaringType传递的扩展方法,因为它将在内部默认为typeof(Logger)

答案 1 :(得分: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如果你不添加任何内容是没有意义的。

此外,它(通常)在您记录某些内容时设置类型没有意义,但仅限于初始化Logger时类的顶部