8

VB.Net アプリケーションの初期化をログに記録するために使用する TraceSource オブジェクトがあります。いくつかの TraceListeners がアタッチされています。

  • ConsoleTraceListener
  • TextWriterTraceListener
  • EventLogTraceListener

最初の 2 つについては、エントリの出力を「生」にする必要があります。つまり、標準ヘッダーなしです。

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 には次の書き込みオプションがあります。

  • 書く()
  • 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

これは機能しているようですが、MicrosoftのTraceListener.TraceEvent Methodに関するドキュメントには次のように書かれています。

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 はまったく必要ないことに気付きました。しかし、それはまた、独自のフィルタリングとスイッチングのメカニズムを実装しなければならないことも意味します (しかし、それは、私が望むように動作させるために支払っても問題ないかもしれません)。

4

3 に答える 3

2

使用できるフォーマット可能なリスナーを持つ別の同様のプロジェクトはEssential Diagnosticsです。これは、実際には Ukadc.Diagnostics に触発されたものです。

ただし、外部依存関係を望まないことを示しましたが、フレームワークの一部を書き直さなくてもいくつかのオプションがあります。

(A) TraceSource を書き直すのではなく、.NET Framework で設計された拡張ポイントは、独自の TraceListener を作成することです。

独自のトレース リスナー「ConsoleWithoutPrefixListener」および「FileWithoutPrefixListener」を作成する場合は、TraceEvent() メソッドをオーバーライドして、メッセージを TraceWrite() に転送する (そしてプレフィックスを削除する) ことができます。

実際、ConsoleTraceListener も TextWriterTraceListener もシールされていないため、それらを継承して、TraceEvent() メソッド (およびコンストラクター) を 1 行オーバーライドするだけで機能するようになると思います。

(B) もう 1 つの方法は、EventLogTraceListener をソースに対して構成したままにし、他の 2 つのリスナーを (トレース ソースではなく) 下に構成することです。

これの欠点は、コードで毎回 2 回ログを記録する必要があることです。

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

プレフィックス付きのメッセージとプレフィックスなしのメッセージを書きたい場合は、2 つのトレース ソースが必要になります。

次に、ラッパーでソース A (3 つすべて) またはソース B + Trace 静的メソッドに書き込みます。

(C) 個人的には、イベント ログへの書き込みにトレースを使用しないことをお勧めします。問題がイベント ログに書き込むのに十分なほど重要である場合、通常、ユーザーが構成によってそれらをオフにできるようにしたくありません。

この場合、ラッパーはイベント ログ (EventLog.WriteEntry など) に直接書き込み、コードはファイルとコンソールのトレース ソースおよび/または Trace 静的メソッドに書き込みます。

イベント ログへの書き込みを正しく機能させるには、アクセス許可を考慮する必要があることに注意してください。イベント ログ ソースを作成するには、管理者として実行する必要があります。開発者として、通常は管理者権限を持っているので、そうでない人のコンテキストでこれを適切にテストする必要があります。

また、管理者権限が必要なのは最初の作成のみであり、これは最初のメッセージを書き込むときに自動的に行われるため、開発者管理者として既に行っている場合は、テストするクリーンなマシンを見つける必要があることに注意してください。

このため、通常、コードの一部として EventLogInstaller が必要です。これは、インストール中にイベント ログ ソースを作成する InstallUtil (または同等の MSI など) によって実行されます (インストール管理者によって行われるため)。次に、プログラムを実行すると、ソースが存在します。

では、これはトレースへの書き込みと何の関係がありますか? 構成で EventLogTraceListener を構成するだけの場合、通常のユーザーには機能しません。イベントをソースに (initializeData 属性で) 書き込もうとし、ソースを作成しようとします。管理者として実行されていない場合は失敗します。

イベント ソースのインストーラーを追加した場合でも、誰かが構成ファイルを変更すると問題が発生します。

このため、EventLogInstaller と EventLog の両方をコードで直接作成して、名前が一致し、トレース インフラストラクチャを経由しないようにすることをお勧めします。

于 2013-04-21T07:06:07.777 に答える
1

@Slyの回答に触発された、これに対する私の完全な解決策を次に示します。

TraceEvent()継承できるメソッドを使用するときにヘッダー情報を抑制するには、ConsoleTraceListeneror 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);
        }

    }
}

注: メソッドをオーバーライドしようとしたときに TraceEvent 、この時点でヘッダー情報がメッセージ文字列に追加されていないことに気付きました。 代わりに、他のノックオン効果がないように見える呼び出しを沈黙させることを選択しましたが、少し「ハック」に感じます。誰かが「よりクリーンなアプローチ」を持っている場合、私はそれを受け入れます。Write(string)

この顧客リスナーを使用する構成は、次のようになります。

  <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>
于 2015-01-14T13:43:45.463 に答える
0

codeplexのUkadc.Diagnosticsプロジェクトを見てください。これはSystem.Diagnosticsのアドオンであり、ロギング/トレース出力を好きなようにフォーマットする機能を提供します(log4netおよびNLogで実行できるのと同様)。構成を通じて使用するため、コードがライブラリに直接依存することはありません。ライブラリには、フォーマット用の構成可能なオブジェクトと、フォーマットを利用するために必要なカスタムTraceListenersが付属しています。このライブラリを使用すると、独自のフォーマット「トークン」と独自のTraceListenerを簡単に作成することもできます。

たとえば、次のようなフォーマットステートメントを使用するようにUkadc.DiagnosticsConsoleTraceListenerを構成できます。

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

ログに記録されるすべてのメッセージにより、日付/時刻、ソース名、イベントタイプ、およびメッセージが発生します。

試してみてください、きっと気に入ると思います。私はそれを自分で使用し(主にプロトタイピング用であり、「実際の」製品用ではありません)、成功を収めています。

一部のトークン(DateTimeなど)では、タイプに適した標準形式を適用することもできます(たとえば、DateTimeの場合、日付/時刻を書き込む形式を指定できます)。

Ukadc.Diagnosticsに付属のファイルトレースリスナーでは、トークンシステムを使用してファイル名を指定することもできます。

于 2010-10-31T19:40:41.597 に答える