数か月前にこういうセッションをして紹介したSLABですが、
肝心の導入の仕方とか使い方は説明しないままでした。また、 id:okazuki 先生がわかりやすい SLABの解説を書いてくださっています。
EnterpriseLibrary 6のSemantic Logging Application Blockの感想 - かずきのBlog@hatena
id:okazuki 先生は In-Process なログ出力を扱っていましたが、WebアプリだとやはりOut-of-Process の方が好ましいことが多いと判断しています。というわけで、 SLABの Out-of-Process (OOB) を試してみたいと思います。今回はNugetで公開されているライブラリを取得してきて動かしてみるところまでです。
SLABのOOBはNugetで配布されていますが、C# (などの)VisualStudioプロジェクトに追加して使うのではなく、単体のツールとして動きます。そのためセットアップもちょっと変わった方法になります*1。
まず、ドライブ直下に「OOB」などといった適当なフォルダを作ります*2。そして、NuGet Gallery | Home からNugetをダウンロードして、「.nuget\Nuget.exe」に置いておきます。 ここからはPowerShellでセットアップしていきます。以下のコマンドを実行してNugetから EnterpriseLibrary.SemanticLogging.Service をlibフォルダ以下にダウンロードします。
.\.nuget\nuget.exe install EnterpriseLibrary.SemanticLogging.Service -OutputDirectory lib
これで終わり。と思いきや、もう一度依存するライブラリをNugetから取得しないといけないので次のコマンドを実行します。
.\lib\EnterpriseLibrary.SemanticLogging.Service.2.0.1406.1\tools\install-packages.ps1 -autoAcceptTerms
こんな風にダウンロードが完了します。「Press ENTER key to finish...」とあるので適当に押して終わりましょう。
さて、ここで勘のいい方は気づいたかもしれませんが、-autoAcceptTerms オプションを指定しているのにもかかわらずユーザーからの入力を求めています。つまり、このツールの展開を自動化する場合には、ここのユーザー入力がネックになってしまいます... 回避策はなくはないのですが、本家に修正してもらうのがいいと思いますので、Issueを上げています。
さて、toolsフォルダ 以下に必要なものがダウンロードされているので見てみましょう。dll や SQLファイルのほかに、SemanticLogging-svc.exe と SemanticLogging-svc.xml があると思いますが、これが本体のexeと設定ファイルになります。
SemanticLogging-svc.xml を開くと flatFileSink とか書かれたXML要素があるはずです。ここで、どのような出力(Sink)を使うかと、その設定、入力を指定します。 今回は最初から用意されている ConsoleSink というSinkを使ってみましょう。 SemanticLogging-svc.xml を以下のように編集します。
<?xml version="1.0" encoding="utf-8" ?> <configuration xmlns="http://schemas.microsoft.com/practices/2013/entlib/semanticlogging/etw" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/practices/2013/entlib/semanticlogging/etw SemanticLogging-svc.xsd"> <traceEventService/> <sinks> <consoleSink name="ConsoleEventSink"> <sources> <eventSource name="My" level="LogAlways" /> </sources> <eventTextFormatter header="+=========================================+"/> </consoleSink> </sinks> </configuration>
consoleSink 要素の中のsourcesが取得するSLABのイベントソースです。今回はテスト用にログを発生させるので、とりあえず"My"という名前にしておきました。 テスト用のログはこんな風なプログラムで実行しました。
using System; using System.Diagnostics.Tracing; using System.Threading; namespace ConsoleApplication11 { class Program { static void Main(string[] args) { var log = MyEventSource.Log; var random = new Random(); while (true) { log.Login("user" + random.Next(100)); Thread.Sleep(TimeSpan.FromSeconds(1)); } } } [EventSource(Name = "My")] public sealed class MyEventSource : EventSource { public class Keywords { public const EventKeywords Perf = (EventKeywords)1; } public class Tasks { public const EventTask Login = (EventTask)1; } private readonly static MyEventSource log = new MyEventSource(); private MyEventSource() { } public static MyEventSource Log { get { return log; } } [Event(201, Level = EventLevel.Informational, Keywords = Keywords.Perf, Message = "Login: {0}", Task = Tasks.Login, Version = 1)] public void Login(string user) { WriteEvent(201, user); } } }
書いたコンソールアプリを起動しておきます。
それでは、 SemanticLogging-svc.exe を実行します。PowerShellコンソールを管理者権限で開きます。引数つけずに実行するとヘルプが出ます。
Enterprise Library Semantic Logging Service v2.0.1406.1 Microsoft Enterprise Library Microsoft Corporation [ -i | -install ] Install as a Windows Service. [ -u | -uninstall ] Uninstall the Windows Service. [ -s | -start ] Start or install and start the service. [ -c | -console ] Run as a console application. [ -h | -help | -? ] Display list of arguments [ -a=type | -account=type] Specifies the account type. Accepted values are User, LocalSystem, and LocalService. De ault is LocalService.
サービスとしてセットアップできますが、今回はコンソールアプリとして動かしてみましょう。 "SemanticLogging-svc.exe -c" と実行してみます。
+=========================================+ EventId : 201, Level : Informational, Message : Login: user19, Payload : [user : user19] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:22.9527575Z, Proc essId : 6684, ThreadId : 7232 +=========================================+ EventId : 201, Level : Informational, Message : Login: user46, Payload : [user : user46] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:23.9530479Z, Proc essId : 6684, ThreadId : 7232 +=========================================+ EventId : 201, Level : Informational, Message : Login: user8, Payload : [user : user8] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:24.9534321Z, Proces sId : 6684, ThreadId : 7232 +=========================================+ EventId : 201, Level : Informational, Message : Login: user27, Payload : [user : user27] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:25.9541017Z, Proc essId : 6684, ThreadId : 7232 +=========================================+ EventId : 201, Level : Informational, Message : Login: user19, Payload : [user : user19] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:26.9549686Z, Proc essId : 6684, ThreadId : 7232 +=========================================+ EventId : 201, Level : Informational, Message : Login: user70, Payload : [user : user70] , EventName : LoginInfo, Timestamp : 2014-07-25T12:51:27.9557676Z, Proc essId : 6684, ThreadId : 7232
EventSourceから出力したイベントを consoleSink で取得できましたね。Payload にはメソッドの引数が含まれていますが、これとは別にログが発生したTimestampも含まれています。