通过app.config关闭跟踪

时间:2010-11-10 12:21:59

标签: c# .net vb.net configuration trace

我正在尝试使用System.Diagnostics做一些非常基本的日志记录。我想我会使用框中的内容,而不是像Log4Net或EntLib那样使用额外的依赖。

我已经全部成立,追踪工作非常好。代码段:

Trace.TraceInformation("Hello World")

App.config中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="TraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Trace.log" traceOutputOptions="DateTime" />
        <remove name="Default" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

我的小“Hello World”很好地显示在我的Trace.log文件中。但现在我想关闭跟踪,所以我深入了解MSDN并找到How to: Configure Trace Switches 。我添加了<switches>元素,现在我的app.config看起来像这样:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="TraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Trace.log" traceOutputOptions="DateTime" />
        <remove name="Default" />
      </listeners>
    </trace>
    <switches>
      <add name="Data" value="0" />
    </switches>
  </system.diagnostics>
</configuration>

value="0"应该关闭跟踪 - 至少如果您按照How to: Create and Initialize Trace Switches进行跟踪,它会告诉您添加以下代码行:

Dim dataSwitch As New BooleanSwitch("Data", "DataAccess module")

这对我没有意义:我只需要通过.config文件声明BooleanSwicth的实例能够管理(禁用)跟踪?我应该喜欢...... 使用 ...某个地方的对象?

无论如何,我确信我错过了一些非常明显的东西。请帮忙。

如何在app.config中关闭跟踪?

6 个答案:

答案 0 :(得分:34)

我同意@Alex Humphrey建议尝试使用TraceSources。使用TraceSources,您可以更好地控制日志记录/跟踪语句的执行方式。例如,您可以使用以下代码:

public class MyClass1
{
  private static readonly TraceSource ts = new TraceSource("MyClass1");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

public class MyClass2
{
  private static readonly TraceSource ts = new TraceSource("MyClass2");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

TraceSource.TraceEvent调用将根据相关Switch的配置级别自动检查消息级别(TraceEventType.Information),并确定是否应该实际写出消息。

通过为每种类型使用不同名称的TraceSource,您可以单独控制这些类的日志记录。您可以启用MyClass1日志记录,也可以禁用它,或者您可以启用它,但只有在消息级别(TraceEventType)大于某个值(可能只记录“警告”和更高级别)时才进行日志记录。同时,您可以打开或关闭MyClass2中的日志记录或设置为一个级别,完全独立于MyClass1。所有这些启用/禁用/级别的东西都发生在app.config文件中。

使用app.config文件,您也可以以相同的方式控制所有TraceSource(或TraceSources组)。因此,您可以进行配置,以便MyClass1和MyClass2都由同一个Switch控制。

如果您不希望每种类型都有不同名称的TraceSource,您可以在每个类中创建相同的TraceSource:

public class MyClass1
{
  private static readonly TraceSource ts = new TraceSource("MyApplication");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

public class MyClass2
{
  private static readonly TraceSource ts = new TraceSource("MyApplication");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

这样,您可以使应用程序中的所有日志记录发生在同一级别(或者关闭或使用相同的TraceListener,或其他任何方式)。

您还可以将应用程序的不同部分配置为可独立配置,而无需在每种类型中定义唯一TraceSource的“麻烦”:

public class Analysis1
{
  private static readonly TraceSource ts = new TraceSource("MyApplication.Analysis");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

public class Analysis2
{
  private static readonly TraceSource ts = new TraceSource("MyApplication.Analysis");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

public class DataAccess1
{
  private static readonly TraceSource ts = new TraceSource("MyApplication.DataAccess");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

public class DataAccess2
{
  private static readonly TraceSource ts = new TraceSource("MyApplication.DataAccess");

  public DoSomething(int x)
  {
    ts.TraceEvent(TraceEventType.Information, "In DoSomething.  x = {0}", x);
  }
}

通过这种方式对您的课程进行检测,您可以将应用程序日志中的“DataAccess”部分设置为一个级别,而应用程序的“分析”部分则在不同级别(当然,应用程序的任一部分或两部分)可以配置,以便禁用日志记录。)

以下是配置TraceSources和TraceSwitches的app.config文件的一部分:

<system.diagnostics>
  <trace autoflush="true"></trace>
  <sources>
    <source name="MyClass1" switchName="switch1">
      <listeners>
        <remove name="Default"></remove>
        <add name="console"></add>
      </listeners>
    </source>
    <source name="MyClass2" switchName="switch2">
      <listeners>
        <remove name="Default"></remove>
        <add name="console"></add>
      </listeners>
    </source>
  </sources>
  <switches>
    <add name="switch1" value="Information"/>
    <add name="switch2" value="Warning"/>
  </switches>
  <sharedListeners>
    <add name="console"
         type="System.Diagnostics.ConsoleTraceListener">
    </add>
    <add name="file"
         type="System.Diagnostics.TextWriterTraceListener"
         initializeData="trace.txt">
    </add>
  </sharedListeners>
</system.diagnostics>

正如您所看到的,您可以配置单个TraceSource和单个Switch,并且所有日志记录都可以通过单一级别的控制进行(即您可以关闭所有日志记录或使其在特定级别进行日志记录)。

或者,您可以定义多个TraceSource(并在代码中引用相应的TraceSource)和多个Switch。可以共享交换机(即多个TraceSource可以使用相同的交换机)。

最后,通过现在花费更多精力来使用TraceSources并在代码中引用适当命名的TraceSources(即逻辑定义TraceSource名称,以便您可以对应用程序中的日志记录进行所需的控制程度),从长远来看,将获得显着的灵活性。

以下是一些可能会帮助您使用System.Diagnostics的链接:

.net Diagnostics best practices?

Logging best practices

What's the best approach to logging?

Does the .Net TraceSource/TraceListener framework have something similar to log4net's Formatters?

在我发布的链接中,经常讨论“最佳”日志框架。我并不想说服您从System.Diagnostics更改。链接也往往有关于使用System.Diagnostics的良好信息,这就是我发布它们的原因。

我发布的一些链接包含指向Ukadc.Diagnostics的链接。这是System.Diagnostics的一个非常酷的库添加库,它增加了丰富的格式化功能,类似于你可以用log4net和NLog做的。此库对您的应用程序施加仅限配置依赖性,而不是代码或引用依赖项。

答案 1 :(得分:3)

您不会以这种方式全局关闭跟踪。

你必须 1)声明一个开关并设置其值:

<switches>
  <add name="MySwitch" value="Information"/>
</switches>

2)将此开关与您使用的TraceSource相关联:

<sources>
  <source name="MySource" switchName="MySwitch"/>
</source>

因此,无论您通过名为“MySource”的TraceSource写入的内容都会根据切换值进行过滤。

如果您使用Trace.Write之类的静态方法,我想,根本不能使用开关,因为没有TraceSource来应用过滤器。
如果要通过静态方法关闭跟踪,只需删除所有侦听器:<listeners> <clear/> </listeners>

答案 2 :(得分:1)

是源节点的switchValue属性:

<system.diagnostics>
<sources>
  <source name="System.ServiceModel"
          switchValue="Off"
          propagateActivity="true">
    <listeners>
      <add name="traceListener"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData= "somePath" />
    </listeners>
  </source>
</sources>
<trace autoflush="true" />

答案 3 :(得分:1)

根据需要,在需要登录时检查dataSwitch的状态:

http://msdn.microsoft.com/en-us/library/aa984285%28v=VS.71%29.aspx

然而,这是非常讨厌的,不得不把这些检查放在任何地方。他们是不是只想从app.config中的侦听器集合中删除TraceListener的原因?

除此之外,我还会调查使用包含TraceSource的.NET 2.0+跟踪内容。新的(呃)东西提供了更高程度的配置,你可能会发现它更合适。

http://msdn.microsoft.com/en-us/library/ms228993.aspx

答案 4 :(得分:1)

最近加入了一个关于app.config的快速脚注,如果这样可以节省几天人员的生命:

假设你有一个包含classA的启动(.exe)projectA,它使用包含classB的projectB(.dll)。

ClassB又使用了一个新的TraceSource(“classB”)实例。要进行配置,您需要修改app.config或projectA。调整projectB的app.config不会导致任何问题。

还要注意

的位置
<system.diagnostics>

app.config中的部分如果放在部分之前似乎会导致问题:

<configSections>

或在以下部分之后:

<userSettings>

至少在我的情况下,当我试图将它放在我项目的app.config中的这些位置时,我遇到了错误。适合我的布局是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
         ...config sections here if any...
     </configSections>
     <system.diagnostics>
         <trace autoflush="true"/>
         <sources>
             <source name="classB"
                 switchName="mySwitch"
                 switchType="System.Diagnostics.SourceSwitch" >
                 <listeners>
                    <clear/>
                    <add name="textwriterListener"
                         type="System.Diagnostics.TextWriterTraceListener"
                         initializeData="ClassBLog.txt"
                         traceOutputOptions="DateTime" />
                 </listeners>
             </source>
          </sources>
          <switches>
             <add name="mySwitch" value="Verbose" />
          </switches>
     </system.diagnostics>
     <runtime>
         ...runtime sections here if any...
     </runtime>
     <userSettings>
         ...usersettings sections here if any...
     </userSettings>
 </configuration>

答案 5 :(得分:0)

尝试这个简单的解决方案。在下面的示例中,“ SomeNoisyLibrary”在日志中堆满了许多无用的条目。我们用“条件成立”

对其进行过滤

https://github.com/NLog/NLog/wiki/When-Filter

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        internalLogFile="../log/MyApplication.log"
        autoReload="true" throwExceptions="true">

  <targets async="true">
    <target xsi:type="File" 
            name="file"
            layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message} ${exception:format=ToString}"
            fileName="../log/MyApplication.${processid}.${shortdate}.log" keepFileOpen="false"
            maxArchiveFiles="10"
            archiveAboveSize="10024000"
            archiveEvery="Day"
            />
    <target xsi:type="ColoredConsole" 
            name="console" 
            layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message}${exception:format=ToString}" />
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="file,console">
      <filters defaultAction='Log'>
        <when condition="equals('${logger}','SomeNoisyLibrary')" action="Ignore" />
      </filters>
    </logger>
  </rules>
</nlog>