c#“缓存调试日志”

本文关键字:日志 调试 缓存 | 更新日期: 2023-09-27 18:04:14

我想向这里的c#专家寻求建议。我的调试日志有问题。我有一个简单的类,它只是打开一个文件,写入提供的字符串,并再次关闭文件。然而,有时我需要使用这个调试日志,而我正在使用多线程。于是麻烦来了。我不能让文件打开多次,所以我收到一个异常,因为我只是试图再次打开被锁定的文件。出于这个目的,我希望有一个类似于"缓存调试日志"的东西,它可以防止这种异常。有没有什么简单的方法来实现这一点?

c#“缓存调试日志”

c# 4.0提供了像System.Collections.Concurrent.ConcurrentQueue<T>这样的线程安全集合。您可以修改日志记录类,使其在自己的线程中运行,并且调用日志方法只是将消息添加到这样的队列中。这样,日志线程就可以安全地从队列中读取条目,并写入文件,而不会中断。

编辑

当然,最方便的做法是开始使用预先存在的日志框架,该框架已经处理好了这些事情。我推荐NLog,尽管log4net也是一个有价值的竞争者。

这通常是通过在代码的所有部分调用一个单例记录器来完成的;日志记录器是唯一直接访问文件的东西。现在已经有很多框架(nlog、log4net、enterprise library)可以为您完成这些工作。

您可能想要查看。net Tracing。我更喜欢使用内置的TraceSource类,而不是使用第三方日志框架(如nlog)。我以前甚至会围绕nlog编写一个facade,但是有这么多依赖关系和这么多抽象层,只是为了写一条日志消息,这似乎相当愚蠢。

您可以在这里看到TraceSource的概述:http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx

这个想法是你把跟踪从监听中分离出来。在整个代码中,您可以添加跟踪调用,每个调用具有不同的日志级别(Error、Verbose、Debug)和不同的源。然后在应用程序配置中配置不同的侦听器。

<system.diagnostics>
    <sources>
      <source name="Source1" switchName="verboseSwitch">
        <listeners>
          <add name="console" />
        </listeners>
      </source>
      <source name="Source2" switchName="warningSwitch">
        <listeners>
          <add name="console" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="verboseSwitch" value="Verbose" />
      <add name="warningSwitch" value="Information" />
    </switches>
    <sharedListeners>
      <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false"/>
    </sharedListeners>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="console" />
      </listeners>
    </trace>
  </system.diagnostics>

public void MethodOne()
{
     TraceSource ts = new TraceSource("Source1");
     ts.TraceEvent(TraceEventType.Verbose, 0, "Called MethodOne");
     // do something that causes an error
     ts.TraceEvent(TraceEventType.Error, 0, "MethodOne threw an error");
}

在这里,MethodOne被设置为使用源"Source1"。Source1目前在上面配置为侦听任何Verbose和更高级别的内容。这意味着

Called MethodOne
MethodOne threw an error 

将同时写入控制台

public void MethodTwo()
{
     TraceSource ts = new TraceSource("Source2");
     ts.TraceEvent(TraceEventType.Verbose, 0, "Called MethodTwo");
     // do something that causes a error
     ts.TraceEvent(TraceEventType.Error, 0, "MethodTwo threw an error");
}

在这里,MethodTwo被配置为使用Source2,它只被设置为侦听Warning及以上。

因此,当代码运行时,输出将是
MethodTwo threw an error

允许你做的是控制你希望在程序的不同部分看到多少信息。也许,如果有一天您开始在某些库中看到错误,您可以将该库的跟踪源设置为verbose,现在可以看到所有调试信息,而不会被程序其他部分的数据所淹没。

我使用不同的侦听器来控制关键错误的流程。我有针对特定来源和特定错误级别的监听器,一旦有错误写入日志,它们就会给我发电子邮件。我不关心404错误,但我确实关心注册码中发生的任何事情,例如。

您有用于写入控制台/调试窗口的ConsoleTraceListenerFileLogTraceListener用于写入文件甚至EventLogTraceListener

您可以在这里看到内置侦听器的完整列表

然后是第三方侦听器,用于发送日志事件的电子邮件,存储在数据库中,写入Azure表存储等。

你当然可以用NLog这样的框架来完成所有这些。. net Trace方法是高性能的,并且在。net框架中广泛使用。我觉得你选它不会错的。