【问题标题】:Should a TraceSource be guarded with "if" statements?TraceSource 是否应该使用“if”语句来保护?
【发布时间】:2014-05-03 01:08:47
【问题描述】:

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

(将守卫外跟踪方法会影响对调用中/调用中使用的表达式的评估-当然副作用或计算量大的操作是“坏的”和“不明智的” ,但我仍然希望专注于主要问题。)

【问题讨论】:

    标签: c# trace tracesource traceswitch


    【解决方案1】:

    根据昂贵的跟踪参数计算,我想出了以下内容:

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

    有更好的主意吗?

    【讨论】:

      【解决方案2】:

      我知道在 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。

      【讨论】:

      • '“不”你可能不应该检查。'似乎是 TraceSource 的方式。因此,使用延迟格式化选项并使跟踪参数/用法不改变程序很重要。
      • @Derek 如果更复杂的情况下 TraceEvent 参数的计算成本很高,该怎么办?
      【解决方案3】:

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

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

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

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

      【讨论】:

      • 就我而言,没有副作用或昂贵/额外的字符串构建。感谢您的提示和建议(何时重要)。
      • @MatthewMartin 你能澄清一下最后一段吗?
      【解决方案4】:

      就像@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());
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-02
        • 2021-02-03
        • 2019-11-24
        • 2020-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多