Отключение трассировки через app.config - PullRequest
18 голосов
/ 10 ноября 2010

Я пытаюсь использовать 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 и нахожу Как: настроить переключатели трассировки .Я добавляю элемент <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" должен отключить трассировку - по крайней мере, если вы затем выполните Как: создать иИнициализируйте переключатели трассировки , которые говорят вам добавить эту строку кода:

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

Это не имеет смысла для меня: я просто должен объявить экземпляр BooleanSwicth, чтобы иметь возможностьуправлять (отключить) трассировкой через файл .config?Мне нравится ... использовать ... объект где-нибудь?

В любом случае, я уверен, что где-то упустил нечто действительно очевидное.Пожалуйста, помогите.

Как отключить трассировку в app.config?

Ответы [ 6 ]

34 голосов
/ 10 ноября 2010

Я согласен с рекомендацией @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 автоматически проверит уровень сообщения (TraceEventType.Information) относительно настроенного уровня связанного коммутатора и определит, действительно ли сообщение должно быть записано.

Используя различные имена TraceSource для каждого типа, вы можете контролировать ведение журнала из этих классов по отдельности. Вы можете включить ведение журнала MyClass1 или отключить его, либо включить его, но вести его только в том случае, если уровень сообщения (TraceEventType) превышает определенное значение (возможно, только журнал «Предупреждение» и выше). В то же время, вы можете включить или отключить вход в MyClass2 или установить уровень, совершенно независимо от MyClass1. Все это включение / отключение / уровень происходит в файле app.config.

Используя файл app.config, вы также можете управлять всеми TraceSources (или группами TraceSources) таким же образом. Таким образом, вы можете настроить так, чтобы MyClass1 и MyClass2 контролировались одним и тем же коммутатором.

Если вы не хотите, чтобы 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» частью журнала вашего приложения на одном уровне, в то время как часть «Analysis» вашего приложения регистрируется на другом уровне (конечно, одна или обе части вашего приложения). можно настроить так, чтобы ведение журнала было отключено).

Вот часть файла app.config, который настраивает TraceSources и TraceSwitches:

<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 и один коммутатор, и вся регистрация будет происходить с одним уровнем управления (т. Е. Вы можете отключить всю регистрацию или сделать ее регистрацией на определенном уровне).

Кроме того, вы можете определить несколько TraceSources (и ссылаться на соответствующие TraceSources в вашем коде) и несколько Switch. Коммутаторы могут быть общими (то есть несколько источников могут использовать один и тот же коммутатор).

В конечном итоге, приложив немного больше усилий, чтобы теперь использовать TraceSources и ссылаться на соответствующим образом названные TraceSources в своем коде (т.е. определить имена TraceSource логически, чтобы вы могли иметь желаемую степень контроля над входом в приложение), вы получит значительную гибкость в долгосрочной перспективе.

Вот несколько ссылок, которые могут помочь вам с System.Diagnostics по мере продвижения вперед:

.net Рекомендации по диагностике?

Регистрация лучших практик

Каков наилучший подход к ведению журнала?

Имеет ли платформа .Net TraceSource / TraceListener что-то похожее на средства форматирования log4net?

В ссылках, которые я разместил, часто обсуждается «лучшая» структура ведения журналов. Я не пытаюсь убедить вас перейти от System.Diagnostics. Ссылки, как правило, содержат хорошую информацию об использовании System.Diagnostics, поэтому я разместил их.

Некоторые из размещенных мной ссылок содержат ссылку на Ukadc.Diagnostics . Это действительно классное дополнение для библиотеки System.Diagnostics, которое добавляет расширенные возможности форматирования, аналогично тому, что вы можете делать с log4net и NLog. Эта библиотека налагает зависимость только для конфигурации на ваше приложение, а не код или ссылочную зависимость.

3 голосов
/ 10 ноября 2010

Вы не отключаете трассировку глобально таким образом.

Вы должны
1) объявить переключатель и установить его значение:

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

2) связать этот переключательс TraceSource, который вы используете:

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

Итак, все, что вы пишете через TraceSource с именем «MySource», фильтруется в соответствии со значением переключателя.

Если вы используете статические методы, такие как Trace.Write,Я полагаю, что вы вообще не можете использовать переключатели, потому что нет TraceSource для применения фильтра.
Если вы хотите отключить трассировку статическими методами, просто удалите все слушатели: <listeners> <clear/> </listeners>.

1 голос
/ 30 октября 2012

Позднее присоединение с краткой сноской о app.config, на случай, если это спасет пару дней от жизни кого-то там:

Предположим, у вас есть запускаемый (.exe) проект A, содержащий класс A, который использует проект B (.dll), содержащий класс B.

ClassB, в свою очередь, использует новый экземпляр TraceSource ("classB"). Чтобы настроить его, вам нужно изменить app.config или projectA. Настройка app.config проектаB ни к чему не приведет.

Также обратите внимание, что размещение

<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>
1 голос
/ 10 ноября 2010

Проверяйте состояние dataSwitch всякий раз, когда вам нужно войти в систему, как:

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

Однако, это довольно неприятно, когда нужно ставить эти проверки везде.Это причина, по которой вы не хотите просто удалять TraceListener из коллекции слушателей в app.config?

Кроме того, я бы исследовал использование трассировки .NET 2.0+, которая включает TraceSource.Новый (er) материал предлагает гораздо более высокую степень конфигурации, и вы можете найти его более подходящим.

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

1 голос
/ 10 ноября 2010

Это атрибут 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" />

0 голосов
/ 12 июня 2019

Попробуйте это простое решение.В приведенном ниже примере «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>
...