DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

TraceSourceを使用してトレースする、ログに書き込む

注意:ここで紹介する方法は、.NET Framework 2.0以降で有効です。それ以外では、こちらこちらのように、TraceとDebugを使用するようにします。

ここでは、.NET Framework 2.0から追加されたTraceSourceクラスを使ってトレースする方法を紹介します。.NET Framework 1.1以前は、こちらこちらのように、TraceとDebugを使用してトレースを行いましたが、.NET Framework 2.0ではTraceSourceを使用したトレースが推奨されています。

早速ですが、TraceSourceを使った簡単な例を示します。以下のコードでは、Button1をクリックしたときに、指定したメッセージがVisual Studioの出力ウィンドウに表示されます。

VB.NET
コードを隠すコードを選択
'TraceSourceの作成
Private Shared appTrace As New System.Diagnostics.TraceSource("MainTraceSource")
'次のようにソースレベルを指定して作成することもできる
'指定しないと、Offになる
'Private Shared appTrace As New System.Diagnostics.TraceSource( _
'    "MainTraceSource", System.Diagnostics.SourceLevels.Error)

'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles Button1.Click
    'ソースレベルを変更する
    'Error以上のイベントが通過されるようにする
    appTrace.Switch.Level = System.Diagnostics.SourceLevels.Error

    'Warningイベントを書き込む
    'ソースレベルがErrorなので、出力されない
    appTrace.TraceEvent(System.Diagnostics.TraceEventType.Warning, 0, "警告")

    'Criticalイベントを書き込む
    'ソースレベルがErrorなので、出力される
    appTrace.TraceEvent(System.Diagnostics.TraceEventType.Critical, 1, "重大")

    'フラッシュする
    appTrace.Flush()
End Sub
C#
コードを隠すコードを選択
//TraceSourceの作成
private static System.Diagnostics.TraceSource appTrace =
    new System.Diagnostics.TraceSource("MainTraceSource");
//次のようにソースレベルを指定して作成することもできる
//指定しないと、Offになる
//private static System.Diagnostics.TraceSource appTrace =
//    new System.Diagnostics.TraceSource("TraceSource1",
//    System.Diagnostics.SourceLevels.Error);

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, EventArgs e)
{
    //ソースレベルを変更する
    //Error以上のイベントが通過されるようにする
    appTrace.Switch.Level = System.Diagnostics.SourceLevels.Error;

    //Warningイベントを書き込む
    //ソースレベルがErrorなので、出力されない
    appTrace.TraceEvent(System.Diagnostics.TraceEventType.Warning, 0, "警告");

    //Criticalイベントを書き込む
    //ソースレベルがErrorなので、出力される
    appTrace.TraceEvent(System.Diagnostics.TraceEventType.Critical, 1, "重大");

    //フラッシュする
    appTrace.Flush();
}

上記のコードを実行すると、Visual Studioの出力ウィンドウに次のように出力されます。

MainTraceSource Critical: 1 : 重大

上記のコードでは、TraceSourceのスイッチレベルをErrorにしています。これにより、CriticalかErrorのイベントしか出力されなくなります。つまり上記のように、Warningでは表示されず、Criticalでは表示されます。

TraceSourceのスイッチレベルに指定できるSourceLevels列挙体のメンバの意味は、次のようなものです(ヘルプの「SourceLevels 列挙体」より抜粋)。

SourceLevels列挙体のメンバ名 説明
ActivityTracing Stop、Start、Suspend、Transfer、および Resume の各イベントを通過させます。
All すべてのイベントを通過させます。
Critical Critical イベントのみを通過させます。
Error Critical イベントおよび Error イベントを通過させます。
Information Critical、Error、Warning、および Information の各イベントを通過させます。
Off いずれのイベントも通過させません。
Verbose Critical、Error、Warning、Information、および Verbose の各イベントを通過させます。
Warning Critical、Error、および Warning の各イベントを通過させます。

TraceEventメソッドの第1引数に指定できるTraceEventType構造体のメンバの意味は、次のようなのもです(ヘルプの「TraceEventType 列挙体」からの抜粋)。

TraceEventType列挙体のメンバ 説明
Critical 致命的なエラーまたはアプリケーションのクラッシュ。
Error 回復可能なエラー。
Information 情報メッセージ。
Resume 論理演算の再開。
Start 論理演算の開始。
Stop 論理演算の停止。
Suspend 論理演算の中断。
Transfer 相関 ID の変更。
Verbose トレースのデバッグ。
Warning 重大でない問題。
補足:TraceEventメソッドの第2引数に指定する数字は、イベントのIDです。ここで指定できる数字の最大値は65,535です。それ以上を指定すると、65,535になります。
補足:イベントの種類を"Information"、IDを"0"としてメッセージを書き込むには、TraceEventメソッドの代わりにTraceInformationを使うと便利です。
また、イベントの種類を"Transfer"としてTraceEventメソッドを呼び出す代わりに、TraceTransferメソッドを使うこともできます。

リスナを追加する

トレースソースで使用されるリスナは、デフォルトでDefaultTraceListenerです。トレースソースにリスナを追加する方法は、「TraceやDebugのWriteメソッドでファイルに出力する」で紹介している方法とほぼ同じです。リスナに関する簡単な説明や、使用できるリスナの種類等もそちらで説明いています。

以下にTextWriterTraceListenerを追加し、テキストファイルに出力する例を示します。

VB.NET
コードを隠すコードを選択
'TraceSourceの作成
Private Shared appTrace As New System.Diagnostics.TraceSource("MainTraceSource")

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    'DefaultTraceListenerが必要なければ削除する
    appTrace.Listeners.Remove("Default")

    '出力先ファイルを C:\test.txt、名前を LogFile として
    'TextWriterTraceListenerオブジェクトを作成
    Dim twtl As New System.Diagnostics.TextWriterTraceListener( _
        "C:\test.txt", "LogFile")
    'リスナコレクションに追加する
    appTrace.Listeners.Add(twtl)
End Sub
C#
コードを隠すコードを選択
//TraceSourceの作成
private static System.Diagnostics.TraceSource appTrace =
    new System.Diagnostics.TraceSource("MainTraceSource");

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //DefaultTraceListenerが必要なければ削除する
    appTrace.Listeners.Remove("Default");

    //出力先ファイルを C:\test.txt、名前を LogFile として
    //TextWriterTraceListenerオブジェクトを作成
    System.Diagnostics.TextWriterTraceListener twtl =
        new System.Diagnostics.TextWriterTraceListener(
            "C:\\test.txt", "LogFile");
    //リスナコレクションに追加する
    appTrace.Listeners.Add(twtl);
}

リスナ毎にスイッチレベルを指定する

通常は、TraceSource.Switch.Levelで指定されたレベルに応じて、TraceSourceに追加されているリスナがメッセージを出力するかしないか制御されます。しかし、リスナ毎に別のレベルを設定したい場合もあるでしょう。そのような時は、リスナのFilterプロパティにEventTypeFilterオブジェクトを設定します。

ただし、はじめにTraceSource.Switch.Levelで指定されたレベルを通過したイベントが、リスナのFilterでさらに審査されるという方式ですので、リスナのFilterがTraceSource.Switch.Levelよりも低いレベルでは意味がありません。完全にそれぞれのリスナのFilterによって判断されるようにするには、TraceSource.Switch.LevelにAllを指定すればよいでしょう。

"Default"リスナのレベルをErrorにする例を以下に示します。

VB.NET
コードを隠すコードを選択
Private Shared appTrace As New System.Diagnostics.TraceSource("MainTraceSource")

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
        Handles MyBase.Load
    'ソースレベルを変更する
    'すべてのイベントが通過されるようにする
    appTrace.Switch.Level = System.Diagnostics.SourceLevels.All

    'DefaultリスナのレベルをErrorにする
    appTrace.Listeners("Default").Filter = _
        New System.Diagnostics.EventTypeFilter( _
            System.Diagnostics.SourceLevels.Error)
End Sub
C#
コードを隠すコードを選択
//TraceSourceの作成
private static System.Diagnostics.TraceSource appTrace =
    new System.Diagnostics.TraceSource("MainTraceSource");

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, EventArgs e)
{
    //ソースレベルを変更する
    //すべてのイベントが通過されるようにする
    appTrace.Switch.Level = System.Diagnostics.SourceLevels.All;

    //DefaultリスナのレベルをErrorにする
    appTrace.Listeners["Default"].Filter =
        new System.Diagnostics.EventTypeFilter(
            System.Diagnostics.SourceLevels.Error);
}

アプリケーション構成ファイルに設定を記述する

これまではTraceSourceの作成、設定の変更、リスナの追加などすべてコードで行いましたが、アプリケーション構成ファイルに記述することによっても可能です。むしろ、こちらの方法が推奨されています。なお、アプリケーション構成ファイルについては、こちらをご覧ください。

トレースソースのスイッチのレベルを指定する

まずは簡単な例です。"MainTraceSource"という名前のトレースソースのスイッチのレベルをWarningにしています。このようにすると、一番はじめに紹介したコードのように、TraceSource.Switch.Levelを指定する必要がなくなります。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="MainTraceSource" switchName="sourceSwitch"
        switchType="System.Diagnostics.SourceSwitch"/>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Warning"/>
    </switches>
  </system.diagnostics>
</configuration>

リスナを追加する

リスナを追加する方法は、こちらで紹介している方法とほぼ同じです。ここではこれに加えて、リスナのFilterも指定します。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="MainTraceSource" switchName="sourceSwitch"
        switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <add name="LogFile"
            type="System.Diagnostics.TextWriterTraceListener"
            initializeData="C:\test.txt">
            <filter type="System.Diagnostics.EventTypeFilter"
                    initializeData="Error"/>
          </add>
          <remove name="Default"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Warning"/>
    </switches>
  </system.diagnostics>
</configuration>

<sharedListeners>要素にリスナの設定を記述する

複数のTraceやTraceSourceで同じリスナを使う場合は、<sharedListeners>要素を使うと便利です。ここに共有するリスナを記述しておき、source要素でその名前だけを指定してリスナを追加できます。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="MainTraceSource" switchName="sourceSwitch"
        switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <add name="LogFile"/>
          <remove name="Default"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Warning"/>
    </switches>
    <sharedListeners>
      <add name="LogFile"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="C:\test.txt">
        <filter type="System.Diagnostics.EventTypeFilter"
                initializeData="Error"/>
      </add>
    </sharedListeners>
  </system.diagnostics>
</configuration>

まとめ

.NET Framework 2.0で使用できるリスナをアプリケーション構成ファイルによりTraceSourceに追加する例を示します。アプリケーション構成ファイルを以下のようにして、listeners要素内の使用したいリスナのコメントアウトを元に戻すだけです。ログを書き込む位置などは適当に書き換えてください。(こちらを参考にして作成しました。)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <sources>
      <source name="MainTraceSource" switchName="sourceSwitch"
        switchType="System.Diagnostics.SourceSwitch">
        <listeners>
          <!-- <add name="EventLog" /> -->
          <!-- <add name="TextLog" /> -->
          <!-- <add name="Delimited" /> -->
          <!-- <add name="XmlWriter" /> -->
          <!-- <add name="Console" /> -->
          <!-- <add name="FileLog" /> -->
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="sourceSwitch" value="Warning"/>
    </switches>
    <sharedListeners>
      <add name="EventLog"
        type="System.Diagnostics.EventLogTraceListener"
        initializeData="sample application" />
      <add name="TextLog"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="C:\TextLog.txt" />
      <add name="Delimited" 
        type="System.Diagnostics.DelimitedListTraceListener"
        initializeData="C:\DelimitedLog.txt"
        delimiter=","
        traceOutputOptions="DateTime" />
      <add name="XmlWriter"
        type="System.Diagnostics.XmlWriterTraceListener"
        initializeData="C:\Log.xml" />
      <add name="Console"
        type="System.Diagnostics.ConsoleTraceListener"
        initializeData="true" />
      <add name="FileLog"
        type="Microsoft.VisualBasic.Logging.FileLogTraceListener"
        initializeData="FileLogWriter" />
    </sharedListeners>
  </system.diagnostics>
</configuration>

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。