65.9K
CodeProject 正在变化。 阅读更多。
Home

ActivityTracerScope - 使用 SvcTraceViewer.exe 和 System.Diagnostics 轻松进行活动追踪

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.44/5 (14投票s)

2011 年 4 月 22 日

CPOL

3分钟阅读

viewsIcon

52410

downloadIcon

482

一种获得有效活动追踪的简便方法,利用内置的 System.Diagnostics 和标准工具 SvcTraceViewer.exe(不仅适用于 WCF)。

摘要

在本文中,我将介绍并解释一种有效的追踪“活动”的方法。 我还将展示如何使用 MS 提供的标准 SvcTraceViewer 工具以友好的方式可视化标准的 System.Diagnostics 日志。

引言

几周前,在学习 WCF 认证 (70-531) 时,我意识到用于读取 WCF 消息日志和活动追踪的工具也可以用于普通日志。 该工具(SvcTraceViewer.exe,.NET SDK 的一部分)具有一些非常有用的可视化功能:它会根据类型(信息、警告、错误等)突出显示跟踪。而且,它可以以非常花哨的方式显示“活动”,比使用“baretail”打开的普通 .txt 日志文件好得多。

所以我深入研究了 System.Diagnostics,我发现了一些有趣的工具,可以用来将代码片段分组到逻辑“活动”中,以便更容易维护它们。

我最终得到了三个想法

  1. 找到一种方法,使您可以使用 Trace.StartTrace.Stop 创建的“活动范围”在代码中更加可见。
  2. 使跟踪与 SvcTraceViewer 兼容,以便利用该强大的工具。
  3. 跟踪包含在活动范围内的任何未处理的异常,而无需到处使用 try-catch(第二部分)。

背景

我经常发现代码完全被日志弄得乱七八糟,产生了凌乱的文本文件,我必须使用 baretail 阅读。 其他时候,根本没有日志。 本文是关于快速而干净的日志,利用标准的 System.Diagnostics 库和 SvcTraceViewer.exe。 此外,我提出了一种使用 ActivityTracerScope 类使日志中的“活动”范围更加可见的方法。 当尝试运行提供的示例然后打开生成的日志文件时,好处会立即显现。

开发

在 .NET 中构建范围基础设施的最简单方法是使用“using”关键字 :)

为了做到这一点,你的类必须实现 IDisposable 接口和 Dispose 方法。 所以我们的类将利用 System.Diagnostics 活动关联和 IDisposable 接口

namespace MyNameSpace
{
    using System;
    using System.Diagnostics;
    
    public class ActivityTracerScope : IDisposable
    {
        private readonly Guid oldActivityId;
        private readonly Guid newActivityId;
        private readonly TraceSource ts;
        private readonly string activityName;
        
        public ActivityTracerScope(TraceSource ts, string activityName)
        {
            this.ts = ts;
            this.oldActivityId = Trace.CorrelationManager.ActivityId;
            this.activityName = activityName;

            this.newActivityId = Guid.NewGuid();
            
            if (this.oldActivityId != Guid.Empty)
            {
                ts.TraceTransfer(0, "Transferring to new activity...", newActivityId);
            }
            Trace.CorrelationManager.ActivityId = newActivityId;
            ts.TraceEvent(TraceEventType.Start, 0, activityName);
        }
        public void Dispose()
        {
            if (this.oldActivityId != Guid.Empty)
            {
                ts.TraceTransfer(0, "Transferring back to old activity...", oldActivityId);
            }
            ts.TraceEvent(TraceEventType.Stop, 0, activityName);
            Trace.CorrelationManager.ActivityId = oldActivityId;
        }
    }
}

然后,在代码中使用我们的类,我们将能够跟踪活动并在我们的代码中清楚地看到它们……

namespace MyNameSpace
{
    class Program
    {
        static void Main(string[] args)
        {
            var ts = new TraceSource("SampleUsageTraceSource");
            using (new ActivityTracerScope(ts, "Sample Main Activity"))
            {
                ts.TraceEvent(TraceEventType.Information, 0, "my information event");
                using (new ActivityTracerScope(ts, "Sample Subactivity 1"))
                {
                    ts.TraceEvent(TraceEventType.Information, 0, 
                                  "another information event 1");
                } 
                using (new ActivityTracerScope(ts, "Sample Subactivity 2"))
                {
                    ts.TraceEvent(TraceEventType.Information, 0, 
                                  "another information event 2"); 
                    ts.TraceEvent(TraceEventType.Information, 0, 
                                  "another information event 3"); 
                    using (new ActivityTracerScope(ts, "Nested Activity"))
                    {
                        ts.TraceEvent(TraceEventType.Information, 0, 
                                      "another information event 4");
                    }
                } 
                using (new ActivityTracerScope(ts, "Sample Subactivity 3"))
                {
                    ts.TraceEvent(TraceEventType.Warning, 0, 
                                  "WARNING! WARNING, WILL ROBINSON!"); 
                    using (new ActivityTracerScope(ts, "More Nested Activity"))
                    {
                        ts.TraceEvent(TraceEventType.Warning, 0, "Nested information");
                    }
                } 
                using (new ActivityTracerScope(ts, "Sample Subactivity 3"))
                {
                    ts.TraceEvent(TraceEventType.Information, 0, 
                                  "another information event 5");
                }
            }
        }
    }
}

……并且,提供一个跟踪源,以及 app.config 中的适当配置(注意日志文件夹中的权限)……

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="SampleUsageTraceSource" switchValue="Information, ActivityTracing">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="DefaultServer" />
          <add name="xmlServer" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add initializeData="C:\logs\SampleUsage.TraceActivityManagerUsage.svclog"
           type="System.Diagnostics.XmlWriterTraceListener"
           name="xmlServer" traceOutputOptions="Callstack" />
    </sharedListeners> 
    <trace autoflush="true" />
  </system.diagnostics>
</configuration>

……我们将能够使用 SvcTraceViewer.exe。 它位于 C:\Program Files\Microsoft SDKs\Windows\[Framework Version]\Bin。 如果你找不到它,可能你必须下载 .NET Framework SDK。

所以现在,在运行了那个 Main 方法之后,我们可以打开我们的 c:\logs\SampleUsage.TraceActivityManagerUsage.svclog。 在那里我们可以看到我们的活动,以及所有相关的数据。

尝试玩一下它。 我认为最有趣的部分是图形可视化。 如果你点击它,你会看到一个代表你记录的活动的树

结论

通过一些简单的代码管道,很容易释放 SDK 提供的标准通用工具的力量。 有时你只需要将东西放在一起,而不是将你的代码与第三方库耦合。

© . All rights reserved.