.Net: Как подавить заголовок TraceSource («SourceName TraceEventType: Id:»)? - PullRequest
8 голосов
/ 31 октября 2010

У меня есть объект TraceSource, который я использую для регистрации инициализации приложения VB.Net.К нему подключено несколько TraceListener:

  • ConsoleTraceListener
  • TextWriterTraceListener
  • EventLogTraceListener

Для первых двух я хочу, чтобы вывод записи был«raw» - то есть без стандартного заголовка:

SourceName TraceEventType: Id :

Я реализовал обертку, которая делает это, когда для TraceEventType установлено значение Verbose:

If _buffer.EventType = TraceEventType.Verbose Then
    For Each listener As TraceListener In _traceSource.Listeners
        listener.Write(_buffer.Text)
    Next
Else
    _traceSource.TraceEvent(_buffer.EventType, id, _buffer.Text)
End If

Я мог бы сделать это для всей трассировки, но тогда все записи в EventLog будут перечислены с Level = Information.Поэтому я хочу иметь возможность указать серьезность сообщения трассировки, но я не могу найти какой-либо метод в TraceSource или TraceListeners, который позволил бы мне сделать это.Насколько я могу судить, TraceListener имеет следующие параметры для записи в него:

  • Write ()
  • WriteLine ()
  • TraceData ()
  • TraceEvent ()
  • TraceTransfer ()

Последние 3 позволяют предоставить TraceEventType (который правильно помечает записи EventLog, но в результате вывод на консоль и в файл журналазатем включает префиксы и заканчивается следующим образом (например):

Bootstrapper Warning: 0 : Failed to validate assembly

Есть ли способ переопределить, как ConsoleTraceListener и TextWriterTraceListener форматируют свой вывод, чтобы не включать этот заголовок, в то время какв то же время возможность пометить записи с помощью TraceEventType (для EventLog)?

Это лучшее, что я придумал до сих пор:

For Each listener As TraceListener In _traceSource.Listeners
    If listener.GetType Is GetType(ConsoleTraceListener) OrElse listener.GetType Is GetType(TextWriterTraceListener) Then
        listener.Write(_buffer.Text)
    Else
        listener.TraceEvent(Nothing, _traceSource.Name, _buffer.EventType, id, _buffer.Text)
    End If
Next

Это работает, но в документации по методу TraceListener.TraceEvent от Microsoft говорится:

Important: This method is not intended to be called directly by application code but by members of the Debug, Trace, and TraceSource classes to write trace data to output.

.. поэтому я не уверен, что это хорошочто делать?

Редактировать:

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

Ответы [ 3 ]

2 голосов
/ 21 апреля 2013

Еще один похожий проект, в котором можно использовать форматируемые прослушиватели, которые вы можете использовать, это Essential Diagnostics , который изначально был вдохновлен Ukadc.Diagnostics.

Однако вы указали, что неЯ не хочу внешних зависимостей, но у вас все еще есть несколько вариантов без переписывания частей Framework:

(A) Вместо того, чтобы переписывать TraceSource, разработанная точка расширения в .NET Framework заключается в написании собственного TraceListener.

Если вы пишете собственные прослушиватели трассировки «ConsoleWithoutPrefixListener» и «FileWithoutPrefixListener», то вы можете переопределить методы TraceEvent (), чтобы просто переслать сообщение в TraceWrite () (и удалить префиксы).

На самом деле ни ConsoleTraceListener, ни TextWriterTraceListener не запечатаны, поэтому я думаю, что вы могли бы наследовать их и заставить работать с переопределением на одну строку метода TraceEvent () (плюс конструктор).

(B) Другойальтернативой будет оставить EventLogTraceListener настроен по отношению к источнику, но сконфигурирован для двух других слушателей (а не источника трассировки).

Недостаток этого заключается в том, что в вашем коде вам необходимо каждый раз дважды регистрироваться, например:

_traceSource.TraceEvent (_buffer.EventType, id, _buffer.Text) Trace.TraceWrite (_buffer.Text)

Если вы хотите написать несколько сообщений с префиксами, а некоторые без, вам понадобятся два источника трассировки: один, который будетнастроен для всех трех прослушивателей, а один - только для прослушивателя журнала событий.

Затем в вашей оболочке либо пишите в источник A (все три), либо в источник B + статические методы трассировки.

(C) Лично я бы не советовал использовать трассировку для записи в журнал событий - если проблемы достаточно важны для записи в журнал событий, вы обычно не хотите, чтобы пользователь мог отключить их через конфигурацию.

В этом случае ваша оболочка записывает в журнал событий напрямую (EventLog.WriteEntry или что-то еще), а затем ваш код записывает в траСтатические методы источника и / или трассировки для файла и консоли.

Обратите внимание, что для правильной работы записи в журнал событий необходимо учитывать разрешения.Для создания источника журнала событий вы должны быть с правами администратора .Как разработчик, вы, вероятно, обычно имеете права администратора, поэтому вам нужно правильно проверить это в контексте того, кто этого не делает.

Также обратите внимание, что только начальное создание требует прав администратора, и этоавтоматически выполняется при написании первого сообщения, поэтому, если вы уже сделали это как администратор разработчика, вам нужно найти чистую машину для тестирования.

Из-за этого, как правило, вам нужно иметь EventLogInstaller как частьвашего кода, который запускается с помощью InstallUtil (или эквивалентного MSI или любого другого), который создает источник журнала событий во время установки (поскольку установка выполняется администратором).Затем, когда программа запускает исходный код, существует.

Итак, как это связано с записью в трассировку? Хорошо, если единственное, что вы делаете, это конфигурируете EventLogTraceListener в вашей конфигурации, то для обычных пользователей этоне сработает;он попытается записать события в источник (в атрибуте initializeData), который затем попытается создать источник, и, если он не запущен от имени администратора, произойдет сбой.

Если вы добавите установщик для источника события, тоу вас все еще есть проблема, если кто-то изменяет конфигурационный файл.

Из-за этого я бы рекомендовал, чтобы и EventLogInstaller, и EventLog создавались непосредственно в коде, чтобы гарантировать совпадение имен, а не проходить через инфраструктуру трассировки..

1 голос
/ 14 января 2015

Вот мое полное решение, вдохновленное ответом @ Sly .

Для подавления информации заголовка при использовании метода TraceEvent(), который можно унаследовать от ConsoleTraceListenerили TextWriterTraceListener (или любой другой вкус слушателя), например, так:

namespace Custom.Lib {
    public class ConsoleTraceListener : System.Diagnostics.ConsoleTraceListener {

        // overridding this method here will suppress header information
        // your TraceEvent() messages will still reach the listener
        public override void Write(string message) {
            //base.Write(message);
        }

    }
}

NB При попытке переопределить метод TraceEvent я заметил, что информация заголовкане был добавлен в строку сообщения на этом этапе.Вместо этого я решил замолчать на звонок Write(string) , который, похоже, не имеет каких-либо других эффектов, но он выглядит немного "хакерским", если у кого-то есть "более чистый подход" I "м. открыта для него.

Конфигурация для использования этого прослушивателя клиента должна выглядеть примерно так:

  <system.diagnostics>
    <sources>
      <source name="AppTrace" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <add name="consoleListener"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Information"/>
    </switches>
    <sharedListeners>
      <add name="consoleListener" type="Custom.Lib.ConsoleTraceListener, Custom.Lib" initializeData=""/>
    </sharedListeners>
  </system.diagnostics>
0 голосов
/ 31 октября 2010

Посмотрите на проект Ukadc.Diagnostics на codeplex. Это дополнение к System.Diagnostics, которое дает вам возможность форматировать выходные данные журнала / трассировки так, как вам нравится (аналогично тому, что вы можете делать с log4net и NLog). Вы используете его через конфигурацию, поэтому ваш код не будет зависеть от библиотеки. Библиотека поставляется с настраиваемыми объектами для форматирования и пользовательскими TraceListener, необходимыми для использования преимуществ форматирования. Библиотека также позволяет вам легко создавать собственные "токены" форматирования и собственный TraceListener.

Например, вы можете настроить Ukadc.Diagnostics ConsoleTraceListener для использования оператора форматирования примерно так:

{DateTime} {Source} {EventType} {Message}

Каждое зарегистрированное сообщение будет содержать дату / время, имя источника, тип события и сообщение.

Попробуйте, я думаю, вам понравится. Я сам использовал его (в основном для создания прототипов, а не для «настоящего» продукта) и добился хорошего успеха.

Обратите внимание, что для некоторых токенов (например, DateTime) вы также можете применять стандартные форматы, соответствующие типу (например, для DateTime вы можете указать формат, в котором должны быть записаны дата / время).

Прослушиватель трассировки файлов, который поставляется с Ukadc.Diagnostics, также позволяет указывать имя файла с помощью системы токенов.

...