.net frameworkに標準でついているロギングクラス群を使ってみた、作ってみた。

【設定ファイル】
アプリケーション構成ファイルを追加して、そこに設定を記述する。
ログ出力判定
  1. 出力レベルが、TraceSourceで指定されているSourceSwitchのログレベル以上であるか確認
  2. TraceSourceに指定されているListener毎に以下を確認
    出力レベルが、Listenerのフィルタで指定されているログレベル以上であるか確認
  3. すべてパスしたListenerを使用してログ出力する。
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.diagnostics>
        <sources>
          <source name="Log" switchName="ss_info" switchType="System.Diagnostics.SourceSwitch">
            <listeners>
              <add name="console" />
              <add name="my_text" />
              <remove name="Default" />
            </listeners>
          </source>
        </sources>
        <switches>
          <add name="ss_info" value="Information" />
        </switches>
        <sharedListeners>
          <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning"/>
          </add>
          <!-- 自前のTraceListenerのタイプは、"タイプフルネーム,アセンブリ名"と指定する。 -->
          <add name="my_text" type="TraceSourceSample.MyTraceListener,TraceSourceSample" initializeData="MyLogfile.log">
            <filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning"/>
          </add>
        </sharedListeners>
      </system.diagnostics>
    </configuration>
    
    【カスタムListener】
    TextWriterTraceListenerがshift_jisで出力されて、フォーマットが気に入らなかったので作ってみた。
    (文字コード問題は、コンストラクタでStreamを渡してやればいいのだろうけど、
    フォーマットが変更できなそうだったので。)
    /// <summary>
    /// カスタムTraceLIstener
    /// </summary>
    /// <remarks>
    /// utf8なテキストファイルにログを出力する、スレッドセーフなTraceser
    /// </remarks>
    public class MyTraceListener : TraceListener
    {
        private static FileStream fs = null;
        private static StreamWriter sw = null;
    
        public MyTraceListener(String log_file_path)
        {
            //Todo:複数パラメータをつけたときの設定ファイル記述方法がわからない。
            //     AutoFlushフラグなど付けたりしたい。
    
            if (fs == null)
            {
                fs = new FileStream(log_file_path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                sw = new StreamWriter(fs, Encoding.UTF8);
            }
        }
    
        private String getDate()
        {
            return "[" + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + "]";
        }
    
        public override void Write(string message)
        {
            /*
             * TraceSourceクラスのTraceEventメソッドを呼び出した際のログ出力処理は
             * 二回に分けて出力される。
             * 
             * 1, TraceEventTypeとイベントId -> Writeメソッドで出力
             * 2, ログメッセージ -> WriteLineメソッドで出力
             * 
             * その為、WriteLineメソッドだけメッセージの後ろに日付を追加している。
             */
    
            lock (sw)
            {
                sw.Write(message);
                sw.Flush();
            }
        }
    
        public override void WriteLine(string message)
        {
            lock (sw)
            {
                sw.WriteLine(message + getDate());
                sw.Flush();
            }
        }
    
        public override void Flush()
        {
            lock (sw)
            {
                sw.Flush();
            }
        }
    
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            sw.Dispose();
        }
    }
    
    【動作確認フォーム】
    public partial class Form1 : Form
    {
        private static readonly TraceSource ts = new TraceSource("Log");
    
        public Form1()
        {
            InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
    
            try
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread thd = new Thread(new ParameterizedThreadStart(trace));
                    thd.Start(i);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.ToString());
            }
        }
    
        private void trace(Object param)
        {
            int idx = (int)param;
            ts.TraceEvent(TraceEventType.Warning, 0, "Event Message[" + idx.ToString() + "] ");
        }
    }