読者です 読者をやめる 読者になる 読者になる

.NET Framework(C#)のLogger

C#

どういうわけか今までログについてあまり考えてきませんでしたが、最近少し需要を感じるようになりました。きっと用意されているはず、と調べると案の定いくつかありました。ごく簡単にまとめておきます。

System.Diagnostics.TraceSource

多分定番です。

TraceSource log = new TraceSource("TraceSource Log", SourceLevels.All);

log.TraceEvent(TraceEventType.Error, 0, "hogehoge");
log.Flush();

コンストラクタのSourceLevelsでどのレベルまでのイベントを出力させるかを設定できます。ログの書き出し時のレベルはTraceEventTypeで設定します。


これだけではファイルには書き出されません。リスナを追加します。

TextWriterTraceListener listener = new TextWriterTraceListener("log_tracesource.txt", "LogFile");
listener.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.ProcessId | TraceOptions.ThreadId;
log.Listeners.Add(listener);

TraceOutputOptionsで出力に含める情報を設定できます。TraceEventメソッドに渡す文字列に自力で情報を詰め込まなくても、ここをいじるだけで結構な情報が入ります。

Microsoft.VisualBasic.Logging.Log

VB.NETではMy.Application.Logとして利用できる便利なクラスです。C#ではMicrosoft.VisualBasicを参照に追加する必要があります。TraceSourceのラッパーのような仕組みになっていて、よく似ています。

TraceSourceと違い、最初からファイルへ書き出すことが前提になっています。指定した場所のファイルへ出力するには、DefaultFileLogWriterプロパティからLocationとCustomLocationを設定します。CustomLocationで設定した名前のディレクトリが作られ、その中にログファイルが置かれるようです。

Log log = new Log("VB Log");
log.DefaultFileLogWriter.Location = LogFileLocation.Custom;
log.DefaultFileLogWriter.CustomLocation = "log_vb";

log.WriteEntry("fugafuga");
log.TraceSource.Flush();

TraceSource同様に書き出す際の情報を加えたいときは、次のようにします。

log.TraceSource.Listeners[1].TraceOutputOptions = TraceOptions.DateTime | TraceOptions.ProcessId | TraceOptions.ThreadId;

System.IO.Log.FileRecordSequence

.NET Framework 3.0で追加されたらしいSystem.IO.Log名前空間。利用にはSystem.IO.Logを参照に追加します。

なんだかすごそうではあるのですが、今のところいまいち使い方が良くわかりません。とりあえず書き込むには以下のようにします。文字列のままでは書き込めず、byte[]に変換します。

FileRecordSequence seq = new FileRecordSequence("log_logstore.log", FileAccess.ReadWrite);

byte[] bytes = Encoding.Unicode.GetBytes("piyopiyo");
ArraySegment<byte> segment = new ArraySegment<byte>(bytes);
seq.Append(segment, SequenceNumber.Invalid, SequenceNumber.Invalid, RecordAppendOptions.ForceFlush);

byte[]で書き込んだことからも分かるように、ログファイルがテキスト形式にならず、読めません。以下のプログラムは読み込むコードです。

foreach (LogRecord record in seq.ReadLogRecords(seq.BaseSequenceNumber, LogRecordEnumeratorType.Next))
{
    byte[] data = new byte[record.Data.Length];
    record.Data.Read(data, 0, (int)record.Data.Length);
    string str = Encoding.Unicode.GetString(data);
    Console.WriteLine(str);
}

締めはこれで。

seq.Dispose();