.net frameworkに標準でついているロギングクラス群を使ってみた、作ってみた。
【設定ファイル】
アプリケーション構成ファイルを追加して、そこに設定を記述する。
ログ出力判定
- 出力レベルが、TraceSourceで指定されているSourceSwitchのログレベル以上であるか確認
- TraceSourceに指定されているListener毎に以下を確認 出力レベルが、Listenerのフィルタで指定されているログレベル以上であるか確認
- すべてパスした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() + "] "); } }