2011-12-01 71 views
7

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

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

大多数日志语句是非常昂贵的,因为它们应该提供有用的信息,并且它们总是被建立,即使日志记录被禁用totaly。

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

例如,下面的代码总是加载一个巨大的延迟加载的树,在正常执行过程中永远不会被加载totaly。

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

好吧,我知道...,但是这仅仅是对所有存在于复杂的记录方法的替代这绝不正常释放执行)期间执行的大多数程序

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

所以我在寻找一个记录解决方案

  • 不会过度地通过调试语句来破坏我的源代码
  • 其中日志级别是在运行时而不是在编译时确定的
  • 其中的语句仅解决,如果neccessary(LOGLEVEL> definedLogLevel)

最佳答案;-)

编辑额外loglines:我正在寻找在.NET 2.0

回答

5
的解决方案

一种方法“懒惰测井”是使用式(创建函数代表一个返回消息),而不是使用直接评价:

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

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

+0

感谢您的解决方案,这听起来不错,但我forgott,它必须与.NET 2.0解决:-( – oberfreak

+0

@oberfreak,在这种情况下,我认为标准的'如果'检查是你最好的选择;希望你 –

+0

为什么这个问题不适用于.NET 2.0?我一直以VS.NET 2010和.NET 2.0作为目标平台来做这件事 –

0

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

+3

我想你几乎完全错过了这个问题的观点。 –

+0

我认为这将会走以及他的选择两个DoLogDebug()检查,除了该方法不需要太多的逻辑。毕竟比从web.config或app.config获取appsettings值更简单。 –

+0

“EnableLogging”甚至不是log4net配置密钥。当log4net已经拥有自己的启用配置功能时,为什么你会这样做? – Amy

4

大多数日志语句是非常昂贵的,因为它们应该提供有用的信息,并且它们总是被建立,即使日志记录被禁用totaly。

不完全正确。请参阅:

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

如果你希望能够通过日志记录级别,并通过类来定制你的日志输出,或甚至整个命名空间,这是必经之路走。

+1

根据Log4Net的FAQ,这确实是推荐的“最快”方式:http://logging.apache.org/log4net/release/faq.html#perf-not-logging –

+0

感谢您的回答,但我很抱歉。我不想在我的businesslogic中使用日志记录代码,因此可以轻松地进行扩展/交换。如果决定发生在BL中,那么每当你(例如)想要引入一个新的日志记录级别时,就会有一千多条线路进行检查。所以我认为我将来不够灵活。 (软件将会有一个10年-15年的ALS,所以它应该是可扩展和可维护的) – oberfreak

+0

@oberfreak,这个决定将严格来自log4net配置,在你的代码中没有任何地方。从另一个程序使用的库将使用该程序配置,而不是它们自己的。 – Amy