在跟踪TraceSource之前,应该跟踪"跟踪级别"在发布跟踪之前要检查吗?
var ts = new TraceSource("foo");
ts.Switch.Level = SourceLevels.Warning;
if (/* should there be a guard here? and if so, what? */) {
ts.TraceEvent(TraceEventType.Warning, 0, "bar");
}
虽然有SourceSwitch.ShouldTrace(TraceEventType)
,但文档显示
应用程序代码不调用此方法;它只能由TraceSource类中的方法调用。
似乎pre-TraceSource模型使用TraceSwitch(不是SourceSwitch)类,它有各种TraceXYZ
方法(为此目的?),但似乎不需要/使用/提及TraceSource模型。
(保护外部跟踪方法会影响对呼叫中使用的表达式的评估 - 当然,副作用或计算成本高昂的操作会导致这种情况发生。"坏"以及"不明智的",但我仍然喜欢关注主要问题。)
答案 0 :(得分:2)
根据昂贵的跟踪参数计算,我想出了以下内容:
internal sealed class LazyToString
{
private readonly Func<object> valueGetter;
public LazyToString(Func<object> valueGetter)
{
this.valueGetter = valueGetter;
}
public override string ToString()
{
return this.valueGetter().ToString();
}
}
用法是
traceSource.TraceEvent(TraceEventType.Verbose, 0, "output: {0}", new LazyToString(() =>
{
// code here would be executed only when needed by TraceSource
// so it can contain some expensive computations
return "1";
}));
有更好的主意吗?
答案 1 :(得分:1)
我知道在NLog中你通常只需要处理你想要的任何级别的跟踪,它将负责是否应该跟踪日志级别。
对我而言,TraceSource的工作原理相同。
所以我会说“不”你可能不应该检查。
通过设置不同的跟踪级别并在不同级别跟踪消息并查看跟踪内容来测试它。
我认为,就性能而言,如果您使用类中定义的方法,通常就可以了:
基于以下示例:http://msdn.microsoft.com/en-us/library/sdzz33s6.aspx
这很好:
ts.TraceEvent(TraceEventType.Verbose, 3, "File {0} not found.", "test");
这很糟糕:
string potentialErrorMessageToDisplay = string.Format( "File {0} not found.", "test" );
ts.TraceEvent(TraceEventType.Verbose, 3, potentialErrorMessageToDisplay );
在第一种情况下,如果不记录错误级别,库可能会避免调用string.Format。在第二种情况下,始终调用string.Format。
答案 2 :(得分:1)
您提供给消息参数的字符串是否昂贵?常量或字面值非常便宜。如果是这种情况,请不要担心,使用跟踪开关/跟踪侦听器过滤器等来减少处理的跟踪数量(以及跟踪的执行成本)(BTW,默认跟踪监听器非常昂贵) ,在添加所需的跟踪之前,始终清除跟踪侦听器
System.Diagnostics没有任何东西可以使非活动的TraceSource调用无成本。即使您使用侦听器过滤器,或将跟踪开关设置为零(将其关闭),也将调用TraceEvent并构造消息字符串。
想象一下,跟踪字符串的计算成本很高,例如,它遍历数据集中的所有行并将它们转储到字符串中。这可能需要一个非常微不足道的毫秒数。
为了解决这个问题,您可以将字符串构建部分包含在具有条件属性的函数中,以便在发布模式下将其关闭,或者使用包含lambda表达式的包装器方法或创建字符串的Func(并且isn& #39; t在不需要时执行)
答案 3 :(得分:0)
像@nexuzzz建议的那样,可能会出现事件参数计算成本高昂的情况。这是我能想到的。
对开发人员的建议是:&#34;如果您没有现成的字符串参数,请使用lambda版本的TraceInformation或TraceWarning。
public class TraceSourceLogger : ILogger
{
private TraceSource _traceSource;
public TraceSourceLogger(object that)
{
_traceSource = new TraceSource(that.GetType().Namespace);
}
public void TraceInformation(string message)
{
_traceSource.TraceInformation(message);
}
public void TraceWarning(string message)
{
_traceSource.TraceEvent(TraceEventType.Warning, 1, message);
}
public void TraceError(Exception ex)
{
_traceSource.TraceEvent(TraceEventType.Error, 2, ex.Message);
_traceSource.TraceData(TraceEventType.Error, 2, ex);
}
public void TraceInformation(Func<string> messageProvider)
{
if (_traceSource.Switch.ShouldTrace(TraceEventType.Information))
{
TraceInformation(messageProvider());
}
}
public void TraceWarning(Func<string> messageProvider)
{
if (_traceSource.Switch.ShouldTrace(TraceEventType.Warning))
{
TraceWarning(messageProvider());
}
}
}