出力したログと全く同じ内容を文字列で取得
log4netを使っていて、「××がログファイルに出力されること」みたいなテスト項目があったとする。無理矢理ログファイルをオープンして読む以外に自動的に確認する方法はあるんだろうか。
ということで、ファイルに書き込むと同時にStringWriterにも同じ内容を書き込んで保持しておくAppenderを作って使ってみる。
using System; using System.IO; using log4net.Appender; using log4net.Core; using log4net.Util; namespace MyTest { class TapFileAppender : FileAppender { private TapQuietTextWriter _tapWriter = null; // FileAppenderが書き込みに使う QuietWriter プロパティを // セットする箇所を上書き override protected void SetQWForFiles(TextWriter writer) { _tapWriter = new TapQuietTextWriter(writer, ErrorHandler); base.SetQWForFiles(_tapWriter); } public String Text { get { return _tapWriter.Text; } } } class TapQuietTextWriter : QuietTextWriter { private StringWriter _tapWriter; public TapQuietTextWriter(TextWriter writer, IErrorHandler errorHandler) : base(writer, errorHandler) { _tapWriter = new StringWriter(); } public override void Write(char value) { base.Write(value); _tapWriter.Write(value); } public override void Write(char[] buffer, int index, int count) { base.Write(buffer, index, count); _tapWriter.Write(buffer, index, count); } override public void Write(string value) { base.Write(value); _tapWriter.Write(value); } public String Text { get { return _tapWriter.ToString(); } } } }
log4netの設定で、AppenderをTapFileAppenderに変更
<log4net> <appender name="LogFileAppender" type="MyTest.TapFileAppender" > <param name="File" value="..\log\test.log" /> <param name="AppendToFile" value="true" /> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> </layout> </appender> <root> <level value="ALL" /> <appender-ref ref="LogFileAppender" /> </root> </log4net>
Appenderのうまい取得方法がよく分からないが、とりあえず以下のように取れるらしい。
log4net.Repository.Hierarchy.Hierarchy repo =
(log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository();
TapFileAppender appender =
(TapFileAppender)repo.Root.GetAppender("LogFileAppender");
appender.Text で書き込んだ全内容が取れる。
だめなところ
- FileAppenderのAppendメソッドをオーバーライドしてRenderLoggingEventを呼ぶだけで同じことができるような気もする。とりあえず中身がよくわからないので「ファイルに出力したのと全く同じ内容」にするため、より低レベルなところ(ファイル書き込み寸前のところ)でキャプチャーするようにしてみた。
- 中身はStringWriterなのでそのままではマルチスレッドでは悲惨になるっぽい。
- 一回 Text プロパティを読んだらそこまでの内容は捨てるようにしたい。
- log4netを使いはじめて2時間のド素人なので何が正しいのかよくわからない。