独自のトレースリスナの実装
ほとんどのアプリケーションでは、.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
アプリケーション内でDatabaseTraceListenerを使用する
独自に作成したトレースリスナを使用するのに必要な作業は、.configファイルの一部を書き換えることだけです。この書き換えをした後は、TraceクラスとDebugクラスを使用してトレースメッセージとデバッグメッセージを書き出すことができます。
.configファイル内で必要な設定
今回作成した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.NETでのトレース
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種類のトレースを実装する方法を詳しく見ていきます。
ASP.NETでのSystem.Web.TraceContextクラス(またはTraceオブジェクト)
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属性には次のいずれかの値を指定できます。
SortByTimeSortByCategory
Trace.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のトレースでは次の情報が得られます。
- Request Details(要求の詳細)
- Trace Information(トレース情報)
- Control Tree(コントロールのツリー)
- Cookies Collection(クッキーコレクション)
- Headers Collection(ヘッダーコレクション)
- Server Variables(サーバー変数)
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トレースを使用するときは十分に注意してください。
一般的には、アプリケーションの開発時には広範囲に渡ってトレースを使用することをお勧めします。アプリケーションをリリースできる段階になったら、開発固有のトレースメッセージをコードから取り除けばよいのです(ヒント:トレースレベルを使用します)。ある種のトレースは、アプリケーション内のエラーや問題を調査するときに大きな助けになります。
