记录完成正确

obe*_*eak 8 c# logging log4net c#-2.0

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

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

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

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

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

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

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

public void SomeMethod(){
    logger.Debug(someObject.GetHeavyDescriptionFromLazyTree());
}
Run Code Online (Sandbox Code Playgroud)

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

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

public void SomeMethod(){
    if(logger.DoLogDebug())
        logger.Debug(someObject.GetHeavyDescriptionFromLazyTree());
}
Run Code Online (Sandbox Code Playgroud)

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

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

[Conditional("DEBUG")]  
public void Debug(string debugMessage) 
{ 
    Console.WriteLine(debugMessage); 
} 
Run Code Online (Sandbox Code Playgroud)

所以我正在寻找一种日志解决方案

  • 使用调试语句不会过度破坏我的源代码
  • 在运行时而不是在编译时决定日志记录级别的位置
  • 只有在必要时才解决语句(logLevel> definedLogLevel)

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

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

Dan*_*ant 6

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

logger.Debug(() => someObject.GetHeavyDescriptionFromLazyTree());
Run Code Online (Sandbox Code Playgroud)

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

  • @oberfreak:如果您只希望.NET 2.0作为目标环境,但是为您的开发使用.NET 3.5编译器(VS 2008或2010),那么这也可以.当然,使用VS 2003,这将无法正常工作. (3认同)