所以我的问题是关于日志记录,以及如何处理可能影响代码和运行时行为的日志语句。
日志文件......每个程序都应该编写那些用于解决问题的问题但是如何做到正确?
大多数日志语句都非常昂贵,因为它们应该提供有用的信息,并且即使完全禁用日志记录也始终构建它们。
日志记录可以通过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);
}
所以我正在寻找一个
的日志记录解决方案最佳答案的额外日志; - )
已编辑:我正在寻找.NET 2.0中的解决方案
答案 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获取值并用于检查。