记录完成正确

时间:2011-12-01 20:30:45

标签: c# logging log4net c#-2.0

所以我的问题是关于日志记录,以及如何处理可能影响代码和运行时行为的日志语句。

日志文件......每个程序都应该编写那些用于解决问题的问题但是如何做到正确?

大多数日志语句都非常昂贵,因为它们应该提供有用的信息,并且即使完全禁用日志记录也始终构建它们。

日志记录可以通过xmls,inCode或某些设置等进行配置,但这并不能解决字符串构建问题。

例如,以下代码总是加载一个巨大的延迟加载树,在正常执行期间永远不会加载它。

仅为此日志记录语句创建整个树以显示在日志文件

好的,我知道......,但这只是大多数程序中存在的所有复杂日志记录方法的替代,这些方法在正常发布执行期间永远不应该执行

public void SomeMethod(){
    logger.Debug(someObject.GetHeavyDescriptionFromLazyTree());
}

即使关闭了日志记录,也始终会调用方法someObject.GetHeavyDescriptionFromLazyTree(),因此这个问题有一些常见的解决方案,如:

public void SomeMethod(){
#if DEBUG
    logger.Debug(someObject.GetHeavyDescriptionFromLazyTree());
#endif       
}

public void SomeMethod(){
    if(logger.DoLogDebug())
        logger.Debug(someObject.GetHeavyDescriptionFromLazyTree());
}

我认为很明显#if DEBUG编译器标志不是生产代码的解决方案。 如果我使用logger.DoLogDebug(),将会有过多的代码来检查日志是否已启用...所以这也不是解决方案。

我认为ConditionalAttribute可以提供帮助,但它也绑定到编译器标志,并且它不会停用对GetHeavyDescriptionFromLazyTree的调用

[Conditional("DEBUG")]  
public void Debug(string debugMessage) 
{ 
    Console.WriteLine(debugMessage); 
} 

所以我正在寻找一个

的日志记录解决方案
  • 并没有过多地使用调试语句来破坏我的源代码
  • 其中日志记录级别是在运行时而不是在编译时决定的
  • 只有在必要时才会解析语句(logLevel> definedLogLevel)

最佳答案的额外日志; - )

已编辑:我正在寻找.NET 2.0中的解决方案

3 个答案:

答案 0 :(得分:6)

“延迟日志记录”的一种方法是使用表达式(创建返回消息的函数委托)而不是使用直接评估:

logger.Debug(() => someObject.GetHeavyDescriptionFromLazyTree());

这有其自身的缺点(代表的构造),但它可能比昂贵的方法便宜。通常,您会将此作为重载提供,并且仅在您知道评估表达式的情况下才使用它。

答案 1 :(得分:4)

  

大多数日志语句都非常昂贵,因为它们应该提供有用的信息,并且即使完全禁用日志记录也始终构建它们。

不完全正确。见这里:

if (Log.IsDebugEnabled)
{
    StackFrame f = new StackFrame(2);
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name);
}

如果根本未启用调试日志记录,则不会构建您的消息。这满足了您的所有三个条件,并且是相当标准的做法。

编辑:我应该补充一点IsDebugEnabled考虑是否全局启用调试日志记录此特定记录器的任何覆盖配置。它非常具体,在运行时确定,但在配置更改之前也会进行缓存。

Edit2:

  

如果我使用logger.DoLogDebug(),将会有过多的代码来检查日志是否已启用...所以这也不是解决方案。

我在上面概述的if语句并不过分,并且评估得非常快。我建议你试验一下,如果性能足够的话,自己评估一下。如果您发现这些if遍布,则标准建议是尽可能合并它们。

这里的一个关键想法是log4net具有五个日志记录级别,每个级别都可以完全独立于其他级别。因此,您可能在一个地方IsDebugEnabled,在另一个地方IsInfoEnabled。你不会很容易通过条件编译得到这个,这甚至会使更多麻烦。在我编写的代码中,这种情况实际上很常见:

if (Log.IsDebugEnabled)
{
    StackFrame f = new StackFrame(2);
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name);
}
if (Log.IsInfoEnabled)
{
    StackFrame f = new StackFrame(2);
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name);
}
if (Log.IsErrorEnabled)
{
    StackFrame f = new StackFrame(2);
    Log.Debug("Very expensive message to put together and stuff." + f.GetMethod().Name);
}

如果您希望能够通过记录级别和类别,甚至整个名称空间来定制日志输出,那么这就是您的选择。

答案 2 :(得分:0)

您可以通过web.config或app.config对其进行配置。添加名为EnableLogging (<add key="EnableLogging" value="false"/>)的项目。然后创建一个静态方法,从.config获取值并用于检查。