次の方法で共有


例外とエラーの処理

例外は、サービスまたはクライアント実装内でエラーをローカルに通信するために使用されます。 一方、障害は、サーバーからクライアント、またはその逆など、サービス境界を越えてエラーを通信するために使用されます。 障害に加えて、トランスポート チャネルではトランスポート固有のメカニズムを使用して、トランスポート レベルのエラーを通信することがよくあります。 たとえば、HTTP トランスポートでは、404 などの状態コードを使用して、既存ではないエンドポイント URL を通信します (エラーを返すエンドポイントはありません)。 このドキュメントは、カスタム チャネル作成者にガイダンスを提供する 3 つのセクションで構成されています。 最初のセクションでは、例外を定義してスローするタイミングと方法に関するガイダンスを提供します。 2 番目のセクションでは、エラーの生成と使用に関するガイダンスを示します。 3 番目のセクションでは、実行中のアプリケーションのトラブルシューティングでカスタム チャネルのユーザーを支援するトレース情報を提供する方法について説明します。

例外

例外をスローするときは、2 つの点に留意する必要があります。まず、ユーザーが例外に適切に対応できる正しいコードを記述できる型である必要があります。 次に、ユーザーが問題の原因、障害の影響、および修正方法を理解するのに十分な情報を提供する必要があります。 次のセクションでは、Windows Communication Foundation (WCF) チャネルの例外の種類とメッセージに関するガイダンスを示します。 また、.NET の例外に関する一般的なガイダンスについては、例外の設計ガイドラインに関するドキュメントを参照してください。

例外の種類

チャネルによってスローされるすべての例外は、 System.TimeoutExceptionSystem.ServiceModel.CommunicationException、または CommunicationExceptionから派生した型である必要があります。 ( ObjectDisposedException などの例外もスローされる可能性がありますが、呼び出し元のコードがチャネルを誤用したことを示すためだけにスローされます。チャネルが正しく使用されている場合は、特定の例外のみをスローする必要があります)。WCF には、 CommunicationException から派生し、チャネルで使用するように設計された 7 つの例外の種類が用意されています。 システムの他の部分で使用されるように設計された他の CommunicationException派生例外があります。 これらの例外の種類は次のとおりです。

例外の種類 意味 内部例外コンテンツ 復旧戦略
AddressAlreadyInUseException リッスン用に指定されたエンドポイント アドレスは既に使用されています。 存在する場合は、この例外の原因となったトランスポート エラーの詳細を提供します。 例えば。 PipeExceptionHttpListenerException または SocketException 別のアドレスを試してください。
AddressAccessDeniedException このプロセスは、リッスン用に指定されたエンドポイント アドレスへのアクセスを許可されていません。 存在する場合は、この例外の原因となったトランスポート エラーの詳細を提供します。 たとえば、PipeException、または HttpListenerException です。 別の資格情報でログインを試してください。
CommunicationObjectFaultedException 使用されている ICommunicationObject は Faulted 状態です (詳細については、「 状態の変更について」を参照してください)。 保留中の呼び出しが複数あるオブジェクトが Faulted 状態に遷移すると、1 つの呼び出しのみがエラーに関連する例外をスローし、残りの呼び出しでは CommunicationObjectFaultedExceptionがスローされることに注意してください。 通常、この例外は、アプリケーションが何らかの例外を見落とし、既にエラーが発生したオブジェクト (元の例外をキャッチしたスレッド以外のスレッド) を使用しようとしたためにスローされます。 存在する場合は、内部例外に関する詳細が提供されます。 新しいオブジェクトを作成します。 最初に ICommunicationObject が障害を起こした原因によっては、回復に必要な他の作業が存在する可能性があることに注意してください。
CommunicationObjectAbortedException 使用されている ICommunicationObject は中止されました (詳細については、「 状態の変更について」を参照してください)。 CommunicationObjectFaultedExceptionと同様に、この例外は、アプリケーションがオブジェクト (場合によっては別のスレッドから) Abortを呼び出し、その理由でオブジェクトが使用できなくなったことを示します。 存在する場合は、内部例外に関する詳細が提供されます。 新しいオブジェクトを作成します。 最初に ICommunicationObject が中止された原因によっては、回復に必要な他の作業が存在する可能性があることに注意してください。
EndpointNotFoundException ターゲット リモート エンドポイントがリッスンしていません。 これは、エンドポイント アドレスの一部が正しくない、回復できない、またはエンドポイントがダウンしている可能性があります。 例としては、DNS エラー、Queue Manager が使用できない、サービスが実行されていないなどがあります。 内部例外は、通常は基になるトランスポートから詳細を提供します。 別のアドレスを試してください。 または、サービスがダウンした場合に備え、送信者はしばらく待ってから再試行することもできます
ProtocolException エンドポイントのポリシーで説明されているように、通信プロトコルはエンドポイント間で不一致です。 たとえば、フレーミング コンテンツ タイプの不一致や最大メッセージ サイズの超過などです。 存在する場合は、特定のプロトコル エラーに関する詳細情報を提供します。 たとえば、エラーの原因が MaxReceivedMessageSize を超える場合、 QuotaExceededException は内部例外です。 回復: 送信者と受信したプロトコルの設定が一致していることを確認します。 これを行う 1 つの方法は、サービス エンドポイントのメタデータ (ポリシー) を再インポートし、生成されたバインディングを使用してチャネルを再作成することです。
ServerTooBusyException リモート エンドポイントはリッスンしていますが、メッセージを処理する準備ができていません。 存在する場合、内部例外は SOAP エラーまたはトランスポート レベルのエラーの詳細を提供します。 回復: 後で操作を待機して再試行します。
TimeoutException タイムアウト期間内に操作を完了できませんでした。 タイムアウトに関する詳細を指定できます。 後で操作を待ってから再試行してください。

新しい例外の種類を定義するのは、その型が既存のすべての例外の種類とは異なる特定の回復戦略に対応する場合のみです。 新しい例外の種類を定義する場合は、 CommunicationException またはその派生クラスの 1 つから派生する必要があります。

例外メッセージ

例外メッセージはプログラムではなくユーザーを対象としているため、ユーザーが問題を理解して解決するのに役立つ十分な情報を提供する必要があります。 適切な例外メッセージの 3 つの重要な部分は次のとおりです。

どうされました。 ユーザーのエクスペリエンスに関連する用語を使用して、問題の明確な説明を入力します。 たとえば、不適切な例外メッセージは "無効な構成セクション" になります。 これにより、ユーザーは、どの構成セクションが正しくないのか、なぜ正しくないのか疑問に思う。 改善メッセージは「無効な構成セクション <customBinding>」です。 さらに良いメッセージは、"バインドに myTransport という名前のトランスポートが既に存在するため、myBinding という名前のバインドに myTransport という名前のトランスポートを追加できません" です。 これは、ユーザーがアプリケーションの構成ファイルで簡単に識別できる用語と名前を使用した非常に具体的なメッセージです。 ただし、いくつかの重要なコンポーネントがまだ不足しています。

誤差の有意性。 エラーの意味がメッセージに明確に示されていない限り、ユーザーは致命的なエラーかどうか、または無視できるかどうか疑問に思う可能性があります。 一般に、メッセージはエラーの意味や重要性を先頭に置くべきです。 前の例を改善するために、次のようなメッセージが考えられます:「構成エラーにより ServiceHost のオープンに失敗しました。myTransport という名前のトランスポートを myBinding という名前のバインドに追加できません。バインドにはすでに myTransport という名前のトランスポートが存在しています。」

ユーザーが問題を修正する方法。 メッセージの最も重要な部分は、ユーザーが問題を解決するのを支援することです。 メッセージには、問題を解決するために確認または修正する内容に関するいくつかのガイダンスまたはヒントが含まれている必要があります。 たとえば、「ServiceHostは、設定エラーが原因でオープンに失敗しました: すでにmyTransportという名前のトランスポートがあるため、myBindingという名前のバインディングにmyTransportという名前のトランスポートを追加することができません。」 バインディングに含まれているトランスポートが 1 つだけであることを確認してください" というメッセージにします。

エラーの伝達

SOAP 1.1 と SOAP 1.2 はどちらも、障害の特定の構造を定義します。 2 つの仕様にはいくつかの違いがありますが、一般に、エラーの作成と使用には Message 型と MessageFault 型が使用されます。

SOAP 1.2 障害および SOAP 1.1 障害
SOAP 1.2 エラー (左) と SOAP 1.1 エラー (右)。 SOAP 1.1 では、Fault 要素のみが名前空間修飾されます。

SOAP は、エラー メッセージを、エラー要素 (名前が <env:Fault>の要素) のみを含むメッセージとして、 <env:Body>の子として定義します。 図 1 に示すように、エラー要素の内容は SOAP 1.1 と SOAP 1.2 の間で若干異なります。 ただし、 System.ServiceModel.Channels.MessageFault クラスは、これらの違いを 1 つのオブジェクト モデルに正規化します。

public abstract class MessageFault  
{  
    protected MessageFault();  
  
    public virtual string Actor { get; }  
    public virtual string Node { get; }  
    public static string DefaultAction { get; }  
    public abstract FaultCode Code { get; }  
    public abstract bool HasDetail { get; }  
    public abstract FaultReason Reason { get; }  
  
    public T GetDetail<T>();  
    public T GetDetail<T>( XmlObjectSerializer serializer);  
    public System.Xml.XmlDictionaryReader GetReaderAtDetailContents();  
  
    // other methods omitted  
}  

Code プロパティは、env:Code (または SOAP 1.1 のfaultCode) に対応し、エラーの種類を識別します。 SOAP 1.2 では、 faultCode の 5 つの許容値 (Sender や Receiver など) を定義し、サブコード値を含めることができる Subcode 要素を定義します。 (許容されるエラー コードとその意味の一覧については、 SOAP 1.2 の仕様 を参照してください)。SOAP 1.1 には、少し異なるメカニズムがあります。4 つの faultCode 値 (クライアントとサーバーなど) を定義します。これは、まったく新しいものを定義するか、ドット表記を使用して、より具体的な faultCodes (Client.Authentication など) を作成することによって拡張できます。

MessageFault を使用してエラーをプログラムすると、FaultCode.Name と FaultCode.Namespace は、SOAP 1.2 env:Code または SOAP 1.1 faultCodeの名前と名前空間にマップされます。 FaultCode.SubCode は SOAP 1.2 の env:Subcode にマップされ、SOAP 1.1 の場合は null です。

プログラムでエラーを区別するのが興味深い場合は、新しい障害サブコード (または SOAP 1.1 を使用している場合は新しい障害コード) を作成する必要があります。 これは、新しい例外の種類の作成に似ています。 SOAP 1.1 エラー コードではドット表記を使用しないでください。 ( WS-I 基本プロファイル では、エラー コードのドット表記の使用も推奨されません)。

public class FaultCode  
{  
    public FaultCode(string name);  
    public FaultCode(string name, FaultCode subCode);  
    public FaultCode(string name, string ns);  
    public FaultCode(string name, string ns, FaultCode subCode);  
  
    public bool IsPredefinedFault { get; }  
    public bool IsReceiverFault { get; }  
    public bool IsSenderFault { get; }  
    public string Name { get; }  
    public string Namespace { get; }  
    public FaultCode SubCode { get; }  
  
//  methods omitted  
  
}  

Reason プロパティは、例外のメッセージに似たエラー状態の人間が判読できる説明であるenv:Reason (または SOAP 1.1 のfaultString) に対応します。 FaultReason クラス (および SOAP env:Reason/faultString) には、グローバリゼーションのために複数の翻訳を行うサポートが組み込まれています。

public class FaultReason  
{  
    public FaultReason(FaultReasonText translation);  
    public FaultReason(IEnumerable<FaultReasonText> translations);  
    public FaultReason(string text);  
  
    public SynchronizedReadOnlyCollection<FaultReasonText> Translations
    {
       get;
    }  
  
 }  

エラー詳細の内容は、 GetDetail<T> や GetReaderAtDetailContents() などのさまざまなメソッドを使用して MessageFault で公開されます。 障害の詳細は、障害に関する追加の詳細を伝達するための不透明な要素です。 障害に関連する特定の構造化された情報を保持したい場合に便利です。

エラーの生成

このセクションでは、チャネルまたはチャネルによって作成されたメッセージ プロパティで検出されたエラー状態に応答してエラーを生成するプロセスについて説明します。 一般的な例として、無効なデータを含む要求メッセージに応答してエラーが返されます。

エラーを生成する場合、カスタム チャネルはエラーを直接送信するのではなく、例外をスローし、上記のレイヤーがその例外をエラーに変換するかどうかと送信する方法を決定させる必要があります。 この変換を支援するために、チャネルは、カスタム チャネルによってスローされた例外を適切なエラーに変換できる FaultConverter 実装を提供する必要があります。 FaultConverter は、次のように定義されます。

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                   MessageVersion version);  
    protected abstract bool OnTryCreateFaultMessage(  
                                   Exception exception,
                                   out Message message);  
    public bool TryCreateFaultMessage(  
                                   Exception exception,
                                   out Message message);  
}  

カスタム エラーを生成する各チャネルは、 FaultConverter を実装し、 GetProperty<FaultConverter>の呼び出しから返す必要があります。 カスタム OnTryCreateFaultMessage 実装では、例外をエラーに変換するか、内部チャネルの FaultConverterにデリゲートする必要があります。 チャネルがトランスポートである場合は、例外またはデリゲートをエンコーダーの FaultConverter または WCF で提供される既定の FaultConverter に変換する必要があります。 既定の FaultConverter は、WS-Addressing および SOAP で指定されたエラー メッセージに対応するエラーを変換します。 OnTryCreateFaultMessage実装の例を次に示します。

public override bool OnTryCreateFaultMessage(Exception exception,
                                             out Message message)  
{  
    if (exception is ...)  
    {  
        message = ...;  
        return true;  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =
                    this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&
        (encoderConverter.TryCreateFaultMessage(  
         exception, out message)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =
                   FaultConverter.GetDefaultFaultConverter(  
                   this.channel.messageVersion);  
    return defaultConverter.TryCreateFaultMessage(  
                   exception,
                   out message);  
#else  
    FaultConverter inner =
                   this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateFaultMessage(exception, out message);  
    }  
    else  
    {  
        message = null;  
        return false;  
    }  
#endif  
}  

このパターンの影響は、エラーが必要なエラー状態に対してレイヤー間でスローされる例外には、対応する障害ジェネレーターが正しい障害を作成するための十分な情報が含まれている必要があるということです。 カスタム チャネルの作成者は、このような例外がまだ存在しない場合に、異なる障害状態に対応する例外の種類を定義できます。 チャネル レイヤーを通過する例外は、不透明な障害データではなく、エラー状態を伝える必要があることに注意してください。

障害カテゴリ

一般に、障害には次の 3 つのカテゴリがあります。

  1. スタック全体に広がる障害。 これらのエラーは、チャネル スタック内の任意のレイヤー (InvalidCardinalityAddressingException など) で発生する可能性があります。

  2. フローされたトランザクションやセキュリティ ロールに関連するいくつかのエラーなど、スタック内の特定のレイヤーの上の任意の場所で発生する可能性があるエラー。

  3. スタック内の単一レイヤーに限定される障害、例えば WS-RM のシーケンス番号に関するエラーなど。

カテゴリ 1。 障害は通常、WS-Addressing および SOAP エラーです。 WCF によって提供される基本 FaultConverter クラスは、WS-Addressing および SOAP で指定されたエラー メッセージに対応するエラーを変換するため、これらの例外の変換を自分で処理する必要はありません。

カテゴリ 2。 エラーは、レイヤーがそのレイヤーに関連するメッセージ情報を完全に使用しないプロパティをメッセージに追加するときに発生します。 エラーは、後で上位レイヤーがメッセージ情報をさらに処理するようにメッセージ プロパティに要求したときに検出される場合があります。 このようなチャネルでは、前に指定した GetProperty を実装して、上位のレイヤーが正しい障害を返せるようにする必要があります。 その例として、TransactionMessageProperty があります。 このプロパティは、ヘッダー内のすべてのデータを完全に検証せずにメッセージに追加されます (これを行うには、分散トランザクション コーディネーター (DTC) に接続する必要があります)。

カテゴリ 3. 障害は、プロセッサ内の 1 つのレイヤーによってのみ生成および送信されます。 したがって、すべての例外はレイヤー内に含まれます。 チャネル間の整合性を向上させ、メンテナンスを容易にするには、カスタム チャネルでは、内部障害の場合でも、以前に指定したパターンを使用してエラー メッセージを生成する必要があります。

受信したエラーの解釈

このセクションでは、エラー メッセージを受信するときに適切な例外を生成するためのガイダンスを提供します。 スタック内のすべての層でメッセージを処理するためのデシジョン ツリーは次のとおりです。

  1. レイヤーがメッセージを無効と見なす場合、レイヤーは "無効なメッセージ" 処理を行う必要があります。 このような処理はレイヤーに固有ですが、メッセージの破棄、トレース、または例外をスローしてそれをエラーに変換することが含まれる場合があります。 たとえば、セキュリティが適切に保護されていないメッセージを受信する場合や、RM が不適切なシーケンス番号のメッセージを受信する場合などです。

  2. それ以外の場合、メッセージがレイヤーに特に適用されるエラー メッセージであり、メッセージがレイヤーの相互作用の外部で意味を持たない場合、レイヤーはエラー状態を処理する必要があります。 その例として、RM チャネルの上位層には意味のない RM シーケンス拒否障害があり、これが RM チャネルの障害を引き起こし、保留中の操作を中断することを意味します。

  3. それ以外の場合は、Request() または Receive() からメッセージを返す必要があります。 これには、レイヤーが障害を認識するが、エラーは要求が失敗したことを示すだけで、チャネルの障害と保留中の操作からのスローを意味しないケースが含まれます。 このような場合の使いやすさを向上させるために、レイヤーはGetProperty<FaultConverter>を実装し、FaultConverterをオーバーライドしてエラーを例外に変換できるOnTryCreateException派生クラスを返す必要があります。

次のオブジェクト モデルでは、メッセージを例外に変換できます。

public class FaultConverter  
{  
    public static FaultConverter GetDefaultFaultConverter(  
                                  MessageVersion version);  
    protected abstract bool OnTryCreateException(  
                                 Message message,
                                 MessageFault fault,
                                 out Exception exception);  
    public bool TryCreateException(  
                                 Message message,
                                 MessageFault fault,
                                 out Exception exception);  
}  

チャネル 層は、エラー メッセージの例外への変換をサポートする GetProperty<FaultConverter> を実装できます。 これを行うには、 OnTryCreateException をオーバーライドし、エラー メッセージを調べます。 認識された場合は変換を行い、それ以外の場合は内部チャネルに変換を依頼します。 トランスポート チャネルは、既定の SOAP/WS-Addressing FaultConverter を取得するために、 FaultConverter.GetDefaultFaultConverter に委任する必要があります。

一般的な実装は次のようになります。

public override bool OnTryCreateException(  
                            Message message,
                            MessageFault fault,
                            out Exception exception)  
{  
    if (message.Action == "...")  
    {  
        exception = ...;  
        return true;  
    }  
    // OR  
    if ((fault.Code.Name == "...") && (fault.Code.Namespace == "..."))  
    {  
        exception = ...;  
        return true;  
    }  
  
    if (fault.IsMustUnderstand)  
    {  
        if (fault.WasHeaderNotUnderstood(  
                   message.Headers, "...", "..."))  
        {  
            exception = new ProtocolException(...);  
            return true;  
        }  
    }  
  
#if IMPLEMENTING_TRANSPORT_CHANNEL  
    FaultConverter encoderConverter =
              this.encoder.GetProperty<FaultConverter>();  
    if ((encoderConverter != null) &&
        (encoderConverter.TryCreateException(  
                              message, fault, out exception)))  
    {  
        return true;  
    }  
  
    FaultConverter defaultConverter =  
             FaultConverter.GetDefaultFaultConverter(  
                             this.channel.messageVersion);  
    return defaultConverter.TryCreateException(  
                             message, fault, out exception);  
#else  
    FaultConverter inner =
                    this.innerChannel.GetProperty<FaultConverter>();  
    if (inner != null)  
    {  
        return inner.TryCreateException(message, fault, out exception);  
    }  
    else  
    {  
        exception = null;  
        return false;  
    }  
#endif  
}  

個別の復旧シナリオがある特定の障害状態の場合は、 ProtocolExceptionの派生クラスを定義することを検討してください。

MustUnderstand の処理

SOAP は、必要なヘッダーが受信側によって認識されなかったことを通知するための一般的なエラーを定義します。 この障害は、 mustUnderstand 障害と呼ばれます。 WCF では、カスタム チャネルによって mustUnderstand エラーが生成されることはありません。 代わりに、WCF 通信スタックの上部にある WCF ディスパッチャーは、MustUnderstand=true とマークされたすべてのヘッダーが基になるスタックによって認識されたことを確認します。 認識されなかった場合は、その時点で mustUnderstand エラーが生成されます。 (ユーザーはこの mustUnderstand 処理をオフにして、アプリケーションにすべてのメッセージ ヘッダーを受信させることができます。その場合、アプリケーションは mustUnderstand 処理を実行する必要があります。生成されたエラーには、認識されなかった MustUnderstand=true のすべてのヘッダーの名前を含む NotUnderstood ヘッダーが含まれています。

プロトコル チャネルが MustUnderstand=true のカスタム ヘッダーを送信し、 mustUnderstand エラーを受け取った場合、そのエラーが送信されたヘッダーによるものかどうかを判断する必要があります。 MessageFault クラスには、次の 2 つのメンバーが役立ちます。

public class MessageFault  
{  
    ...  
    public bool IsMustUnderstandFault { get; }  
    public static bool WasHeaderNotUnderstood(MessageHeaders headers,
        string name, string ns) { }  
    ...  
  
}  

IsMustUnderstandFaultは、障害がtrue障害の場合はmustUnderstandを返します。 WasHeaderNotUnderstood は、指定した名前と名前空間を持つヘッダーが NotUnderstood ヘッダーとしてエラーに含まれている場合、 true を返します。 それ以外の場合は、falseを返します。

チャネルが MustUnderstand = true とマークされているヘッダーを出力する場合、そのレイヤーは例外生成 API パターンも実装し、そのヘッダーによって引き起こされる mustUnderstand エラーを前述のようにより便利な例外に変換する必要があります。

追跡

.NET Framework には、デバッガーをアタッチしてコードをステップ実行できない運用アプリケーションや断続的な問題の診断を支援する方法として、プログラムの実行をトレースするメカニズムが用意されています。 このメカニズムのコア コンポーネントは、 System.Diagnostics 名前空間にあり、次の要素で構成されます。

コンポーネントのトレース

カスタム チャネルからのトレース

カスタム チャネルでは、実行中のアプリケーションにデバッガーをアタッチできない場合の問題の診断に役立つトレース メッセージを書き出す必要があります。 これには、 TraceSource をインスタンス化し、そのメソッドを呼び出してトレースを書き込むという 2 つの大まかなタスクが含まれます。

TraceSourceをインスタンス化すると、指定した文字列がそのソースの名前になります。 この名前は、トレース ソースの構成 (トレース レベルの有効化/無効化/設定) に使用されます。 また、トレース出力自体にも表示されます。 カスタム チャネルでは、トレース出力の閲覧者がトレース情報の送信元を理解できるように、一意のソース名を使用する必要があります。 情報を書き込むアセンブリの名前をトレース ソースの名前として使用することが一般的な方法です。 たとえば、WCF は System.ServiceModel アセンブリから書き込まれた情報のトレース ソースとして System.ServiceModel を使用します。

トレース ソースを取得したら、その TraceDataTraceEvent、または TraceInformation メソッドを呼び出して、トレース エントリをトレース リスナーに書き込みます。 作成するトレース エントリごとに、イベントの種類を、 TraceEventTypeで定義されているイベントの種類の 1 つとして分類する必要があります。 この分類と構成のトレース レベルの設定によって、トレース エントリがリスナーに出力されるかどうかが決まります。 たとえば、構成のトレース レベルを Warning に設定すると、 WarningError 、および Critical トレース エントリを書き込むことが可能になりますが、Information エントリと Verbose エントリはブロックされます。 トレース ソースをインスタンス化し、情報レベルでエントリを書き出す例を次に示します。

using System.Diagnostics;  
//...  
TraceSource udpSource = new TraceSource("Microsoft.Samples.Udp");  
//...  
udpsource.TraceInformation("UdpInputChannel received a message");  

Von Bedeutung

トレース出力リーダーが出力元を理解できるように、カスタム チャネルに固有のトレース ソース名を指定することを強くお勧めします。

トレース ビューアーとの統合

チャネルによって生成されたトレースは、トレース リスナーとしてを使用してSystem.Diagnostics.XmlWriterTraceListener で読み取り可能な形式で出力できます。 これは、チャネル開発者が行う必要があるものではありません。 代わりに、アプリケーションの構成ファイルでこのトレース リスナーを構成する必要があるアプリケーション ユーザー (またはアプリケーションのトラブルシューティングを行うユーザー) です。 たとえば、次の構成では、 System.ServiceModelMicrosoft.Samples.Udp の両方から TraceEventsFile.e2e という名前のファイルにトレース情報が出力されます。

<configuration>  
  <system.diagnostics>  
    <sources>  
      <!-- configure System.ServiceModel trace source -->  
      <source name="System.ServiceModel" switchValue="Verbose"
              propagateActivity="true">  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
      <!-- configure Microsoft.Samples.Udp trace source -->  
      <source name="Microsoft.Samples.Udp" switchValue="Verbose" >  
        <listeners>  
          <add name="e2e" />  
        </listeners>  
      </source>  
    </sources>  
    <!--   
    Define a shared trace listener that outputs to TraceFile.e2e  
    The listener name is e2e   
    -->  
    <sharedListeners>  
      <add name="e2e" type="System.Diagnostics.XmlWriterTraceListener"  
        initializeData=".\TraceFile.e2e"/>  
    </sharedListeners>  
    <trace autoflush="true" />  
  </system.diagnostics>  
</configuration>  

構造化データのトレース

System.Diagnostics.TraceSource には、トレース エントリに含める 1 つ以上のオブジェクトを受け取る TraceData メソッドがあります。 一般に、 Object.ToString メソッドは各オブジェクトで呼び出され、結果の文字列はトレース エントリの一部として書き込まれます。 System.Diagnostics.XmlWriterTraceListenerを使用してトレースを出力する場合は、System.Xml.XPath.IXPathNavigableをデータ オブジェクトとしてTraceDataに渡すことができます。 結果のトレース エントリには、 System.Xml.XPath.XPathNavigatorによって提供される XML が含まれます。 XML アプリケーション データを含むエントリの例を次に示します。

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">  
  <System xmlns="...">  
    <EventID>12</EventID>  
    <Type>3</Type>  
    <SubType Name="Information">0</SubType>  
    <Level>8</Level>  
    <TimeCreated SystemTime="2006-01-13T22:58:03.0654832Z" />  
    <Source Name="Microsoft.ServiceModel.Samples.Udp" />  
    <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />  
    <Execution  ProcessName="UdpTestConsole"
                ProcessID="3348" ThreadID="4" />  
    <Channel />  
    <Computer>COMPUTER-LT01</Computer>  
  </System>  
<!-- XML application data -->  
  <ApplicationData>  
  <TraceData>  
   <DataItem>  
   <TraceRecord
     Severity="Information"  
     xmlns="…">  
        <TraceIdentifier>some trace id</TraceIdentifier>  
        <Description>EndReceive called</Description>  
        <AppDomain>UdpTestConsole.exe</AppDomain>  
        <Source>UdpInputChannel</Source>  
      </TraceRecord>  
    </DataItem>  
  </TraceData>  
  </ApplicationData>  
</E2ETraceEvent>  

WCF トレース ビューアーは、前に示した TraceRecord 要素のスキーマを理解し、その子要素からデータを抽出し、表形式で表示します。 アプリケーションの構造化データをトレースしてSvctraceviewer.exeユーザーがデータを読めるようにする際には、チャネルでこのスキーマを使用する必要があります。