3

在跟踪到 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 模型似乎不需要/使用/提及这些方法。

(在 trace 方法之外设置守卫会影响对调用中/用于调用的表达式的评估 - 当然,副作用或计算成本高昂的操作是“糟糕的”和“不明智的”,但我仍然希望专注于主要问题。)

4

4 回答 4

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

有更好的主意吗?

于 2014-05-19T00:32:48.487 回答
1

您提供给消息参数的字符串是否昂贵?常量或文字非常便宜。如果是这种情况,请不要担心,使用跟踪开关/跟踪侦听器过滤器等来减少跟踪处理的数量(以及跟踪的性能成本)(顺便说一句,默认的跟踪侦听器非常昂贵,总是在添加所需的跟踪侦听器之前清除跟踪侦听器)

System.Diagnostics 没有任何东西可以使不活动的 TraceSource 调用无成本。即使您使用侦听器过滤器,或将跟踪开关设置为零(将其关闭),也会调用 TraceEvent 并构造消息字符串。

假设跟踪字符串的计算成本很高,例如,它遍历数据集中的所有行并将它们转储到字符串中。这可能需要不小的毫秒数。

为了解决这个问题,您可以将字符串构建部分包装在具有条件属性的函数中以在发布模式下将其关闭,或者使用采用 lambda 表达式或创建字符串的 Func 的包装器方法(并且不执行不需要时)

于 2014-05-03T17:09:01.347 回答
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。

于 2014-05-03T02:24:37.883 回答
0

就像@nexuzzz 建议的那样,可能存在计算事件参数的成本很高的情况。这是我能想到的。

对开发人员的建议是:“如果您没有现成的字符串参数,请使用 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());
        }
    }
}
于 2014-11-12T02:15:47.863 回答