Подтвердить что ты не робот

Отключение трассировки через app.config

Я пытаюсь использовать 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?

4b9b3361

Ответ 1

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

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

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

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

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

Протоколы ведения журналов

Каков наилучший способ ведения журнала?

Имеет ли структура .Net TraceSource/TraceListener нечто похожее на Formatters log4net?

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

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

Ответ 2

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

Вам нужно 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>.

Ответ 3

Это атрибут switchValue источника node:

<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" />

Ответ 4

Проверяйте состояние 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

Ответ 5

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

Предположим, что у вас есть startup (.exe) projectA, содержащий классA, который использует projectB (.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>

Ответ 6

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