我将主要从使用抽象来隔离应用程序代码与特定日志框架之间的角度进行讲解。还有其他因素可能会影响某人选择日志框架或抽象的选择和需求。
我最近花了很多时间评估各种日志框架以及第三方日志抽象。
有些人认为将其应用程序代码与特定日志框架隔离开是有价值的。您会在这里找到许多像
这个 和
这个 和
这个 (还有更多)的帖子,在这些帖子中讨论了日志记录,并且许多人认为日志框架应该被包装/抽象化。
显然,这样可以使您不受限于特定的框架。这很重要吗?您真的会更换日志框架吗?好吧,也有很多人不提及包装或那些反对它的人。如果您看一下已发布的一些日志框架包装代码示例,您还可以看到许多示例,说明至少某些人不应该包装其日志框架!
如果您最近启动了一个项目,可能已经检查了日志框架并将其缩小为两个最终候选:log4net和NLog。每个都有支持它的论点。 log4net显然是最受欢迎的,可能是表达意见者中最受欢迎的。 NLog提供非常相似的功能。从流行度来判断,log4net可能是明显的选择。基于功能,它们似乎非常相似。根据“最近的活动”(由源代码存储库的签入、博客活动或缺乏活动等指示),NLog是明显的选择。如果您一年前必须选择,您可能会选择log4net,因为它是“安全”的选择。当时不清楚NLog何时发布。在此之后的一年里,NLog经历了相当大的开发周期,几天前发布了Beta版本。
一年前该如何选择?现在选择哪一个?那时有一个明显更好的选择吗?现在哪一个更好?抽象化带来的好处之一是能够推迟选择哪一个(你甚至不必永远都选择,尽管如果你计划使用日志框架交付产品,可能还是需要选择)。你可以测试一种框架,然后再测试另一种,感受它们在你的应用程序、团队和环境中的工作方式。类似使用
Common.Logging或
SLF这样的东西,允许你现在就编写代码,编写到某个日志接口/API,并放置你的日志代码。如果你认为抽象提供的接口/API足以支持你的工作(而且为什么不呢?因为它本质上与log4net和NLog提供的接口/API相同),那么使用抽象基本上没有太大的危险。在开发周期中,你可能会发现一种框架比另一种更适合于你的需求。由于已经编码到了抽象层,所以在任何时候,直到你的产品出门前,你都可以自由地进行选择。
你甚至可以考虑,从头开始编写一个日志库。同样,如果你认为log4net和/或NLog的接口/API足以满足你的需求,那么你可以使用类似的API来实现自己的日志库。如果你相信这一点,那也可能是使用抽象的另一个原因。同样,你可以从今天开始编写代码(针对你的产品,而不是你的日志库),使用其他日志框架进行日志记录,直到你的“从头开始”日志库准备就绪为止。也许你真的想使用System.Diagnostics.TraceSource和
Ukadc.Diagnostics(以获得类似于log4net或NLog的输出格式化功能),以便在某些平台上使用TraceSources实现的日志记录与Microsoft的日志记录“更好”地集成。使用TraceSources编写“记录器”,然后编写抽象层,以便将其插入到Common.Logging或SLF中,可能非常容易。(如果接口/API足够,你可以仅基于抽象层库的接口编写“记录器”,而无需编写额外的抽象层)。
有了这样具有说服力的论点,为什么还会有人不使用抽象层呢?哈哈,只是开个玩笑!如果一个抽象化很好,应该自己写还是使用现有的?如果你自己写一个,那么显然你必须要写它。怎么做呢?你可以定义一个接口并包装一个框架(要小心并正确地进行封装!)。之后,如果你决定想换框架,就封装那个框架。如果你小心谨慎,你不需要改变任何应用程序代码,除非你真正创建底层框架的对象。也许这很好。你避免了对某些第三方抽象化的依赖,只需实现单个包装器覆盖单个框架的“小”代价。但是,这是有成本的。在写完你的抽象之前,你不能真正写出有日志记录的大量应用程序代码,除非你有一个更好的策略将其转换为你的抽象。测试驱动两个或多个框架以决定哪个更适合你也变得更加困难。您想要“尝试”的每个框架都需要另外进行一次包装作业。如果您想要轻松地在框架之间切换(至少在开发周期内)则需要做出努力。第三方框架已经为此提供了开箱即用的功能。
哇!现在我被卖了!给我日志记录抽象化,不然我就死!
日志记录抽象化都是好处吗?有什么缺点吗?它们不可能那么好,对吧?
嗯,像购买任何东西或得到免费东西一样,你得到的就是所提供的。日志记录抽象化也不例外。Common.Logging和SLF都没有至少一个非常重要的log4net / NLog日志记录上下文能力集(GDC、MDC、NDC)。这些可以是获得足够信息记录和格式化以使你从中获得最大价值的关键。SLF不提供TraceSource抽象,也不提供IsXXXEnabled函数。Common.Logging提供TraceSource抽象。Castle.Logging为log4net和NLog暴露GDC / MDC / NDC。它还提供了TraceSource抽象。Castle的TraceSource抽象通过提供类似于log4net和NLog提供的“分层”命名功能来增强TraceSource日志记录。看起来很酷!
此外,这些项目都是以某种形式开源的。因此,根据抽象化程度,开发人员可能对保持其最新状态和添加新功能具有更多或更少的利益。据我所知,Common.Logging已经经历了几个版本,并在Spring.Net中使用。至少在历史上似乎很活跃。Castle.Logging在Castle框架中使用。因此,他们显然有“真正”的客户并获得“真实的”使用,这将有望推动更多功能实现。据我所知,SLF不作为“真实”开发平台的一部分使用,因此很难说它被多少人使用。这些平台的路线图尚不清晰。Common.Logging在其网站上列出了一些即将推出的功能,但并没有明确说明它们何时可用。网站上写着“六月”,但是是哪一年的六月呢?邮件列表的监视频率如何?对于SLF,他们的codeplex监控频率有多高?与开发人员的付费工作相比,这些“免费”项目的优先级如何?您是否能负担得起一些第三方抽象来实现所需的功能?如果您实现了某些功能并提交回以供考虑纳入产品中,他们是否会接受?
好处是,所有这些抽象的源代码都是可用的,因此您可以承担责任并进行任何修复或添加任何增强功能,而无需经过创建抽象的时间和精力。您是否喜欢Common.Logging,但真的想要log4net / NLog GDC / MDC / NDC?获取Castle的实现并将其添加到Common.Logging中。瞧!一个记录抽象,包含近100%的log4net / NLog记录API。您是否喜欢SLF但希望它具有IsXXXEnabled?实现这并不需要太多的工作。在你加上GDC / MDC / NDC之前,请继续进行。您是否喜欢Castle?(我并不太熟悉它,不确定它在Castle之外使用起来有多容易,如果这很重要的话)请注意,我没有使用过它,但是看着git上的源代码,NLog记录器抽象可能 不会保留呼叫站点信息。
将多个开放源代码项目的部分组合成一个“超级”项目(供您或公司使用)是否道德?从Common.Logging中获取并增强Castle的GDC / MDC / NDC实现是否不好?我不知道。我会让其他人回答这个问题。
一些第三方日志记录抽象提供其他功能。您可能会使用一个以log4net为例的库。您可能不想使用log4net,或者至少可能不想受其约束。Common.Logging(和可能是SLF)使您相对较容易地捕获log4net记录消息并重新路由它们通过抽象,以便在抽象的基础日志框架的日志流中捕获它们。 SLF可能提供类似的东西。当然,您可能可以使用现有的日志框架做类似的事情,无论是开箱即用还是编写自定义的log4net Appender、NLog Target或System.Diagnostics TraceListener。这些特性在我对是否在我的项目中使用第三方日志记录抽象的评估中并不是很高,因为我主要感兴趣的是抽象方面。
那么,我的立场是什么?我认为将应用程序代码与特定的日志记录框架隔离开是有价值的。对我来说,Common.Logging看起来是一个很好的抽象选择,尽管缺少一些重要的功能(GDC/MDC/NDC)并且不兼容Silverlight。如果这些功能很快可以获得将会很棒。如果必须的话,我可以很容易地实现GDC/MDC/NDC。使其兼容Silverlight可能需要更多的努力,主要是因为我对C#/.NET/Silverlight不是特别熟悉。在这些问题得到解决之前,我们将能够使用Common.Logging编写大量的应用程序代码。我们可以花时间开发我们的应用程序而不是再开发另一个日志记录库或抽象库。如果最终必须自己添加这些缺失的功能,那么我们就必须做很多工作,就像我们如果自己实现日志记录库或抽象库一样。