過去分
- EnterpriseLibrary 6のSemantic Logging Application Blockを触ってみた - かずきのBlog@hatena
- EnterpriseLibrary 6のSemantic Logging Application BlockでAzure Storageにログをはく - かずきのBlog@hatena
- Enterprise Library 6のSemantic Logging Application Block + Reactive Extensions - かずきのBlog@hatena
はじめに
ログ関係のライブラリを使いこんでいくうちに出てくる要求として出力先をカスタマイズしたいというのはよくあると思います。Semantic Logging Application Blockでも当然そこは拡張できるように作られてるのでやってみました。
****Sinkというクラスを作る
Semantic Logging Application BlockはRxと相性がいいだけあって、ログの出力する人はEventEntryのIObserverです。OnNextを処理すればOKというわかりやすい設計。今回はコンソールに出すだけの簡単なものを作ってみました。フォーマッティングはIEventTextFormatterにお任せしてます。
// 独自の出力先 class MyConsoleSink : IObserver<EventEntry> { private IEventTextFormatter formatter; public MyConsoleSink(IEventTextFormatter formatter = null) { this.formatter = formatter ?? new EventTextFormatter(); } public void OnCompleted() { } public void OnError(Exception error) { } public void OnNext(EventEntry value) { // 値がわたってきたときだけ if (value == null) { return; } // formatterで整形して出力する using (var w = new StringWriter()) { this.formatter.WriteEvent(value, w); Console.Write(w); } } }
そして、IObservable
// MyConsoleSink購読用拡張メソッド static class MyConsoleSinkExtensions { public static SinkSubscription<MyConsoleSink> LogToMyConsole(this IObservable<EventEntry> self, IEventTextFormatter formatter = null) { var sink = new MyConsoleSink(formatter); var d = self.Subscribe(sink); return new SinkSubscription<MyConsoleSink>(d, sink); } }
Subscribeして、SinkSubscriptionというものを返すのがお約束っぽいのでそれに従ってます。Semantic Logging Application BlockのログがIObservableから発行されたものをIObserverで監視して出力するだけということがわかれば、間にRxのLINQ挟み込めるのも納得ですね。
使い方
// リスナー作って var l = new ObservableEventListener(); // 監視するログの種類を設定して l.EnableEvents( MyEventSource.Log, EventLevel.Verbose, MyEventSource.Keywords.Diagnostic | MyEventSource.Keywords.Lifecycle); // 自前のログ出力先へ出力する l.LogToMyConsole(); MyEventSource.Log.Start(); MyEventSource.Log.Query("select * from dual"); MyEventSource.Log.Stop();
とても簡単ですね。