何时应该使用Tracing而不是Logger.NET、Enterprise Library、log4net或Ukadc.Diagnostics?

42
我该如何在标准追踪、Logger.NET、企业库、log4net或Ukadc.Diagnostics之间进行选择?它们各自适用的情况有哪些呢?(比如ASP.NET、控制台应用程序、Azure Cloud、SOHO、企业级...)它们的优缺点是什么?还有没有其他重要的日志框架被我忽略了?
6个回答

105

这里有很多类似的问题:

你错过了几个常用的日志记录框架。以下是一些常用框架的列表,其中包括你列出的一些:

日志记录抽象:

System.Diagnostics 插件:

其他

在CodePlex上还有几个其他的日志框架(我在Stack Overflow上看到过提及):

为什么你会选择其中之一?这是一个棘手的问题。很大程度上取决于个人偏好。其中一些是技术(或功能)优越性。任何日志记录框架(特别是第三方框架)最明显的缺点是支持质量。如果您对log4net、NLog、Common.Logging等有问题,您能否从这些框架的开发者那里得到修复?虽然这些框架的源代码可用,但您可能更喜欢不“继承”源树来进行修复或添加增强功能。我会说,这些框架非常可扩展,许多增强功能可以通过正常的扩展点添加。如果您阅读我上面发布的链接,我认为可以公平地说,仅基于有利提及的数量,log4net将成为明显的“赢家”。它将被更频繁地提及作为历史记录的喜爱,并且许多人将选择使用它。NLog有其支持者,但似乎没有log4net那样的渗透率或“头脑中的认知度”,尽管它们非常相似。NLog的功能与log4net非常相似,并且它还具有最近经历过重大开发周期的额外优势。企业库通常被誉为不错的选择,但同样经常被誉为糟糕的选择。也许它的一些负面声誉是早期版本不太好?现在可能更好了吗?

System.Diagnostics经常被推荐作为一个合理的选择,至少有三个强大的好处:没有第三方依赖,许多Microsoft组件都使用了System.Diagnostics进行仪表化,它很容易扩展(可能添加一些在log4net和NLog等框架中已经免费提供的功能)。如果您使用System.Diagnostics,我认为共识将是(也是我的建议)使用TraceSource对象而不是Trace.WriteLine/Debug.WriteLine。

还要注意的是,System.Diagnostics和WCF很好地配合使用。WCF消息流量可以使用System.Diagnostics记录,并且WCF还将在WCF服务边界调用之间传播System.Diagnostics活动信息(System.Diagnostics.CorrelationManager.ActivityId)。

我不确定log4net是否应该继续保持其最受青睐的地位。正如在SO上其他地方所指出的那样,log4net似乎最近没有进行太多开发(请注意,我认为“log4net已死”是一种夸张),而NLog 2.0目前正在beta测试中,最终版本预计在2011年第一季度发布(更新:NLog 2.0 已于2011年7月17日发布)。这是否使得NLog比log4net显然更好?我不知道,但我认为,在选择两者之间时,相对而言,NLog应该获得至少相等的考虑,并且可能应该成为新开发的首选,至少在log4net开发显示更多生命迹象之前。

log4net和NLog都提供非常灵活的配置选项。它们允许您在定义日志语句时具有非常细粒度的控制(通过“标准”模式定义每个类型的记录器)。它们还允许您通过开发自己的“日志目标”对象(log4net附加程序和NLog目标)和“格式化”对象(log4net模式转换器和NLog布局渲染器)轻松扩展库。
除了选择记录框架外,一些人主张通过使用抽象层来隔离应用程序代码与特定记录框架的强依赖性。这可以采用您自己的ILogger接口的形式进行实现,可能是在现有框架之上。将来,您可以通过在不同的框架上实现ILogger来更改框架。或者,您可以使用DI/IoC将“ILogger”注入到您的代码中。许多DI/IoC框架提供了一个内置的ILogger抽象,可以配置为使用log4net、NLog或Enterprise Library,或者您可以编写自己的ILogger实现并注入它。谁关心实现呢?另一种将代码与特定记录框架的强依赖性隔离的方法是通过使用现有的日志抽象框架,例如Common.Logging或SLF。好处是,再次强调,您的应用程序不依赖于特定的记录框架。然而,有人会说,您只是将一个依赖项(记录框架)换成了另一个(日志抽象框架)。
关于日志抽象还有两点需要注意:
  1. 一个好的日志抽象应该允许你在同一个输出文件中捕获来自不同日志框架的输出。Common.Logging称之为“桥接”。假设你使用Common.Logging编写了一个应用程序,支持NLog。现在假设你正在使用一个使用log4net直接编写的第三方类库。通过桥接系统,您可以捕获log4net输出(通过自定义appender)并重新路由它通过Common.Logging,以便可以在您的应用程序日志输出的上下文中查看第三方类库的日志输出。

  2. 使用日志抽象还允许您在开发过程中“试驾”日志框架。您可能开始认为log4net是最好的选择,但您想让自己尝试NLog。使用日志抽象相对容易在两者之间切换。最终,您可以选择哪个日志框架,但与此同时,您已经能够编写大量不以任何特定日志框架为依赖的代码。

您可能选择一个框架而不是另一个框架的另一个原因是您工作的环境。如果您已经使用企业库的一部分,那可能足以推动您使用Enterprise Library日志记录。

如果您正在开发Silverlight呢?您可能会选择使用Clog - part of Calcium这样的东西。您也可以选择使用NLog 2.0,它与Silverlight和WP7兼容。

System.Diagnostics addons (Ukadc.Diagnostics, Essential.Diagnostics)。它们本身不是日志框架,而是表示可与现有的System.Diagnostics框架一起使用的有用对象和扩展点的集合。在我看来,这些插件中最好的一个是每个插件都增加了类似于log4net和NLog的格式化日志输出的功能。我没有使用过Essential.Diagnostics,但我已经尝试过Ukadc.Diagnostics,认为它非常酷。甚至编写自己的“格式化标记”也很容易。

我不知道这是否完全回答了您的问题(无论如何,它都很广泛),但我认为这里有很多值得思考的东西。


2
100万个赞,非常感谢您的回答,看起来是基于经验和广泛知识的! - makerofthings7
5
我想投票关闭这个问题,因为在SO上已经有很多次提问。然而,你的答案非常好。它真正增加了SO上已有答案的价值。出于这个原因,我不投票关闭,但是给你一个+1。 - Steven
@Steven - 感谢您的赞美之言! - wageoghe
1
哇,谢谢你提供这么详细的答案。我一直在比较日志实现方式...但现在我已经把重点转移到了首先检查抽象工具上。 - Damien Sawyer
2
有关上述主要日志框架(System.Diagnostics、log4net、NLog 和 Enterprise Library)的比较,包括性能比较,请参阅 https://essentialdiagnostics.codeplex.com/wikipage?title=Comparison。 - Sly Gryphon

5
我刚开始在VS2010中使用log4net,并发现它依赖于System.Web...这使得它与“.NET x.x客户端框架”目标不兼容...考虑到有人在这里发布的关于Windows Update使用Client Profile作为.NET可再发行版本的选择,这意味着如果您想让您的代码在大多数计算机上运行,log4net将不再是首选的记录器...感谢其他选择的信息-我会去了解一下...

3

从微软2013年的Build会议中学到了一些东西:

  • 在高负载下,Log4NET主要由于这个进程是同步的,所以写入文件。在某些条件下可能会出现争用和超时。可以使用AppDynamics或任何类似的工具进行验证。

  • NLog不实现排队,因此在负载下,IO调用会堆积。

  • 根据微软的说法,ETW使用内核环形缓冲区,效率非常高。 .NET 4.5和事件日志框架结合使用语义化日志应用程序块(也称为SLAB)将使其更加高效。


2
请引用您的示例。 - Dan Esparza
@DanEsparza,我相信我问题中的链接里面包含了所有引用。 - makerofthings7
6
我在寻找关于“在某些情况下可能会出现争用和超时”、“NLog没有实现排队,因此在负载下,IO调用会堆积起来”和“根据微软的说法,ETW使用内核环形缓冲区,这是非常高效的”链接。 - Dan Esparza

1
我不是log4j或log4net的粉丝。我喜欢java.util.net日志记录工具,并在名为NetLog的github项目上重新创建了它,大部分内容都一样,链接为https://github.com/greggwon/NetLog/。欢迎提供反馈。我正在努力抽出时间,用ConfigurationManager替代logging.properties文件进行配置。使用java.util.logging,很容易使用命令行属性设置指定日志配置所在位置。如果不使用ConfigurationManager,在.net中会更加麻烦。提供对CM的支持,将为一些日志记录器和处理程序之间的不同关系打开大门,这可能会使一些事情变得更好。
NetLog包括一个EventLogHandler,可记录到系统事件日志中。它还有一个Level.EventLog级别设置,仅略低于“警告”,可以让您使用命名的“级别”来针对EventLog,而无需使用“WARNING”或“SEVERE”。我还有一个TCPSocketHandler,可以让您通过telnet进入“日志记录”,以便您可以在Windows上进行“尾随”,而无需使用“尾随”程序。

0

由于某些原因,System.Diagnostics不支持将所有跟踪输出定向到单个侦听器的方法。如果您希望将多个源定向到同一个侦听器,则必须显式列出每个源的名称。

在具有许多依赖项的大型系统中,您可能不知道所有源,也可能不关心。您只想查看输出以了解底层发生了什么。为每个源单独设置侦听器使得在大型系统中使用System.Diagnostics变得更加困难。

log4net不仅支持根级别的附加器(侦听器),还支持分层记录,允许您将记录配置为逻辑源的一组。在我看来,这使得log4net成为明显的选择。


0

看看GitHub上的NetLog.Logging包,它是我的作品。它有一个监控应用程序,并遵循java.util.logging API范例,因为这是我喜欢使用的。它有一个自旋锁来访问“写入”,锁持有者将所有排队记录都写入到限制之前,然后再继续。这将使日志记录 less contention based I/O,提供了一个良好的折衷方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接