C#“缓存调试日志”

时间:2011-08-03 00:12:25

标签: c# debugging logging caching

我想在这里向C#专家征求意见。我的调试日志有问题。我有一个简单的类,只打开一个文件,写下提供的字符串并再次关闭文件。但是,有时我需要在使用多线程时使用此调试日志。从而麻烦来了。我不能多次打开文件,所以我收到异常,因为我只是尝试再次打开锁定的文件。为此,我希望有一个类似“缓存的调试日志”的东西,它可以防止这种异常。有没有简单的方法来实现这个?非常感谢。

3 个答案:

答案 0 :(得分:2)

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

修改

当然,最有利的做法是开始使用已经存在这些东西的预先存在的日志框架。我推荐NLog,虽然log4net也是一个有价值的竞争者。

答案 1 :(得分:1)

这通常是通过从代码的所有部分调用的单例记录器来完成的;记录器是唯一直接访问文件的东西。有许多框架已经存在(nlog,log4net,企业库),可以为您完成此任务。

答案 2 :(得分:1)

您可能想要查看.NET跟踪。我更喜欢使用内置的TraceSource类和使用像nlog这样的第三方日志框架。我曾经走过甚至围绕nlog写一个立面的道路,但是那么拥有如此多的依赖关系和如此多的抽象层似乎相当愚蠢,只是为了写一条日志消息。

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

这个想法是你将追踪与听力区分开来。在整个代码中,您可以添加跟踪调用,每个调用具有不同的日志级别(错误,详细,调试)和不同的源。在应用程序配置中,然后配置不同的侦听器。

<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目前在上面配置为侦听任何详细和更高版本。所以这意味着

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,它仅设置为侦听警告及以上。

因此,当代码运行时,输出将是

MethodTwo threw an error

这使您可以控制您希望在程序的不同部分看到多少信息。也许如果有一天你开始在某个库中看到错误,你可以将该库的跟踪源变为详细,现在可以查看所有调试信息,而不会被来自程序其他部分的数据所淹没。

我使用这样的不同监听器来控制关键错误的流动。我有一些侦听器用于某些来源和某些错误级别,这些错误级别会在错误写入日志时向我发送电子邮件。我不关心404错误,但我确实关心注册代码中发生的任何事情,例如。

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

您可以查看内置侦听器的完整列表here

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

您当然可以使用像NLog这样的框架来完成所有这些工作。 .NET Trace方法具有高性能,可在整个.NET Framework中使用。你选择它不会出错恕我直言。