次の方法で共有


IIS 7.0 マネージド モジュールにトレースを追加する方法

作成者: Saad Ladki

はじめに

IIS 7.0 以降では、カスタムで開発されたマネージド モジュールをプラグインして使用し、さまざまなタスクを実行し、それらのモジュールをあらゆる種類のコンテンツに使用できる機能が備わっています。 しかし、モジュールに問題があったり、難しい箇所があったらどうなるかという疑問があります。 以前は、問題が発生したときは、System.Diagnostics を使用してイベントをトレースしていました。 残念ながら、これらのトレースは IIS トレースとは完全に分離されています。

IIS 7.0 以降ではそうではありません。 現在は、System.Diagnostics.TraceSource (.Net 2.0 の新機能) を使用して、モジュール コードにトレースを追加できるようになりました。 これらのトレースを IIS トレース インフラストラクチャにルーティングして、トレースを使用するモジュール (失敗した要求のトレースなど) で使用可能にできます。

IIS チームは、次のような基本的なパターンを使用してコードをインストルメント化することをお勧めします。

  • コード内の主要なアクティビティに関する START イベントと STOP イベント
  • 要求が失敗する可能性がある予期しない発生 (認証の失敗など) に関する WARNING イベントと ERROR イベント
  • 診断 (使用されているモジュール構成など) に役立てるための INFORMATIONAL イベントと VERBOSE イベント

このチュートリアルでは、以下のタスクを行います。

  • System.Diagnostics.TraceSource を使用したモジュールへのトレースの追加
  • これらのトレースをキャプチャするための失敗した要求のトレースの構成
  • エラー状態の生成と結果のトレースの表示

前提条件

この記事のタスクを実行する前に、次の手順に従います。

手順 1: IIS のインストール

まず、IIS をインストールする必要があります。 http://localhost/ を参照して IIS がインストールされているかどうかを確認します。 IIS がインストールされている場合は、"工事中" ページが表示されます。 IIS がインストールされていない場合の手順については、「IIS のインストール」を参照してください。 次の IIS コンポーネントをインストールしてください。

  • ASP ([World Wide Web サービス] の下 => [アプリケーション開発機能] => [ASP])
  • ASP.Net ([World Wide Web サービス] の下 => [アプリケーション開発機能] => [ASP.Net])
  • トレース ([World Wide Web サービス] => [正常性] と [診断] => [トレース] の下)

手順 2: 管理者としてログイン

管理者アカウントまたは Administrators グループとしてログインします。

Note

Administrators グループに属していても、既定では完全な管理者特権が付与されるわけではありません。 多くのアプリケーションで、管理者として実行する必要があります。 アプリケーション アイコンを右クリックし、[管理者として実行] を選択します。

手順 3: バックアップの作成

この記事のタスクを実行する前に、構成のバックアップを作成します。 次の手順を実行します:

  1. [スタート] ボタン -> [すべてのプログラム] -> [アクセサリ] -> (右クリック) コマンド プロンプト -> [管理者として実行] を選択します
    右クリック ドロップダウン メニューの [管理者として実行] オプションにフォーカスがある Windows スタート メニューのスクリーンショット。

  2. そのコマンド プロンプトで、次のコマンドを実行します。

    %windir%\system32\inetsrv\appcmd add backup
    

手順 4: サンプル コンテンツの作成

  1. c:\inetpub\wwwroot フォルダー内のすべてを削除します。
  2. 上記で開始した管理者コマンド プロンプトから、添付されたコードを test.htm という inetpub\wwwroot 内のファイルに貼り付けます。
<h2>HOWTO: Adding tracing to modules </h2>
This is a sample page served by the static file handler (native code).

単純なモジュールの作成とトレース

このセクションでは、インストルメント化するサンプル モジュールを作成します。

手順 1: 単純なモジュールの作成

管理者コマンド プロンプトを使用して、次のコードをコピーし、IIS_MOD_REQDATA.cs というファイルに貼り付けます。

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace IIS_MOD_REQDATA
{
    public class IIS_MOD_REQDATA : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.EndRequest += (new EventHandler(this.Application_EndRequest));
        }

        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            // start writing out the request data

            context.Response.Write("<hr>");
            context.Response.Write("<b><font size=2 color=green>REQUEST HEADERS</font></b><br>");
            context.Response.Write("<font size=2>");
            context.Response.Write("METHOD : " + context.Request.HttpMethod + "<br>");
            context.Response.Write("URL : " + context.Request.Url + "<br>");
            context.Response.Write("QUERYSTRING : " + context.Request.QueryString + "<br>");
            context.Response.Write("</font><br>");

            // now response data

            context.Response.Write("<b><font size=2 color=blue>RESPONSE HEADERS</font></b><br>");
            context.Response.Write("<font size=2>");
            context.Response.Write("STATUS CODE : " + context.Response.StatusCode.ToString() + "." + context.Response.SubStatusCode.ToString() + "<br>");
            context.Response.Write("CONTENT TYPE : " + context.Response.ContentType.ToString() + "<br>");
            context.Response.Write("EXPIRES : " + context.Response.Expires.ToString() + "<br>");
            context.Response.Write("</font><br>");

            // set cache policy on response so it's not cached.

            context.Response.DisableKernelCache();
        }

        public void Dispose()
        {
        }
    }
}

手順 2: マネージド モジュールへのトレースの追加

モジュールにトレースを追加し、そのトレース イベントを IIS にルーティングするには、System.Diagnostics.Trace ソースを使用します。 using ステートメントの下に次の行を追加します。

using System.Diagnostics;

コード内に TraceSource を作成する必要があります。IIS_MOD_REQDATA モジュールの宣言内の traceSource の定義に注目してください。

public class IIS_MOD_REQDATA : IHttpModule
{
    TraceSource tsStatus;

tsStatus メンバーは、IHttpModule の Init() メソッドの間に初期化されます。

public void Init(HttpApplication application)    
{    
    application.EndRequest += (new EventHandler(this.Application_EndRequest));
    // setup traceSource
    tsStatus = new TraceSource("tsStatus");    
}

この名前は後で web.config ファイルで参照されるため、TraceSource ("tsStatus") の名前は重要です。 次は、必要に応じて、モジュールがイベントを出力するように設定します。

新しいトレース イベントを追加するには、tsStatus.TraceEvent(<type>, 0, <somestring>) を使用してイベントを書き出します。 推奨される Start イベントと End イベントを Application_EndRequest() メソッドに追加します。

private void Application_EndRequest(Object source, EventArgs e)        
{    
    tsStatus.TraceEvent(TraceEventType.Start, 0, "[REQDATA MODULE] START EndRequest");

    // other code

    tsStatus.TraceEvent(TraceEventType.Stop, 0, "[REQDATA MODULE] END EndRequest");    
}

<型>が異なることに注意してください。サポートされている型には、次のようなものがあります。

  • TraceEventType.Start
  • TraceEventType.Stop
  • TraceEventType.Error
  • TraceEventType.Warning
  • TraceEventType.Information
  • TraceEventType.Verbose

全部揃える場合、モジュールのソース全体 (トレース イベントを含む) をここからコピーできます。

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Diagnostics;

namespace IIS_MOD_REQDATA
{
    public class IIS_MOD_REQDATA : IHttpModule
    {

        TraceSource tsStatus;

        public void Init(HttpApplication application)
        {
            application.EndRequest += (new EventHandler(this.Application_EndRequest));

            // TRACING

            tsStatus = new TraceSource("tsStatus");
        }

        private void Application_EndRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            tsStatus.TraceEvent(TraceEventType.Start, 0, "[REQDATA MODULE] START EndRequest");

            // start writing out the request data

            context.Response.Write("<hr>");
            context.Response.Write("<b><font size=2 color=green>REQUEST HEADERS</font></b><br>");
            context.Response.Write("<font size=2>");
            context.Response.Write("METHOD : " + context.Request.HttpMethod + "<br>");
            context.Response.Write("URL : " + context.Request.Url + "<br>");
            context.Response.Write("QUERYSTRING : " + context.Request.QueryString + "<br>");
            context.Response.Write("</font><br>");

            tsStatus.TraceEvent(TraceEventType.Verbose, 0, "[REQDATA MODULE] done with Req Data, moving onto Response");

            // now response data

            context.Response.Write("<b><font size=2 color=blue>RESPONSE HEADERS</font></b><br>");
            context.Response.Write("<font size=2>");
            context.Response.Write("STATUS CODE : " + context.Response.StatusCode.ToString() + "." + context.Response.SubStatusCode.ToString() + "<br>");
            context.Response.Write("CONTENT TYPE : " + context.Response.ContentType.ToString() + "<br>");
            context.Response.Write("EXPIRES : " + context.Response.Expires.ToString() + "<br>");
            context.Response.Write("</font><br>");

            if (context.Response.StatusCode > 399)
            {
                tsStatus.TraceEvent(TraceEventType.Warning, 0, "[REQDATA MODULE] error status code detected");
            }

            tsStatus.TraceEvent(TraceEventType.Verbose, 0, "[REQDATA MODULE] done with Response Data");

            // set cache policy on response so it's not cached.

            context.Response.DisableKernelCache();
            tsStatus.TraceEvent(TraceEventType.Verbose, 0, "[REQDATA MODULE] cache setting is (" + context.Response.Cache.ToString() + ")");

            tsStatus.TraceEvent(TraceEventType.Stop, 0, "[REQDATA MODULE] STOP - EndRequest");
        }

        public void Dispose()
        {
        }
    }
}

手順 3: トレースされたモジュールのコンパイル

モジュールをコンパイルしてデプロイします。 管理者コマンド プロンプトで、次のコマンドを実行します。

%systemroot%\Microsoft.NET\Framework\v2.0.50727\csc.exe /target:library /out:IIS_MOD_REQDATA.dll /debug /d:TRACE /R:System.Web.dll IIS_MOD_REQDATA.cs

メモ帳の感嘆符コードダッシュ consoleMain コマンドのスクリーンショット。

Note

64 ビット システムでこれを実行している場合は、64 ビット c# コンパイラを %windir%\microsoft.net\framework64\v2.0.50727\csc.exe で使用してコンパイルします

/debug スイッチと /d:TRACE スイッチの使用に注意してください。 これらのスイッチを使用して、トレース イベントをバイナリにコンパイルする必要があります。 これらのスイッチを使用してコンパイルできない場合は、モジュールにトレース イベントがないことを意味します。

モジュールをコンパイルしたら、モジュールをデプロイし、初期テストを実行して、トレースをキャプチャする前にモジュールが機能するかどうかを確認します。

サイトの構成へのモジュールの追加

このセクションには、モジュールの追加とテストが含まれます。

手順 1: モジュールのサイト構成への追加

  1. 同じ管理者コマンド プロンプトを使用して、\inetpub\wwwroot\bin という名前のディレクトリを作成し、IIS_MOD_REQDATA.dll をそのディレクトリにコピーします。
  2. モジュールを有効にします。 管理者コマンド プロンプトで、「start inetmgr」と入力して IIS 管理 UI を表示します。
  3. [接続] ウィンドウで、ローカル コンピューター名、サイトの順に展開し、[既定の Web サイト] を選択します。
  4. 中央のウィンドウの [IIS] で、[モジュール] をダブルクリックします。
    [モジュール] オプションが強調表示されている [既定の Web サイトホーム] 画面のスクリーンショット。
  5. このサイトで使用するように構成されたモジュールの長い一覧が表示されます。 [操作] の下の UI の右側にある [マネージド モジュールの追加] を選択します。
    [管理モジュールの追加] オプションにフォーカスがある [操作] ウィンドウのスクリーンショット。
  6. 表示されるウィンドウで、マネージド モジュールに IIS_MOD_REQDATA という名前を付けます。モジュールの型は IIS_MOD_REQDATA.IIS_MOD_REQDATA (ドロップダウン リスト ボックスからこれを選択) にします。
    [名前] フィールドと [種類] フィールドを示す [管理モジュールの追加] ダイアログ ボックスのスクリーンショット。
  7. OK をクリックします。 新しくトレースされたモジュールは、Web サイトで使用するように構成されました。
    [モジュール] 画面のスクリーンショット。新しくトレースされたモジュールが表示されています。

手順 2: モジュールのテスト

Internet Explorer を開き、http://localhost/test.htm を参照してモジュールをテストします。 次のウィンドウが表示されます。

ここで読んでいる Web ページのスクリーンショットは、静的ファイル ハンドラーによって提供されるサンプル ページです。

"REQUEST HEADERS" と "RESPONSE HEADERS" のコンテンツはモジュールから取得され、それが機能することを示しています。

イベントの IIS へのルーティング

このタスクは、モジュールの TraceSource を IIS トレースにフックして、そのイベントが IIS を介して生成されるようにし、これらのトレース イベントをキャプチャするように失敗要求トレースを構成します。

手順 1: モジュール TraceSource の有効化とそのイベントの IIS へのルーティング

モジュールは、トレース イベントを含むように更新されます。 System.Diagnostics と IIS を構成して、これらのトレース イベントをキャプチャし、IIS の失敗した要求のトレース モジュールにルーティングします。 これを行うには、web.config ファイルの <system.diagnostics> セクションを構成して TraceSource を設定し、それに応じてイベントをルーティングします。

  1. 管理者コマンド プロンプトを使用して、c:\inetpub\wwwroot に移動し、メモ帳を使用して web.config ファイルを編集します。

  2. モジュールによって生成されたイベントを IIS のトレース インフラストラクチャにルーティングするには、構成の 3 つの部分を完了する必要があります。

    • IIS イベント traceListener の共有リスナーとしての定義
    • すべてのイベントを有効にするスイッチの定義
    • トレース ソースの定義、定義したスイッチのアタッチ、ソースのトレース リスナーの定義。
  3. IIS は、TraceSource イベントを IIS のトレース インフラストラクチャにルーティングするために使用される新しい System.Diagnostics.TraceListener を発行します。 このプロバイダーは、web.config ファイルでも定義する必要があります。

  4. traceSource を名前 (tsStatus) で定義し、DefaultSwitchIisTraceListener に接続します。

  5. この <system.Diagnostics> セクションをコピーし、web.config ファイルの診断セクション (<system.webServer> セクションの後) に貼り付けます。

    <system.diagnostics>
        <sharedListeners>
          <add name="IisTraceListener" type="System.Web.IisTraceListener, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </sharedListeners>
    
        <switches>
          <add name="DefaultSwitch" value="All" />
        </switches>
    
        <sources>
          <source name="tsStatus" switchName="DefaultSwitch">
            <listeners>
              <add name="IisTraceListener" type="System.Web.IisTraceListener, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            </listeners>
          </source>
        </sources>
    </system.diagnostics>
    

tsStatus traceSource は IIS7TraceListener に接続され、IIS のトレース インフラストラクチャにイベントを出力します。 次の手順に進み、失敗した要求のトレース プロバイダーにそれらのイベントを接続します。

手順 2: 失敗した要求のトレースからのモジュール トレース イベントのキャプチャの有効化

これらの診断イベントが IIS のトレース インフラストラクチャに出力されると、そのプロバイダーの ASP.net プロバイダーとモジュール フラグにマップされます。 詳細度は、使用される TraceEventType によって異なります。 失敗した要求のトレースを構成してこれらを選択するには、次の手順を実行します。

  1. 管理者コマンド プロンプトで、「start inetmgr」と入力します。 [接続] パネルで、コンピューター名、サイト フォルダーの順に展開し、[既定の Web サイト] を選択します。 [操作] ウィンドウの右側にある [構成] の下にある [失敗した要求のトレース] リンクを選択します。
    [操作] ウィンドウの [Web サイトの管理] セクションのスクリーンショット。[失敗した要求トレース] オプションが強調表示されています。

  2. 次のダイアログ ボックスで、次のように構成します。
    [Web サイトの失敗した要求トレース設定の編集] ダイアログ ボックスのスクリーンショット。

  3. [有効にする] チェック ボックスをオンにします。 その他の設定は既定値のままにします。 OK をクリックして続行します。

  4. 失敗した要求のトレース ログが有効になっていることを確認したので、エラー定義を構成する必要があります。 IIS マネージャーに戻り、[IIS] の下にある [失敗した要求トレースの規則] をダブルクリックします
    [失敗した要求トレース ルール] オプションが強調表示されている [既定の Web サイト ホーム] 画面のスクリーンショット。

  5. [操作] ウィンドウで、[追加] を選択します。 これにより、失敗した要求トレースの規則の追加ウィザードが起動します。

  6. [Specify Content to Trace]\(\トレースするコンテンツの指定) ページで、トレース対象の [すべてのコンテンツ (*)] オプションを選択します。 次へ をクリックします。
    [次へ] オプションにフォーカスがある [失敗した要求トレースルールの追加] ページのスクリーンショット。

  7. [Define Trace Conditions]\(\トレース条件の定義) 画面で、[ステータス コード] チェックボックスをオンにして、トレースするステータス コードとして「200」と入力します。
    [状態コード] フィールドがオンになっている [トレース条件の定義] 画面のスクリーンショット。

  8. 次へ をクリックします。 [Select Trace Providers]\(\トレース プロバイダーの選択) ページが表示されます。 [ASPNET] チェック ボックスをオンにし、[領域] の [モジュール] と [ページ] チェック ボックスをオンにします。 [詳細] で [詳細] を選択します。
    [トレース プロバイダーの選択] 画面のスクリーンショット。ASPNET プロバイダー オプションが強調表示されています。

    Note

    Server Beta 3 ビルドのバグにより、モジュール トレースは、モジュールとページの両方の領域が選択されている場合にのみキャプチャできます。 Server Beta 3 以降では、これらのイベントを収集するためのモジュールのみが必要です。

  9. [完了] をクリックします。 既定の Web サイトに関して、次の定義が表示されます。
    [失敗した要求トレース ルール] 画面のスクリーンショット。

結果のテストと表示

このタスクでは、失敗した要求を生成し、結果のトレース ログを表示します。 200 で失敗した http://localhost/* 要求のトレース ログをキャプチャするように IIS を構成したことを思い出してください。 機能することを確認するには、次の手順を実行します。

  1. 新しい Internet Explorer ウィンドウを開きます。 そのアドレス http://localhost/test.htm を入力します。 ここでも、次の内容が表示されます。
    Internet Explorer ウィンドウのサンプル Web ページのスクリーンショット。
  2. キャプチャされたトレースがモジュールによって生成されたことを確認するには、管理者特権の Internet Explorer ウィンドウを使用し、Ctrl キーを押しながら O キーを押し、c:\inetpub\logs\FailedReqLogFiles\W3SVC1 に移動します。 [HTML ファイル] を読み取るドロップダウン リスト ボックスで、[すべてのファイル] を選択します。
  3. 最新の fr######.xml ファイル (今日の日付) を選択し、[開く] を選択します。 次のイベントが表示されます。
    [要求診断] 画面のスクリーンショット。[カスタム モジュール トレース] タブが表示されています。

まとめ

新しいトレース イベントをマネージド モジュールに追加し、そのモジュールをコンパイルしてデプロイし、イベントを IIS のトレース インフラストラクチャにルーティングするように System.Diagnostics を構成し、最後に、イベントをキャプチャするように IIS の失敗した要求のトレース機能を構成しました。 モジュールに新しいイベントを簡単に追加し、モジュールを再コンパイルして \bin ディレクトリにデプロイできるようになりました。 失敗した要求のトレースを使用すると、イベントの結果が表示されます。

System.Diagnostics.TraceSource を使用すると、モジュールとそのトレース イベントは、モジュールを別のトレース リスナーにフックすれば、下位レベルでも使用できます。