在 .NET 应用程序的发布版本中实现跟踪功能的考量






3.61/5 (11投票s)
2002年10月20日
9分钟阅读

114780
在 .NET 应用程序的发布版本中,即当应用程序交付给客户或在生产环境中运行时,生成跟踪输出的最佳技术是什么?本文讨论了标准 .NET 跟踪功能的优缺点,并提出了一些替代方案。
引言
本文是为 挪威 .NET 用户组 的一次演示而编写的。
我曾在之前的 关于自定义 .NET 跟踪监听器的文章 中介绍了各种自定义 .NET 应用程序跟踪输出生成的方法。最初我计划更新那篇文章以包含更高级的自定义功能,但由于几个原因我改变了主意:
- 内置的 .NET 跟踪功能存在严重的局限性,这些局限性阻碍了 .NET
Trace
类成为生产环境跟踪的最佳选择;由于这些局限性,开发人员应该只在一定程度上自定义标准的Trace
类——超出这个程度,他们就应该考虑其他选项; - 自从我写了那篇文章以来,网上已经发布了新的自定义跟踪监听器示例,包括一个基于 SQL 的跟踪监听器(在 15seconds.com 上的文章《.NET 中的跟踪和实现你自己的跟踪监听器》中有所解释),因此我决定使用超链接功能,而不是自己重写相同的内容;
- 微软最近宣布了 他们对未来 .NET 开发的计划,下一版本的 VS.NET(代号为“Everett”)将包含企业仪器框架,该框架将提供当前 .NET 标准跟踪功能所缺乏的功能。
因此,我决定不编写新的花哨的跟踪监听器,而是调查以下问题:
- 是否应该在 .NET 应用程序的发布版本中编译
TRACE
选项? - 内置的 .NET 跟踪功能是否为生产环境中的跟踪输出生成提供了良好的选择?
- .NET
Trace
类有哪些替代方案?
发布版本:是否跟踪
这当然是一个选择问题,尽管微软已经展示了自己的偏好:新生成的托管 C++ 项目的发布版本未定义 TRACE
符号,但 C# 项目的发布版本定义了 TRACE
。这看起来令人困惑,但我认为这是合理的:为应用程序的最终版本提供一个跟踪后门很有用,而且只要没有在配置文件中指定活动的监听器,就不会产生跟踪输出。另一方面,C++ 语言的传统没有默认的跟踪功能,所以 C++ 开发者会接受他们应该记住在发布版本中显式定义 TRACE
符号。
但对此事有不同意见。Richard Grimes 在他的书《使用 Visual Studio.NET 开发应用程序》中批评了在发布版本中启用跟踪的想法。他列出了四点论证:
- 跟踪消息总是生成(即使未收集),因此会影响性能;
- 生成跟踪消息的代码占用了二进制文件空间;
- 如果客户使用了你自己编写的跟踪监听器的版本,并且该版本写得很糟糕,那么你的应用程序将受到它与之无关的代码的影响;
- 在发布版本中留下跟踪消息意味着你没有完全测试你的代码;你的应用程序应该只在报告给 Windows 事件日志的“异常”情况下出现问题。
我必须说,我只同意第一点:如果你的应用程序详细记录其活动,它将始终影响性能。另一方面,这必须是一个有意识的选择:可以用在循环中的低级例程可能应该限制其在调试版本中的输出,但如果你需要在生产环境中从应用程序获取活动报告,你将不得不承担性能成本。
我不认为跟踪消息会大大增加你的二进制文件大小,以至于你应该仅仅为此原因考虑删除它们。现代技术趋势不太关心磁盘空间消耗。看看 .NET 的 XCOPY 部署!你的应用程序 CD 会有多少空间被跟踪消息占用?只有一小部分。
关于可能影响应用程序执行的自定义跟踪监听器的论点需要你注意:是的,添加跟踪功能为你的应用程序增加了一个新的维度,并对跟踪消费者提出了一定的要求。但这在你将程序交付给客户时需要考虑的一个普遍问题:硬件、操作系统服务包、设备驱动程序——有很多参数你无法控制但必须考虑。同样,我认为你不应该仅仅因为这个原因禁用应用程序跟踪。
最后,我最强烈反对的论点是:在发布版本中留下跟踪消息表明你没有完全测试你的代码。这种说法将我们带回了独立应用程序在独立机器上运行的世界,即如果程序失败,它必须是该程序的责任。现代计算机程序聚合了如此多的外部功能,以至于在发生故障时,通常无法指向单个模块——系统管理员必须收集足够的信息来“跟踪”导致错误的步骤序列。
所以我的个人选择是为应用程序的发布版本增强跟踪功能,无论是通过在编译时定义 TRACE
符号,还是使用自定义报告功能。采取一些预防措施来限制跟踪输出的大小(我在上一篇文章中展示了一种方法),但让用户可以选择生成程序活动报告。
发布版本:.NET Trace
类是正确的选择吗?
既然我已经说服你,你应该在发布版本中启用跟踪或某种替代方案(或者至少我自己又一次说服了自己),让我们看看现有的 .NET Trace
类是否可以作为生产环境中跟踪的基础。与任何 .NET 类一样,你可以覆盖默认的跟踪功能(通过实现自定义监听器,而不是通过继承已封锁的 Trace
类)。但是,标准的 .NET Trace
有两个主要的 त्यामुळे设计限制,可能会迫使你寻找替代方案。我在上一篇文章中描述了它们,但让我在此总结一下:
Trace
和TraceListener
的方法无法定义消息严重性级别——你可以使用条件方法,但使用BooleanSwitch
或TraceSwitch
测试的条件不会转发给监听器,也就是说,监听器无法按其TraceSwitch
级别对传入消息进行分类。因此,跟踪输出将不包含错误级别信息。- 在使用标准跟踪功能时,无法为不同的跟踪监听器分配不同的严重性阈值。跟踪输出对所有监听器都相同,尽管你很难将与写入文本文件相同数量的信息发送到 Windows 事件日志。
我认为这些遗漏是设计缺陷:将消息严重性级别排除在 .NET 跟踪实现之外,严重限制了 Trace 类在生产环境中的可用性。我只能想到一个原因,为什么 Trace
被设计成这样:Trace
类在内部几乎是 Debug
类的克隆——它们共享相同的实现,仅在预处理器符号和默认监听器上有所不同。我希望 Trace
拥有更多自己的功能并且更具可扩展性。
但在你决定实现自己的跟踪功能(或使用我在下一节中将提到的功能)之前,请记住,一旦你替换了内置的 .NET Trace
类,你就不再使用统一的跟踪输出了。如果你的应用程序由几个由不同开发人员——甚至供应商——编写的组件组成,你将面临由不同跟踪引擎生成的多个跟踪输出的风险。
那么,应该使用什么标准来选择发布版本的跟踪实现呢?选择当然是你的,但我会考虑以下几点:
- 如果你开发可重用组件,你不应该添加对自定义跟踪实现的依赖:使用内置的 .NET 类,它们将是最通用的;
- 对于大多数桌面应用程序,内置的跟踪监听器(调试、文本和事件日志)提供了足够多的选项;如果你对输出格式不满意,你可以随时通过继承监听器本身或相应的基于
Stream
的类来定制它;因此,在这种情况下,你也应该尝试坚持使用标准的 .NETTrace
类; - 如果你开发企业级应用程序,特别是如果你的程序需要满足 24x7 的可用性要求,你很可能需要优化跟踪输出的清晰度,以便在发生故障时能够快速定位系统日志中的可疑部分;在这种情况下,你不仅需要按监听器过滤跟踪输出,还需要为每条消息存储严重性级别——这些选项都无法从内置的 .NET 跟踪类中获得,因此你需要寻找替代方案。
面向企业的跟踪
那么,如果你需要更精细地控制跟踪输出,内置的 .NET Trace
类有什么替代方案呢?微软似乎意识到了当前 .NET 跟踪的局限性,并且很快就会帮助我们:下一版本的 Visual Studio.NET(代号为“Everett”)将包含企业仪器框架(EIF),该框架将填补这些空白并提供许多新功能。EIF 将支持可配置的事件过滤和严重性级别,因此开发人员应该能够编写以下代码:
// Note that the syntax may change when EIF is released TraceMessageEvent.Raise("My trace message"); ErrorMessageEvent.Raise("My error", 1, "CODE"); // message, severity, error code
当然,SQL 数据库可以配置为跟踪事件存储库,这使得 EIF 成为审计目的的绝佳选择。
虽然企业仪器框架满足你“明天”的需求,但如果你更关心“今天”要去哪里,你必须去别处寻找。一个不错的替代方案是挪威公司 Trimanet 开发的 TrimaTrace 解决方案。它比标准的 .NET 跟踪功能强大得多,可以通过 TCP 远程使用,并且性能非常好(在 1 GHz CPU 的 Pentium III 机器上每秒超过 30,000 条消息)。TrimaTrace 无与伦比的可负担性,因为它免费。
在我上传了本文的第一版后,我收到了另一个替代方案的参考——流行的 log4j Java API 的 .NET 实现,它提供了对日志管理和配置的灵活且任意粒度的控制。这个实现也是免费的,由 NeoWorks 在 SourceForge 上托管。
结论
每一个现代设计决策都是复杂的:所有简单的问题都已得到解答,我们剩下的是比较和妥协的必要。调试选项和格式化跟踪输出等主题在面对我们每天必须解决的“真正”问题时似乎并不重要。然而,不要过度简化它们:它们是你开发环境的基础部分,值得妥善安排。
资源
- Vagif Abilov. 编写自定义 .NET 跟踪监听器。
- Richard Grimes. 使用 Visual Studio.NET 开发应用程序。
- Mansoor Ahmed Siddiqui. .NET 中的跟踪和实现你自己的跟踪监听器。
- TrimaTrace,由 Trimanet 开发的免费 .NET 跟踪工具。
- Log4Net,由 NeoWorks 开发的 Java 日志 API 的免费 .NET 端口。