记录最佳做法


323

我想获得有关人们如何在实际应用程序中处理跟踪和日志记录的故事。以下是一些可能有助于您解答的问题。

构架

您使用什么框架?

  • log4net
  • System.Diagnostics.Trace
  • System.Diagnostics.TraceSource
  • 记录应用程序块
  • 其他?

如果使用跟踪,是否使用Trace.Correlation.StartLogicalOperation?

您是手动编写此代码,还是使用某种形式的面向方面的编程来做到这一点?想要共享一个代码段吗?

您是否在跟踪源上提供任何形式的粒度?例如,WPF TraceSources允许您在各个级别进行配置:

  • System.Windows- 所有WPF的设置
  • System.Windows.Animation- 专门为Animation覆盖。

听众

您使用什么日志输出?

  • 文字档
  • XML文件
  • 事件簿
  • 其他?

如果使用文件,是使用滚动日志还是仅使用一个文件?您如何使日志可供人们使用?

观看中

您使用什么工具查看日志?

  • 记事本
  • 尾巴
  • 事件查看器
  • 系统中心运营经理/微软运营经理
  • WCF服务跟踪查看器
  • 其他?

如果要构建ASP.NET解决方案,还使用ASP.NET运行状况监视吗?您是否在运行状况监视器事件中包括跟踪输出?那么Trace.axd呢?

定制性能计数器呢?


3
如果人们以300票赞成价结束类似问题的解答,可能会建议采用Wiki格式或在developer.stackexchange上发布,或者如果不欢迎此类问题,则建议使用Quora。显然,这个问题实际上是很有建设性的,只是不符合StackOverflow想要的标准。programmers.stackexchange.com/questions/57064/...有24个upvotes。也许StackOverflow缺少了什么?
Niall Connaughton

如果此问题违反了问答格式,则问答格式可能有误,而不是此问题。有时,是否应该关闭某个问题的决定应该取决于所提供的答案,一些开放式问题会引起辩论,而另一些问题会邀请用户提供有价值的内容,例如这个!
马提亚斯·沃尔夫

1
如果有人想这样使用,那么这个问题-尤其是最高答案-可能会为博客文章打下良好的基础。...作为一个客观的问题,它实际上并不适合-它明确地构成了稻草民意调查-但下面有一些很好的信息,因此是锁定的。
Shog9 2013年

Answers:


232

更新:有关System.Diagnostics的扩展,提供了您可能需要的一些缺少的侦听器,请参阅CodePlex上的Essential.Diagnostics(http://essentialdiagnostics.codeplex.com/


构架

问:您使用什么框架?

答:System.Diagnostics.TraceSource,内置于.NET 2.0。

它为应用程序提供了强大,灵活,高性能的日志记录,但是许多开发人员并未意识到其功能,也没有充分利用它们。

在某些领域中,附加功能很有用,或者有时存在该功能,但没有充分记录,但这并不意味着应丢弃整个日志记录框架(设计为可扩展的),并像一些流行的替代品一样完全替换掉(NLog,log4net,Common.Logging甚至EntLib日志记录)。

无需更改在应用程序中添加日志记录语句和重新发明轮子的方式,只需在需要的几个地方扩展System.Diagnostics框架即可。

在我看来,其他框架,甚至是EntLib,都只是遭受“这里没有发明综合症”之苦,而且我认为他们浪费了时间来重新发明在System.Diagnostics中已经很好运行的基础知识(例如,如何编写日志语句),而不是填补现有的一些空白。简而言之,不要使用它们-不需要它们。

您可能不知道的功能:

  • 使用带格式字符串和args的TraceEvent重载可以提高性能,因为将参数作为单独的引用保留,直到Filter.ShouldTrace()成功。这意味着在系统确认消息实际记录之前,不会对参数值进行昂贵的ToString()调用。
  • Trace.CorrelationManager允许您将有关同一逻辑操作的日志语句关联起来(请参见下文)。
  • VisualBasic.Logging.FileLogTraceListener非常适合写入日志文件,并支持文件旋转。尽管在VisualBasic名称空间中,但只需包含DLL,就可以在C#(或其他语言)项目中轻松使用它。
  • 使用EventLogTraceListener时,如果使用多个参数并使用空或null格式的字符串调用TraceEvent,则如果使用的是本地化消息资源,则args将直接传递给EventLog.WriteEntry()。
  • Service Trace Viewer工具(来自WCF)对于查看与活动相关的日志文件的图形很有用(即使您不使用WCF)。这确实可以帮助调试涉及多个线程/活动的复杂问题。
  • 通过清除所有侦听器(或删除默认值)来避免开销;否则,Default会将所有内容传递给跟踪系统(并产生所有这些ToString()开销)。

您可能需要考虑扩展的区域(如果需要):

  • 数据库跟踪侦听器
  • 彩色控制台跟踪侦听器
  • MSMQ /电子邮件/ WMI跟踪侦听器(如果需要)
  • 实现FileSystemWatcher以调用Trace.Refresh进行动态配置更改

其他建议:

使用结构化事件ID,并保留参考列表(例如,在枚举中记录它们)。

对于系统中的每个(重要)事件,具有唯一的事件ID对于关联和查找特定问题非常有用。追溯到记录/使用事件ID的特定代码很容易,并且可以很容易地为常见错误提供指导,例如错误5178表示您的数据库连接字符串有误,等等。

事件ID应该遵循某种结构(类似于电子邮件和HTTP中使用的回复代码理论),这使您可以按类别对待它们,而无需知道特定的代码。

例如,第一位数字可以详细说明通用类别:1xxx可以用于“开始”操作,2xxx可以用于正常行为,3xxx可以用于活动跟踪,4xxx可以用于警告,5xxx可以用于错误,8xxx可以用于“停止”操作,9xxx可以用于致命错误,等等

第二位数字可以详细说明该区域,例如,用于数据库信息的21xx(用于数据库警告的41xx,用于数据库错误的51xx),用于计算模式的22xx(用于计算警告的42xx等),用于另一个模块的23xx等。

分配的结构化事件ID还允许您在过滤器中使用它们。

问:如果使用跟踪,是否使用Trace.Correlation.StartLogicalOperation?

答:Trace.CorrelationManager对于在任何类型的多线程环境中进行日志语句关联非常有用(目前几乎是任何东西)。

您至少需要为每个逻辑操作设置一次ActivityId以便关联。

然后可以将Start / Stop和LogicalOperationStack用于简单的基于堆栈的上下文。对于更复杂的上下文(例如异步操作),将TraceTransfer应用于新的ActivityId(在更改之前)允许关联。

Service Trace Viewer工具对于查看活动图很有用(即使您没有使用WCF)。

问:您是手动编写此代码,还是使用某种形式的面向方面的编程来做到这一点?想要共享一个代码段吗?

答:您可能想要创建一个范围类,例如LogicalOperationScope,该范围类(a)在创建时设置上下文,并且(b)在处置时重置上下文。

这使您可以编写如下代码来自动包装操作:

  using( LogicalOperationScope operation = new LogicalOperationScope("Operation") )
  {
    // .. do work here
  }

创建时,作用域可以首先根据需要设置ActivityId,调用StartLogicalOperation,然后记录TraceEventType.Start消息。在Dispose上,它可能会记录一个Stop消息,然后调用StopLogicalOperation。

问:您是否提供跟踪来源的任何形式的粒度?例如,WPF TraceSources允许您在各个级别进行配置。

答:是的,随着系统的扩大,多个跟踪源非常有用/重要。

尽管您可能希望始终记录所有警告和以上消息,或所有信息和以上消息,但是对于任何大小合理的系统,活动跟踪(开始,停止等)和详细记录的数量都变得太多了。

而不是仅用一个开关将其全部打开或关闭,而是能够一次为系统的一个部分打开此信息很有用。

这样,您可以从通常的日志记录中查找重大问题(所有警告,错误等),然后在所需部分上“放大”并将其设置为“活动跟踪”或“调试”级别。

所需的跟踪源数量取决于您的应用程序,例如,您可能希望每个程序集或应用程序的每个主要部分使用一个跟踪源。

如果您需要更精细的控制,请添加单个布尔开关以打开/关闭特定的高容量跟踪,例如原始消息转储。(或者可以使用单独的跟踪源,类似于WCF / WPF)。

您可能还需要为活动跟踪与常规(其他)日志记录考虑单独的跟踪源,因为它可以使按所需的方式精确配置过滤器变得容易一些。

请注意,即使使用了不同的来源,消息仍然可以通过ActivityId进行关联,因此可以根据需要使用多个消息。


听众

问:您使用什么日志输出?

这可能取决于您正在编写的应用程序类型以及正在记录的内容。通常,不同的东西会放在不同的位置(即多个输出)。

我通常将输出分为三类:

(1)事件-Windows事件日志(和跟踪文件)

例如,如果编写服务器/服务,则Windows上的最佳实践是使用Windows事件日志(您没有要向其报告的UI)。

在这种情况下,所有致命,错误,警告和(服务级别)信息事件都应转到Windows事件日志中。对于这些类型的高级事件,应该保留信息级别,这些事件是您要在事件日志中进行的事件,例如“服务已启动”,“服务已停止”,“已连接到Xyz”,甚至可能是“计划已启动” ,“用户登录”等。

在某些情况下,您可能希望将事件日志写入应用程序的内置部分,而不是通过跟踪系统(即,直接写入事件日志条目)。这意味着它不会被意外关闭。(请注意,您仍然还希望在跟踪系统中记录同一事件,以便可以进行关联)。

相反,Windows GUI应用程序通常会将这些报告给用户(尽管他们也可能会记录到Windows事件日志中)。

事件还可能具有相关的性能计数器(例如,错误数/秒),协调任何直接写入事件日志,性能计数器,写入跟踪系统并报告给用户的报告很重要,以便它们发生在同一时间。

即,如果用户在特定时间看到错误消息,则应该能够在Windows事件日志中找到相同的错误消息,然后在跟踪日志中找到具有相同时间戳的同一事件(以及其他跟踪详细信息)。

(2)活动-应用程序日志文件或数据库表(和跟踪文件)

这是系统执行的常规活动,例如提供网页,提交股票交易,收取订单,执行计算等。

活动跟踪(开始,停止等)在此处(正确的粒度)很有用。

同样,使用特定的应用程序日志(有时也称为审核日志)非常普遍。通常,这是数据库表或应用程序日志文件,包含结构化数据(即一组字段)。

根据您的应用程序,这里的情况可能会变得有些模糊。一个很好的例子是一个Web服务器,它将每个请求写入Web日志。类似的示例可能是消息传递系统或计算系统,其中记录了每个操作以及特定于应用程序的详细信息。

一个不太好的例子是股票交易或销售订购系统。在这些系统中,您可能已经在记录活动,因为它们具有重要的业务价值,但是将它们与其他操作相关联的原理仍然很重要。

除自定义应用程序日志外,活动通常还具有相关的性能计数器,例如每秒的事务数。

通常,您应该协调不同系统之间的活动日志记录,即,在增加性能计数器并记录到跟踪系统的同时,写入应用程序日志。如果您同时执行所有操作(或在代码中彼此直接执行),则调试问题会更容易(比它们都在代码中的不同时间/位置发生的情况要容易得多)。

(3)调试跟踪-文本文件,或者XML或数据库。

这是详细级别和更低级别的信息(例如,用于打开/关闭原始数据转储的自定义布尔开关)。这提供了系统在子活动级别上所做的事情的细节。

这是您希望能够为应用程序的各个部分打开/关闭的级别(因此有多个来源)。您不希望这些东西弄乱Windows事件日志。有时会使用数据库,但更有可能是在一定时间后清除的滚动日志文件。

此信息与应用程序日志文件之间的最大区别在于它是非结构化的。尽管“应用程序日志”可能包含“至”,“发件人”,“金额”等字段,但是详细的调试跟踪可能是程序员输入的内容,例如“检查值X = {value},Y = false”或诸如“完成,然后重试”。

一种重要的做法是确保您放入应用程序日志文件中的内容或Windows事件日志也以相同的详细信息(例如时间戳)记录到跟踪系统中。这样,您便可以在调查时关联不同的日志。

如果由于复杂的关联而打算使用特定的日志查看器,例如Service Trace Viewer,则需要使用适当的格式,即XML。否则,一个简单的文本文件通常就足够了-在较低的级别上,信息基本上是非结构化的,因此您可能会发现数组的转储,堆栈的转储等。如果可以在更高级别上与更结构化的日志相关联,则应该好好地。

问:如果使用文件,是使用滚动日志还是仅使用一个文件?您如何使日志可供人们使用?

答:对于文件,通常您希望从可管理性的角度滚动日志文件(使用System.Diagnostics只需使用VisualBasic.Logging.FileLogTraceListener)。

可用性再次取决于系统。如果仅是在谈论文件,那么对于服务器/服务来说,只是在必要时才可以访问滚动文件。(Windows事件日志或数据库应用程序日志将具有其自己的访问机制)。

如果您无法轻松访问文件系统,则对数据库的调试跟踪可能会更容易。[即实现数据库TraceListener]。

我为Windows GUI应用程序看到的一个有趣的解决方案是,它在运行时将非常详细的跟踪信息记录到“飞行记录器”中,然后如果没有问题就将其关闭,则它只是删除了文件。

但是,如果它崩溃或遇到问题,则不会删除该文件。如果它捕获到错误,或者下次运行它将注意到该文件,然后它可以采取措施,例如将其压缩(例如7zip)并通过电子邮件发送,或者以其他方式提供。

如今,许多系统将故障自动报告合并到中央服务器(例如,出于隐私原因与用户核对之后)。


观看中

问:您使用哪些工具查看日志?

答:如果出于不同原因有多个日志,则将使用多个查看器。

Notepad / vi / Notepad ++或任何其他文本编辑器是纯文本日志的基础。

如果您有复杂的操作,例如带有转移的活动,那么您显然会使用诸如Service Trace Viewer之类的专用工具。(但是,如果您不需要它,则文本编辑器会更容易)。

由于我通常将高级信息记录到Windows事件日志中,因此它提供了一种以结构化方式获得概述的快速方法(查找漂亮的错误/警告图标)。尽管日志至少为您提供了一个起点,但您仅需要在日志中没有足够的文本时就开始搜索文本文件。(此时,确保您的日志具有协调的整体非常有用)。

通常,Windows事件日志还使这些重要事件可用于MOM或OpenView等监视工具。

其他 -

如果您登录到数据库,则可以轻松地对信息进行过滤和排序(例如,放大特定的活动ID。(对于文本文件,您可以使用Grep / PowerShell或类似工具在所需的特定GUID上进行过滤)

MS Excel(或其他电子表格程序)。如果可以使用正确的定界符导入信息,以便不同的值进入不同的列,这对于分析结构化或半结构化信息可能很有用。

在调试/测试中运行服务时,为简单起见,我通常将其托管在控制台应用程序中,我发现彩色控制台记录器很有用(例如,红色表示错误,黄色表示警告,等等)。您需要实现自定义跟踪侦听器。

请注意,该框架不包括彩色控制台记录器或数据库记录器,因此,现在,如果需要它们,则需要编写它们(这不太难)。

确实让我感到烦恼的是,几个框架(log4net,EntLib等)浪费了时间重新发明轮子,并重新实现了基本的日志记录,过滤和日志记录到文本文件,Windows事件日志和XML文件,它们各自使用不同的方式(日志语句各不相同);然后,每个人都实现了自己的版本,例如数据库记录器,而现在大多数已经存在,而所需的只是为System.Diagnostics提供几个跟踪侦听器。谈论大量重复工作。

问:如果您要构建ASP.NET解决方案,您是否还使用ASP.NET运行状况监视?您是否在运行状况监视器事件中包括跟踪输出?那么Trace.axd呢?

这些东西可以根据需要打开/关闭。我发现Trace.axd对于调试服务器如何响应某些事件非常有用,但是在频繁使用的环境或长期跟踪中通常没有用。

问:关于自定义性能计数器呢?

对于专业的应用程序,尤其是服务器/服务,我希望看到它同时具有性能监视器计数器和记录到Windows事件日志的功能。这些是Windows中的标准工具,应使用。

您需要确保包括用于所使用的性能计数器和事件日志的安装程序。这些应该在安装时(以管理员身份安装时)创建。当您的应用程序正常运行时,它不需要管理权限(因此将无法创建丢失的日志)。

这是练习以非管理员身份进行开发的好理由(有一个单独的admin帐户用于您需要安装服务的时间,等等)。如果写入事件日志,.NET将在您第一次写入事件日志时自动创建一个丢失的日志。如果您是以非管理员身份开发的,则您将尽早抓住这一点,并避免在客户安装系统后由于客户未以管理员身份运行而无法使用该系统时感到讨厌。


仅供参考:我遇到了一个问题,其中微软跟踪到文件崩溃。如果您有多个进程(或线程)写入同一个文件,并且它们冲突,则会在日志文件上出现文件系统独占访问锁定错误。
杰伊(Jay)

1
System.Diagnostics基础结构是线程安全的;默认行为是锁定框架,但是,如果您提供自己的锁定,则可以覆盖TraceListener.IsThreadSafe。请参阅msdn.microsoft.com/en-us/library/…。对于多个进程,通常会写入单独的文件,但是请注意,服务跟踪查看器可以加载多个跟踪文件(例如,从多台计算机中读取),并通过ActivityId将它们关联起来。
狡猾的狮

1
也许您可以建议如何使用TraceEvent()记录异常?
Dmitriy Sosunov 2012年

1
System.Diagnostics.Trace它不是装饰的主要缺点之一,[Conditional("TRACE")]从而使其无法在生产环境中使用,因为在生产环境中您很少用该TRACE标志编译代码?
阿斯比约恩Ulsberg

2
@asbjornu Visual Studio中的默认Release版本配置已定义了TRACE(对于DEBUG版本,DEBUG已关闭);但是,如果从命令行进行构建,则需要将其打开。
Sly Gryphon

40

我必须加入推荐log4net的合唱团,就我个人而言,它来自平台灵活性(台式机.Net / Compact Framework,32/64位)。

但是,将其包装在私有标签API中是主要的反模式log4net.ILoggerCommons Logging包装器API的.Net对应版本,因此已经为您最小化了耦合,并且由于它也是一个Apache库,通常甚至不必担心,因为您不会放弃任何控制权:必须。

我见过的大多数房屋包装库也犯了一系列错误:

  1. 使用全局单例记录器(或等效的静态入口点)会失去建议的每类记录器模式的精细分辨率,而没有其他选择性增益。
  2. 未能公开可选Exception参数,导致多个问题:
    • 这使得异常日志记录策略更加难以维护,因此与异常一致地无法完成任何工作。
    • 即使使用一致的策略,将异常格式化为字符串也会过早丢失数据。我编写了一个自定义ILayout装饰器,该装饰器对异常执行详细的向下钻取以确定事件链。
  3. 未能公开属性IsLevelEnabled,从而在关闭日志记录的区域或级别时放弃了跳过格式化代码的功能。

1
我的任务是将围绕log4j的(可怕的)内部包装重构为某种程度不那么恐怖的东西(这仍然很糟糕,但这是我对log4j提出的要求shoe之以鼻的结果)。我试图消除全局静态入口点,但被击落。我真的不明白这一点。在我们的设置中,log4j如此之大地扩展和扭曲,以至于它实际上只是用作事件分配器。我们之所以使用它,是因为有人问“我们如何使用log4j?” 无论直接使用log4,还是只是编写自己的框架。中间的路很痛苦。
亚当·贾斯基维奇

25
我不同意您的建议不要包装log4net。使用瘦的提供程序模型API对其进行包装,可以使您的类库的用户插入自己喜欢的日志记录框架。YMMV当然可以,但是将其描述为“主要反模式”有点教条。同样,存在带有“一连串的错误”的包装器库的事实也不是反对编写良好的包装器的好理由。

1
称呼某种反模式并不意味着它总是100%都是一个坏主意-只是如果您不小心,它就会使自己陷入困境。另外,ILog / LogManager本身是一个写得很好的包装迷你库,它与log4net程序集捆绑在一起的commons-logging镜像一样,但是没有理由不能将其提取并转换为适合CLR的commons-logging。
Jeffrey Hantin 09年

18

我不经常在asp.net中进行开发,但是对于记录器,我认为很多最佳实践都是通用的。这是我多年来学到的一些关于伐木的随机想法:

构架

  • 使用记录器抽象框架-像slf4j(或自己滚动),以便将记录器实现与API分离。我已经看到了许多记录器框架的来龙去脉,而您最好能够轻松地采用一种新的记录器框架。
  • 尝试找到一个支持多种输出格式的框架。
  • 尝试找到一个支持插件/自定义过滤器的框架。
  • 使用可以由外部文件配置的框架,以便您的客户/使用者可以轻松地调整日志输出,以便可以由商业日志管理应用程序轻松读取。
  • 确保不要在自定义日志记录级别上过分关注,否则您可能无法使用其他日志记录框架。

记录仪输出

  • 尝试避免使用XML / RSS样式日志进行可能会发生灾难性故障的日志记录。这很重要,因为如果您的记录器未在未关闭的情况下关闭电源开关,</xxx>标签的日志将被破坏。
  • 日志线程。否则,很难跟踪程序的流程。
  • 如果您必须使日志国际化,则可能只希望开发人员以英语(或您选择的语言)登录。
  • 有时,在调试情况下,可以选择将日志记录语句插入SQL查询可能会节省很多时间。如:
    -调用类:com.foocorp.foopackage.FooClass:9021
    SELECT * FROM foo;
  • 您需要类级别的日志记录。您通常也不想使用记录器的静态实例-这不值得进行微优化。
  • 标记和分类记录的异常有时很有用,因为并非所有异常都被创建为相等。因此,如果您有一个日志监视器需要在紧急状态下发送通知,那么尽早了解重要异常的子集会有所帮助。
  • 复制过滤器将节省您的视力和硬盘空间。您是否真的想看到相同的日志记录语句重复10 ^ 10000000次?仅仅得到如下信息不是更好: This is my logging statement - Repeated 100 times

另请参阅我的这个问题


5
复制过滤器是个好主意
Paul Stovell,09年

我曾经就破标签问题达成共识,但是大多数优秀的XML编写者无论如何都不会使用完整的XML(即没有根元素),因此他们可以在不加载XML DOM的情况下进行记录。在罕见的情况下,由于部分书写的条目出现了问题,您可以手动修复它
Paul Stovell,2009年

多年来,我一直在XML记录方面来回走动。现在,对我来说似乎太过分了。如果我需要应用程序状态的RSS提要,我认为最好使用日志监视实用程序来实现。
以利亚

我同意RSS。我正在考虑更多的可视化工具,这些工具可以使您更好地理解该条目。对于文本文件,您通常希望将条目保持在一行;但有时您想包括堆栈跟踪或序列化的对象。这就是XML日志(WCF使用的)派上用场的地方
Paul Stovell,2009年

+1表示提及SQL查询的手段。对于数据库跟踪和应用程序跟踪的关联,这确实非常有用。我在DAL中手动进行操作,但是我想知道这种技术有哪些工具支持?
康斯坦丁

17

我没有资格评论.Net,因为我的头衔是Java,但是过去8年我们在日志记录中进行了移植,您可能会发现一个类似于您问题的有用类比。

我们从JVM中每个线程使用的Singleton记录器开始,然后设置整个过程的记录级别。如果我们甚至必须调试系统的非常特定的部分,这将导致大量日志,因此第一课是对日志进行细分。

当前记录器的形式允许多个实例,其中一个实例定义为默认实例。我们可以实例化具有不同日志记录级别的任意数量的子记录器,但是此体系结构最有用的方面是能够通过简单地更改日志记录属性来为单个程序包和类创建记录器。第二课是创建一个灵活的系统,该系统允许在不更改代码的情况下覆盖其行为。

我们正在使用围绕Log4J封装的Apache commons-logging库。

希望这可以帮助!

*编辑*

阅读下面Jeffrey Hantin的文章后,我意识到我应该注意到我们内部的日志包装器实际上已经变成了什么。现在,它实际上是一个工厂,并且严格用于使用正确的属性文件(由于遗留原因尚未移至默认位置)来正常工作的记录器。由于您现在可以在命令行上指定日志记录配置文件,因此我怀疑它会变得更精简,并且如果您要启动新应用程序,那么我绝对同意他的说法,即您甚至不必费心包装记录器。


感谢您的回答。您是通过代码手动创建子记录器(即,是否对其进行硬编码)还是通过某种自动/隐式方式创建子记录器?
Paul Stovell

否...如果我们将日志记录配置添加到程序包或类的logging.properties文件中,则将按照该配置记录它们,但未特别配置的任何程序包或类将以默认级别进行记录。
史蒂夫·莫耶

9

我们使用Log4Net作为日志记录提供程序,并为日志实例使用单例包装器(尽管正在审查单例,并质疑它们是否是一个好主意)。

我们选择它的原因如下:

  • 在各种环境下进行简单的配置/重新配置
  • 大量的预建附加程序
  • 我们已经使用的CMS之一已内置
  • 不错的日志级别和配置数量

我应该提到,这是从ASP.NET开发的角度讲的

我可以看到使用.NET框架中的Trace的优点,但是我并没有完全将其出售,主要是因为我使用的组件实际上并没有执行任何Trace调用。我经常使用的唯一方法就是System.Net.Mail从我所知道的内容中得知。

因此,我们有一个包装log4net的库,并且在我们的代码中,我们只需要这样的东西:

Logger.Instance.Warn("Something to warn about");
Logger.Instance.Fatal("Something went bad!", new Exception());

try {
  var i = int.Parse("Hello World");
} catch(FormatException, ex) {
  Logger.Instance.Error(ex);
}

在方法中,我们进行检查以查看是否启用了日志记录级别,因此您没有对log4net API的冗余调用(因此,如果未启用Debug,则将忽略debug语句),但是当我有空的时候我将对其进行更新以公开这些内容,以便您可以自己进行检查。这将防止不应该进行的评估,例如:

Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

这将成为:

if(Logger.DebugEnabled) Logger.Instance.Debug(string.Format("Something to debug at {0}", DateTime.Now);

(节省一点执行时间)

默认情况下,我们在两个位置登录:

  1. 网站的文件系统(非服务文件扩展名)
  2. 电子邮件发送错误和致命消息

文件每天滚动一次或10mb(IIRC)。我们不使用EventLog,因为它可能需要比我们通常希望提供的站点更高的安全性。

我发现记事本可以很好地读取日志。


日志记录框架是单个实例不被滥用的少数实例之一。
mmcdole

可能是要在记录器周围提供上下文。但这确实有助于处理并发
Aaron Powell

7
我一定会淘汰单身人士。您当然可以有一个传递的实例(最好在IOC / DI容器中)。我还将尝试将日志记录转移到拦截器中
。...– yfeldblum

2
也不是单个实例的粉丝。我更喜欢给每个类一个唯一命名的记录器,因此在每个模块的基础上增加或减少记录很容易。
杰弗里·汉汀

8

您使用什么框架?

我们结合使用了日志记录应用程序块和围绕.Net框架位工作的自定义日志记录帮助程序。LAB配置为输出相当广泛的日志文件,其中包括用于服务方法进入/退出的单独的常规跟踪文件,以及用于意外问题的特定错误文件。该配置包括日期/时间,线程,pId等,以提供调试帮助,以及完整的异常详细信息和堆栈(在意外异常的情况下)。

自定义日志记录帮助程序利用了Trace.Correlation,在WF中进行日志记录时特别方便。例如,我们有一个状态机,可以调用一系列顺序的工作流。在这些调用活动的每一个中,我们都记录开始(使用StartLogicalOperation),然后在结束时,使用通用的返回事件处理程序停止逻辑操作。

事实证明,这在尝试调试复杂业务序列中的故障时很有用,因为它使我们能够根据活动执行序列更快地确定诸如If / Else分支决策之类的事物。

您使用什么日志输出?

我们使用文本文件和XML文件。文本文件是通过app块配置的,但我们的WF服务也提供了XML输出。这使我们能够捕获运行时事件(持久性等)以及通用业务类型异常。文本文件是按天和大小滚动的滚动日志(我相信总大小为1MB是一个过渡点)。

您使用什么工具查看日志?

我们正在使用记事本和WCF服务跟踪查看器,具体取决于我们正在查看的输出组。如果您正确地设置了输出,并且可以使读取输出更加简单,那么WCF Service Trace Viewer确实非常方便。就是说,如果我大致知道错误的出处,那么阅读带有注释的文本文件也很好。

日志发送到单个目录,然后根据源服务分为多个子目录。根目录通过网站公开,该网站的访问由支持用户组控制。这使我们可以查看生产日志,而不必发出请求,也无需经过冗长的繁文tape节来获取生产数据。


6

作为该工具的作者,我们当然使用SmartInspect来记录和跟踪.NET应用程序。我们通常将命名管道协议用于实时日志记录,将(加密的)二进制日志文件用于最终用户日志。我们使用SmartInspect控制台作为查看器和监视工具。

实际上,那里有很多.NET的日志记录框架和工具。在DotNetLogging.com上有不同工具的概述和比较。


5

答案中有很多很棒的建议。

一般的最佳做法是考虑谁将读取日志。就我而言,它将是客户端站点上的管理员。因此,我记录了使他们可以采取行动的消息。例如,“无法初始化应用程序。这通常是由......引起的”


1

我们在Web应用程序上使用log4net。

当应用程序在运行时发生故障并且您需要查看更多信息时,通过更改XML配置文件在运行时自定义日志记录的功能非常方便。

它还允许您定位要登录的特定类或属性。当您知道发生错误的位置时,这非常方便。一个典型的例子是NHibernate,您只想查看将SQL发送到数据库的情况。

编辑:

我们将所有事件写入数据库和跟踪系统。我们用于错误或异常的事件日志。我们将大多数事件记录到数据库中,以便我们可以创建自定义报告,并让用户查看日志(如果他们希望从应用程序中获得权限)。


您能否提供有关其用法的更多详细信息?您登录到文件还是事件日志?它是滚动日志文件吗?您如何保护或备份它?我对现实生活中的使用感兴趣。
Paul Stovell

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.