|
事業仕分けによる次世代スーパーコンピューターの開発予算削減について、どうお考えですか?
|
.NETでのトレースの方法と独自のトレースリスナの実装はじめに「デバッグ」と「トレース」は、アプリケーションの作成と保守に役立つ重要なプログラミング操作/プロセスです。デバッグとは、プログラミングエラーを観察して訂正することです。トレースはデバッグの一種であり、アプリケーションの「健康状態」を追跡することです(これは硬直的な定義であり、実際にはもっと広い意味も含まれます)。 アプリケーションの動作を動的に制御し、アプリケーションがどのように実行されているか、実行時にどんなエラーが発生するか、ピーク時にどんな動作をするか、アプリケーションの動作がどのような仕組みで動的に変化しているか、といった側面を追跡できるようにすることは非常に重要です。 この記事では、.NETでデバッグとトレースがどのように実装されているかと、これらの機能をニーズに合わせてカスタマイズする方法について説明します。 .NETでのトレースまずは、.NETでトレースがどのように実装されているかを見てみましょう。.NETにはトレースリスナというオブジェクトが用意されています。トレースリスナとは、トレース出力を受け取って、それを他の場所に出力するオブジェクトです。開発環境内のウィンドウや、ハードディスク上のファイル、Windowsのイベントログ、SQL Serverデータベース、Oracleデータベースなど、さまざまなデータストアにトレース情報を出力することができます。 トレースリスナは、アプリケーションからのトレース情報を出力ストアに送り出すためのパイプのようなものです。トレース情報をトレースリスナに書き込むと、そのトレースリスナがトレース情報をターゲットメディアに出力してくれます。 トレース情報を何らかのデータストアに格納すると、後でそのデータを柔軟な方法で分析することができ、アプリケーション内の動作パターンとエラーやパフォーマンスとの関係を探るのに役立ちます。 新しいプロジェクトを作成したときに、 図1 ![]() .NETフレームワークには、トレーススイッチという概念も導入されています。名前からわかるとおり、これはアプリケーションの外部から値を制御できるスイッチです。アプリケーションの外部から値を制御できるということは、アプリケーションをコンパイルして.exeファイルまたは.DLLファイルを生成した後に、コードを書き換えなくてもこれらのスイッチの値を変更できるということです。.configファイル内の対応するエントリを更新するだけで、アプリケーション内のスイッチに新しい値を割り当てることができます。より厳密に言えば、トレーススイッチとは、.configファイルを通じて外部から制御できる単純なオブジェクトということになります。 以降では、トレースリスナとトレーススイッチについて詳しく見ていきます。次に示すのは、 Trace.WriteLine ("Hello 15Seconds Reader - Trace!") ; Debug.WriteLine ("Hello 15Seconds Reader - Debug!") ; これらのメソッドをデバッグモードで使用すると、トレース出力とデバッグ出力がデバッガの出力ウィンドウに書き出されます(図2を参照)。 図2 ![]() トレースリスナ前述したとおり、トレースリスナはトレース情報を受け取り、格納し、最終的な宛先に送り出すためのオブジェクトです。トレース情報の最終的な宛先は、トレースリスナによって決定されます。.NETには次のようなトレースリスナが用意されています。
すべてのトレースリスナは すべてのトレースリスナは次のメソッドを備えています。これらのメソッドの機能は、トレース出力のターゲットメディアがトレースリスナによって決定されるという点を除いては、どのトレースリスナでも同じです。
DefaultTraceListener このクラスは、 このクラスは、Visual Studio環境内でトレース出力を確認したいときに使用します。Visual Studio .NETの外部でトレースメッセージを取得したい場合は、他のトレースリスナを使用する必要があります。 TextWriterTraceListener 次のコード例を見てください。 1. FileStream objStream = new FileStream("C:AppLog.txt", FileMode.OpenOrCreate) ; 2. TextWriterTraceListener objTraceListener = new TextWriterTraceListener(objStream) ; 3. Trace.Listeners.Add(objTraceListener) ; 4. Trace.WriteLine("Hello 15Seconds Reader -- This is first trace message") ; 5. Trace.WriteLine("Hello again -- This is second trace message") ; 6. Debug.WriteLine("Hello again -- This is first debug message") ; 7. Trace.Flush() ; 8. objStream.Close() ; このコードは、 1行目では、 2行目では、 3行目では、トレースリスナをリスナのコレクションに追加しています。 4行目から6行目では、さまざまなトレースメッセージとデバッグメッセージを書き出しています。 7行目では、 8行目では、ログファイルを閉じています。 このコードを実行すると、ハードディスク上に「Applog.txt」ファイルが作成されます。「Applog.txt」ファイルの内容は図3のようになります。 図3 ![]() このように、ログ情報をファイルに保存するのは非常に簡単です。 EventLogTraceListener このクラスを使用してトレース情報とデバッグ情報をイベントログに書き出すには、まずこのクラスをイベントログに関連付ける必要があります。そのための手段として、 両方の方法を使用したコード例を次に示します。 例1:
|
| トレースレベル | 設定値 | 説明 |
| Off | 0 | トレースリスナにメッセージを出力しません。 |
| Error | 1 | エラーメッセージだけをトレースリスナに出力します。 |
| Warning | 2 | エラーメッセージと警告メッセージをトレースリスナに出力します。 |
| Info | 3 | 情報メッセージ、警告メッセージ、エラーメッセージをトレースリスナに出力します。 |
| Verbose | 4 | すべてのメッセージをトレースリスナに出力します。 |
TraceSwitchクラスのインスタンスは、BooleanSwitchオブジェクトと同様の方法で作成します。トレースを有効にするには、TraceSwitchオブジェクトのLevelプロパティを使用します。スイッチのLevelプロパティを特定のレベル(上記の表のいずれかの値)に設定すると、指定のレベルよりも低いレベルをすべて含むことになります。たとえば、TraceSwitchのLevelプロパティをTraceLevel.Infoに設定した場合は、それよりも低いレベル、つまりTraceLevel.ErrorからTraceLevel.Warningまでを含むことになります。
次のコードは、エラーメッセージと警告メッセージのみのトレースを有効にする方法を示しています。
TraceSwitch objSwitch = new TraceSwitch("ErrorAndWarningTrace", "This is the trace for Error and Warning messages") ; objSwitch.Level = TraceLevel.Warning ;
TraceSwitchクラスには、その他に次のプロパティがあります。
TraceErrorTraceWarningTraceInfoTraceVerbose これらのプロパティはLevelプロパティの値に連動しており、TraceSwitchオブジェクトのLevelプロパティを特定のレベル、たとえばTraceLevel.Warningに設定した場合は、TraceErrorプロパティとTraceWarningプロパティはtrueを返し、TraceInfoプロパティとTraceVerboseプロパティはfalseを返します。これらのプロパティを使用すると、どの種類のメッセージがリスナに送信されるかをコード内で確認できます。これらのプロパティはTraceクラスおよびDebugクラスのWriteIfメソッドとWriteLineIfメソッドで使用されます。
次のコード例は、上記のトレースレベルプロパティを利用してトレース出力を制御する方法を示しています。
Trace.WriteLineIf(objSwitch.TraceWarning, "This is a warning message") ;
このステートメントでは、TraceSwitchのトレースレベルが少なくともTraceLevel.Warningに設定されているか、それより高い場合にのみ、警告メッセージを出力します。トレースレベルがTraceLevel.Errorの場合には、このステートメントは何も出力しません。
ほとんどのアプリケーションでは、.NETに用意されているトレースリスナを使用すれば用が足ります。しかし、独自のトレースリスナを作成したい場合はどうすればいいでしょうか?
.NETでは、TraceListenerクラスを利用して独自のトレースリスナを記述することができます。すべてのトレースリスナはこのクラスを継承しているので、独自のトレースリスナを実装するためには、このクラスを継承してトレースリスナクラスを作成する必要があります。
TraceListenerクラスには、数多くの仮想メソッドと抽象メソッドが用意されています。このクラスを継承するクラスは、少なくともWriteメソッドとWriteLineメソッドを実装する必要があります。この他に重要なメソッドとして、Fail、Close、Flushがあります。これらのメソッドを継承クラスで実装することは必須ではありませんが、実装しておくと便利です。これらのメソッドの機能については、前出の表を参照してください。
WriteメソッドとWriteLineメソッドはオーバーロードされています。Writeメソッドのすべてのオーバーロードを次に示します。
public override void Write(string message)public override void Write(object o)public override void Write(string message, string category)public override void Write(object o, string category) WriteメソッドとWriteLineメソッドのオーバーロードは1対1の対応になっています。TraceListenerクラスのWriteメソッドとWriteLineメソッドのそれぞれに4種類のオーバーロードがあるのはなぜでしょうか? その答えは次のとおりです。
TraceクラスとDebugクラスのWrite、WriteIf、WriteLine、WriteLineIfメソッドも同様にオーバーロードされており、それぞれのメソッドに4種類のオーバーロードがあります。TraceクラスとDebugクラスのメソッドはトレースリスナのWriteメソッドとWriteLineメソッドを呼び出すので、TraceListener側のこれらのメソッドにもオーバーロードが必要になります。 独自のトレースリスナを実装する場合は、TraceListenerクラスからリスナクラスを派生させ、少なくともWriteメソッドとWriteLineメソッドを実装します。必要な作業はこれだけです。
この記事のために、DatabaseTraceListenerというトレースリスナを作成してみました。このリスナはトレースメッセージとデバッグメッセージをデータベースに書き出します。
書き出し先のデータベースは「TraceStore」という名前で、「Traces」というテーブルを含んでいます。このデータベーステーブルの構造は次のとおりです。

TraceDateTime列:トレースメッセージの日付と時刻を格納します。TraceCategory列:トレースメッセージの実際のカテゴリを格納します。TraceDescription列:トレースメッセージを格納します。StackTrace列:スタックトレースを格納します。DetailedErrorDescription列:Failメソッドの2つ目のパラメータに渡される詳細なエラーメッセージを格納します。今回のカスタムトレースリスナは次のメソッドを実装しています。
WriteとそのすべてのオーバーロードWriteLineとそのすべてのオーバーロードFailFlushClose 独自に作成したトレースリスナを使用するのに必要な作業は、.configファイルの一部を書き換えることだけです。この書き換えをした後は、TraceクラスとDebugクラスを使用してトレースメッセージとデバッグメッセージを書き出すことができます。
今回作成したDatabaseTraceListenerは、アプリケーションの.configファイル内に2つのカスタムアプリケーション設定が記述されていることを前提にしています。アプリケーションの.configファイルに次の<appSettings>ノードを追加する必要があります。
<appSettings> <add key="ConnectionString" value="Data Source=localhost;uid=sa;pwd=;Initial Catalog=TraceStore" /> <add key="MaximumRequests" value="2" /> </appSettings>
ConnectionString設定には、データベースへの接続文字列を指定します。MaximumRequests設定には、ローカルキャッシュに格納できるトレースメッセージの最大数を表す整数値を指定します(この最大数を超えるとトレースメッセージがデータベースに保存されます)。MaximumRequests設定を用意したのは効率を良くするためです。トレースメソッドからトレースメッセージを受け取るたびにデータベースに接続してトレースメッセージを保存していたのでは、効率が悪くて仕方ありません。これを避けるために、トレースメッセージをローカルキャッシュに一時的に格納し、最大数に達したらデータベースに保存するようにしています。その後、トレースメッセージのキャッシュを再開し、これを繰り返します。
FlushメソッドとCloseメソッドは、キャッシュしたすべてのメッセージをデータベースに保存するだけです。
MaximumRequests設定の値は、トレースメッセージの頻度に応じて調節できます。大量のトレースメッセージを書き出すアプリケーションの場合は、これを大きな数値に設定します。そうでない場合は、小さな数値に設定します。
同様に、アプリケーションの.configファイルに次の<system.diagnostics>ノードを追加する必要があります。
<system.diagnostics> <trace autoflush="true" indentsize="2"> <listeners> <add name="DBTL", type="CustomTraceListeners.DatabaseTraceListener, CustomTraceListeners"/> </listeners> </trace> </system.diagnostics>
.configファイルに上記の変更を加えれば、このトレースリスナをテストすることができます。次のコードをアプリケーションのどこかに記述して、試してみましょう。
object obj1 = "Message from Trace.Write(object)" ; object obj2 = "Message from Trace.Write(object, category)" ; Trace.Write("Message from Trace.Write(message)") ; Trace.Write(obj1) ; Trace.Write("Message from Trace.Write(message, category)","category1") ; Trace.Write(obj2, "category2") ; Trace.WriteLine("Message from Trace.WriteLine") ; Trace.Fail("Message from Trace.Fail") ; Trace.Fail("Message from Trace.Fail", "Detailed error message") ; Trace.Flush() ;
このコードでは、いくつかのトレースメッセージを単純に書き出しています。Failメソッドの呼び出しは、図5のようなアサーションダイアログボックスを表示します。

これはFailメソッドの既定の動作です。処理を続けるには、[Ignore]ボタンをクリックします。このコードが完全に実行されると、データベース内の「Traces」テーブルに次の行が書き込まれます。

ASP開発者がASPで何かをデバッグ/トレースするときにはどんな方法を使っているでしょうか。クラシックASPの開発者が特定の値を確認したり実際にコードのロジックをチェックしたりするときには、コードのあちこちにResponse.Writeステートメントを記述する必要があります。誰に聞いても同意してもらえると思いますが、ASP内で何かをデバッグ/トレースするのは非常に手間のかかる作業です。コード内にResponse.Writeステートメントを記述するという古典的な手法でトレースを行うときの問題の1つは、アプリケーションが出荷できる段階になったときに、すべてのトレースステートメントをコードから手動で削除しなければならないことです。これは非常に面倒な作業であり、洗練された手法とは言えません。
ASP.NETには、ASP.NETファイル(.aspx、.asmxなど)をデバッグするための新しいデバッガと、トレースを行う非常に柔軟な方法が組み込まれています。ASP.NETのトレースは、従来のものとはまったく異なります。ASP.NETでは非常に洗練された形のトレースを行うことができ、トレースステートメントをコード内に記述したままの状態で、アプリケーションを実働環境に配備することができます。
System.Web.UI.PageクラスのTraceプロパティはSytem.Web.TraceContextオブジェクトを提供します。実際のところ、Traceオブジェクトは、Request、Response、Serverなどと同様の組み込みページオブジェクトと考えられます。このオブジェクトはページコード内から直接アクセスできます。このオブジェクトを使用すると、ページまたはアプリケーション全体のトレースを有効にしたときにのみ動作するデバッグ/トレースステートメントを記述できます。
TraceContextクラスはControl.Context.Traceプロパティを通じてもアクセスできます。これは、カスタムサーバーコントロール内にトレースステートメントを含めたり、必要に応じてASP.NETページの外部(たとえば「global.asax」ファイル)からトレースステートメントを含めたりすることがあるからです。
TraceオブジェクトとSystem.Diagnostics.Traceクラスを混同しないでください。2つはまったく異なるオブジェクトです。前者はASP.NET内でのみ使用できますが、後者はASP.NETアプリケーションでもWindowsアプリケーションでも使用できます。ASP.NETアプリケーション内でも、System.Diagnostics名前空間から提供される機能を完全に使用できます。ASP.NETには、ページレベルのトレースとアプリケーションレベルのトレースという2種類のトレースが用意されています。以降では、この2種類のトレースを実装する方法を詳しく見ていきます。
System.Web.TraceContextクラスはASP.NETページのトレース出力を管理します。このクラスの次に示すメソッドはトレースに関係しています。
| メソッド | 説明 |
IsEnabled | このプロパティは、トレースが有効な場合はtrue、それ以外の場合はfalseを返します。 |
TraceMode | このプロパティは、トレースメッセージをHTMLに書き出す順序を設定するために使用します。 |
Write | このメソッドは、カスタムトレースメッセージをトレース出力に書き出します。 |
Warn | このメソッドはWriteメソッドと同じですが、すべてのトレースメッセージを赤字のテキストとして表示します。 |
次のコードは、ASP.NETアプリケーション内にトレースステートメントを記述する方法を示しています。
// Simple trace statement Page.Trace.Write("This is trace statement") ; // Trace statement in red color. Page.Trace.Warn("This is the last warning for you") ;
ASP.NETではWebページごとにトレースを有効にできます。そのためには、@PageディレクティブのTrace属性を使用します。次のステートメントでは、ページのトレースを有効にしています。
<%@ Page Trace="true" %>
また、@PageディレクティブのTraceMode属性には次のいずれかの値を指定できます。
SortByTimeSortByCategoryTrace.WriteメソッドおよびTrace.Warnメソッドで指定したカテゴリごとに並べ替えます。トレースを有効にすると、どのような情報が得られるのでしょうか? 図7を見てください。図7は、次のコードを実行した単純なASP.NETページを示しています。
Response.Write("Hello 15Seconds Reader") ; Trace.Write("Test Category 1","This is tracing message from ASP.NET") ; Trace.Warn("Test Category 2", "This is warning message from ASP.NET") ;
このことからわかるように、ASP.NETのトレースでは次の情報が得られます。
Trace.WriteおよびTrace.Warnメソッドを使用したときにトレース出力に書き出されるページレベルのトレースメッセージが含まれます。前述のコードで定義したトレースメッセージは、図7のトレース出力の「Trace Information(トレース情報)」セクションに示されています。

この機能のメリットは、ページ内にトレースステートメントを好きなだけ記述しておき、トレースをこれ以上行う必要がなくなったら、@PageディレクティブのTrace属性をfalseに設定するだけで、トレース出力が生成されないようにすることができるという点です。トレースステートメントをコードから手動で削除する必要はありません。
ページレベルのトレースは、1つか2つのページのトレースを有効にする場合には便利ですが、アプリケーションを構成するすべてのページで1つ1つ@Pageディレクティブを使用してトレースを有効にするのはスマートではありませんし、時間がかかりすぎます。トレースを無効にするときにも、同様に、1つ1つのページをエディタで開いてTrace属性をfalseに設定しなければなりません。
ASP.NETでは、この問題の解決策としてアプリケーションレベルのトレースが用意されています。アプリケーションレベルのトレースを有効にするには、Webアプリケーションの「web.config」ファイルの<trace>ノードを使用します。
次の<trace>ノード設定では、Webアプリケーションのアプリケーションレベルのトレースを有効にし、要求の数を20に設定しています。
<configuration> <system.web> <trace enabled="true" requestLimit="20" /> </system.web> </configuration>
<trace>ノードには次の属性があります。
| 属性 | 説明 |
enabled | アプリケーションのトレースを有効にするには、この属性をtrueに設定します。それ以外の場合はfalseに設定します。既定値はfalseです。 |
pageOutput | トレース情報をトレースページと「trace.axd」ファイルの両方に出力する場合は、この属性をtrueに設定します。それ以外の場合はfalseに設定します。既定値はfalseです。たとえば pageOutputをfalseに設定してenabledをtrueに設定した場合は、ページ上にトレース出力が表示されないので、トレース情報を確認するには「trace.axd」ファイルを開く必要があります(@PageディレクティブのTrace属性がfalseに設定されていることが前提です)。 |
requestLimit | この属性では、ASP.NETがトレース情報を格納する要求の最大数を指定します。既定値は10です。 |
traceMode | @PageディレクティブのTraceMode属性と同じ機能です。SortByTimeとSortByCategoryのいずれかの値を取ります。既定値はSortByTimeです。 |
localOnly | この属性では、「trace.axd」ファイルをローカルサーバーからのみアクセス可能にするか(true)、他のコンピュータからもアクセス可能にするか(false)を指定します。既定値はtrueです。 |
アプリケーション全体のトレースを有効にした場合、ASP.NETは、<trace>ノードのrequestLimit属性に指定した要求数に達するまで、すべての要求に対するトレース出力を格納し始めます。
アプリケーションレベルのトレースを有効にした場合に、ASP.NETがそのWebアプリケーションに関して記録したすべてのトレースを見るためには、Webアプリケーションの「trace.axd」ファイルを参照する必要があります。「trace.axd」ファイルを参照するためのジェネリックURLは次のとおりです。
http://<サーバー名>/webapp/trace.axd
私のマシン上でテスト用のWebサイト(/wa)を参照したときの様子を図8に示します。

最大要求数に達するまでは、すべての要求がメモリに格納されます。右端の列に表示されている「View Details(詳細の表示)」リンクをクリックすると、その要求に関するトレースの詳細が表示されます。
ASP.NETのトレースをいろいろ試していて気が付いた重要な点の1つは、.configファイルを変更すると、アプリケーションのトレースがリサイクルされて、メモリ内のトレースがクリアされてしまうということです。
ASP.NETのトレースのしくみは以上ですが、実働環境のアプリケーションではトレースを使用するべきではありません。トレースはアプリケーションのパフォーマンスに深刻な影響を与えるからです。実働環境に配備したASP.NETアプリケーションでトレース情報を取得したい場合は、System.Diagnostics名前空間のクラスを使用することを検討してください。この記事の前半で説明したSystem.Diagnostics名前空間のクラスの詳細は、ASP.NETアプリケーションにもすべて適用できます。ASP.NETアプリケーション内でこれらのクラスをさまざまに活用することができます。
この記事では、トレースの概要と利用方法について解説しました。独自のトレースリスナの作成方法についても触れました。.NETのトレースは非常に洗練されたオブジェクト指向的な方法で実装されており、.configファイルとカスタムリスナのおかげで、非常に柔軟でカスタマイズしやすいものになっています。
ASP.NET Webアプリケーションで1つ注意してほしいのは、開発時にトレースを有効にすることはかまいませんが、実働環境のアプリケーション内でASP.NETトレースを有効にすると、アプリケーションのパフォーマンスに深刻な影響を与えるおそれがあるという点です(System.Diagnostics名前空間のクラスを利用したトレースは問題ありません)。したがって、ASP.NETトレースを使用するときは十分に注意してください。
一般的には、アプリケーションの開発時には広範囲に渡ってトレースを使用することをお勧めします。アプリケーションをリリースできる段階になったら、開発固有のトレースメッセージをコードから取り除けばよいのです(ヒント:トレースレベルを使用します)。ある種のトレースは、アプリケーション内のエラーや問題を調査するときに大きな助けになります。
【Graphic Design Forum】
流動的媒体と静的媒体に関する見解(11月18日) |
![]() |
スマートにソーシャルウェブを構築しよう
|
![]() |
アイレップの SEM フロンティア
|
![]() |
百式のネットビジネス研究
|
![]() |
DevX
HTML 5のフォーム要素(11月24日) |
![]() |
エンジニア転職ノウハウ開発室
エンジニア的「合わない」と思う瞬間/理系の人々(11月24日) |
![]() |
「IT の耳」
|
![]() |
週刊-サイト別アクセス状況データ
|
![]() |
海外ソーシャルウェブに学ぶ成功の秘訣
ゲーム業界を襲う世界的な激震。ソーシャルゲーム急成長のインパクト(11月19日) |
![]() |
今さら聞けない初歩からのアクセス解析
サイトリニューアル前のアクセス解析活用法(11月19日) |
![]() |
成約率、反応率を上げる Web 文章術
文章力を磨き、キャッシュを生み出す Web サイト に(11月19日) |