예외는 서비스 또는 클라이언트 구현 내에서 로컬로 오류를 전달하는 데 사용됩니다. 반면에 오류는 서버에서 클라이언트로 또는 그 반대로 서비스 경계를 넘어 오류를 전달하는 데 사용됩니다. 전송 채널은 오류 외에도 전송 관련 메커니즘을 사용하여 전송 수준 오류를 전달하는 경우가 많습니다. 예를 들어 HTTP 전송은 404와 같은 상태 코드를 사용하여 존재하지 않는 엔드포인트 URL을 통신합니다(오류를 다시 보낼 엔드포인트가 없음). 이 문서는 사용자 지정 채널 작성자에게 지침을 제공하는 세 개의 섹션으로 구성됩니다. 첫 번째 섹션에서는 예외를 정의하고 throw하는 시기와 방법에 대한 지침을 제공합니다. 두 번째 섹션에서는 오류를 생성하고 처리하는 방법에 대한 지침을 제공합니다. 세 번째 섹션에서는 실행 중인 애플리케이션 문제 해결에 사용자 지정 채널의 사용자를 돕기 위해 추적 정보를 제공하는 방법을 설명합니다.
예외
예외를 throw할 때 유의해야 할 두 가지 사항이 있습니다. 먼저 사용자가 예외에 적절하게 대응할 수 있는 올바른 코드를 작성할 수 있는 형식이어야 합니다. 둘째, 사용자가 무엇이 잘못되었는지, 실패에 미치는 영향 및 해결 방법을 이해할 수 있는 충분한 정보를 제공해야 합니다. 다음 섹션에서는 WCF(Windows Communication Foundation) 채널에 대한 예외 유형 및 메시지에 대한 지침을 제공합니다. 예외에 대한 디자인 지침 문서의 .NET에서 예외에 대한 일반적인 지침도 있습니다.
예외 형식
채널에서 throw되는 모든 예외는 System.TimeoutException 또는 System.ServiceModel.CommunicationException이거나 CommunicationException에서 파생된 형식이어야 합니다. (ObjectDisposedException 예외가 발생할 수 있지만, 이는 호출 코드가 채널을 오용했음을 나타내기 위한 것입니다. 채널이 올바르게 사용된 경우, 지정된 예외만 발생해야 합니다.) WCF는 채널에서 사용되도록 설계된 CommunicationException에서 파생된 7가지의 예외 유형을 제공합니다. 시스템의 다른 부분에서 사용하도록 설계된 다른 CommunicationException파생 예외가 있습니다. 이러한 예외 유형은 다음과 같습니다.
예외 유형 | 의미 | 내부 예외 콘텐츠 | 복구 전략 |
---|---|---|---|
AddressAlreadyInUseException | 수신 대기에 지정된 엔드포인트 주소가 이미 사용 중입니다. | 있는 경우 이 예외를 발생시킨 전송 오류에 대한 자세한 정보를 제공합니다. 예를 들어. PipeException, HttpListenerException 또는 SocketException. | 다른 주소를 사용해 보세요. |
AddressAccessDeniedException | 이 프로세스는 수신 대기에 지정된 엔드포인트 주소에 액세스할 수 없습니다. | 있는 경우 이 예외를 발생시킨 전송 오류에 대한 자세한 정보를 제공합니다. 예를 들면 PipeException 또는 HttpListenerException과 같습니다. | 다른 자격 증명을 사용해 보세요. |
CommunicationObjectFaultedException | ICommunicationObject 사용 중인 상태는 오류 상태입니다(자세한 내용은 상태 변경 내용 이해 참조). 보류 중인 호출이 여러 개 있는 객체가 Faulted 상태로 전환되면, 오류와 관련된 예외는 하나의 호출에서만 throw되고 나머지 호출은 CommunicationObjectFaultedException을(를) throw합니다. 이 예외는 일반적으로 애플리케이션이 특정 예외를 인식하지 못하고 원래 예외를 잡아낸 스레드와 다른 스레드에서 이미 오류가 발생한 개체를 사용하려고 하기 때문에 발생합니다. | 있는 경우 내부 예외에 대한 세부 정보를 제공합니다. | 새 개체를 만듭니다. 처음에 오류가 발생한 원인 ICommunicationObject 에 따라 복구해야 하는 다른 작업이 있을 수 있습니다. |
CommunicationObjectAbortedException | 사용 중인 항목이 ICommunicationObject 취소되었습니다(자세한 내용은 상태 변경 이해하기 참조). 이 예외는 CommunicationObjectFaultedException와 유사하게 애플리케이션이 개체를 호출 Abort 했을 때, 아마도 다른 스레드에서 호출했기 때문에 개체를 더 이상 사용할 수 없음을 나타냅니다. | 있는 경우 내부 예외에 대한 세부 정보를 제공합니다. | 새 개체를 만듭니다. 유의하십시오, 처음에 ICommunicationObject가 중단된 원인에 따라 복구를 위해 추가적으로 필요한 작업이 있을 수 있습니다. |
EndpointNotFoundException | 대상 원격 엔드포인트가 수신 대기하지 않습니다. 이로 인해 엔드포인트 주소의 일부가 올바르지 않거나, 복구할 수 없거나, 엔드포인트가 다운될 수 있습니다. 예를 들어 DNS 오류, 큐 관리자를 사용할 수 없음 및 서비스가 실행되고 있지 않습니다. | 내부 예외는 일반적으로 기본 전송에서 세부 정보를 제공합니다. | 다른 주소를 사용해 보세요. 또는 발신자가 잠시 기다렸다가 서비스가 중단된 경우 다시 시도할 수 있습니다. |
ProtocolException | 엔드포인트의 정책에 설명된 대로 통신 프로토콜은 엔드포인트 간에 일치하지 않습니다. 예를 들어 프레이밍 콘텐츠 형식이 일치하지 않거나 최대 메시지 크기가 초과되었습니다. | 있는 경우 특정 프로토콜 오류에 대한 자세한 정보를 제공합니다. 예를 들어 오류 QuotaExceededException 원인이 MaxReceivedMessageSize를 초과하는 경우의 내부 예외입니다. | 복구: 보낸 사람 및 수신된 프로토콜 설정이 일치하는지 확인합니다. 이 작업을 수행하는 한 가지 방법은 서비스 엔드포인트의 메타데이터(정책)를 다시 가져오고 생성된 바인딩을 사용하여 채널을 다시 만드는 것입니다. |
ServerTooBusyException | 원격 엔드포인트가 수신 대기 중이지만 메시지를 처리할 준비가 되지 않았습니다. | 있는 경우 내부 예외는 SOAP 오류 또는 전송 수준 오류 세부 정보를 제공합니다. | 복구: 나중에 작업을 기다렸다가 다시 시도합니다. |
TimeoutException | 시간 제한 기간 내에 작업을 완료하지 못했습니다. | 시간 제한에 대한 세부 정보를 제공할 수 있습니다. | 잠시 기다렸다가 나중에 작업을 다시 시도합니다. |
해당 형식이 모든 기존 예외 형식과 다른 특정 복구 전략에 해당하는 경우에만 새 예외 형식을 정의합니다. 새 예외 형식을 정의할 때, 반드시 CommunicationException 또는 그 파생 클래스 중 하나에서 파생되어야 합니다.
예외 메시지
예외 메시지는 프로그램이 아닌 사용자를 대상으로 하므로 사용자가 문제를 이해하고 해결하는 데 도움이 되는 충분한 정보를 제공해야 합니다. 좋은 예외 메시지의 세 가지 필수 부분은 다음과 같습니다.
무슨 일이 있었나요. 사용자 환경과 관련된 용어를 사용하여 문제에 대한 명확한 설명을 제공합니다. 예를 들어 잘못된 예외 메시지는 "잘못된 구성 섹션"입니다. 이로 인해 사용자는 어떤 구성 섹션이 올바르지 않은지, 왜 잘못된지 궁금하게 만듭니다. 향상된 메시지는 "잘못된 구성 섹션 <customBinding>"입니다. 더 나은 메시지는 "바인딩에 myTransport라는 전송이 이미 있으므로 myBinding이라는 바인딩에 myTransport라는 전송을 추가할 수 없습니다."입니다. 사용자가 애플리케이션의 구성 파일에서 쉽게 식별할 수 있는 용어와 이름을 사용하는 매우 구체적인 메시지입니다. 그러나 여전히 몇 가지 주요 구성 요소가 누락되어 있습니다.
오류의 중요성 메시지가 오류의 의미를 명확하게 표시하지 않는 한 사용자는 심각한 오류인지 아니면 무시할 수 있는지 궁금해할 수 있습니다. 일반적으로 메시지는 오류의 의미 또는 중요성을 나타내야 합니다. 이전 예제를 개선하기 위해 "구성 오류로 인해 ServiceHost를 열지 못했습니다. 바인딩에 myTransport라는 전송이 이미 있으므로 myBinding이라는 바인딩에 myTransport라는 전송을 추가할 수 없습니다."라는 메시지가 표시될 수 있습니다.
사용자가 문제를 해결하는 방법. 메시지의 가장 중요한 부분은 사용자가 문제를 해결하는 데 도움이 되는 것입니다. 메시지에는 문제를 해결하기 위해 확인하거나 수정할 항목에 대한 몇 가지 지침이나 힌트가 포함되어야 합니다. 예를 들어 "ServiceHost가 구성 오류로 인해 열리지 못했습니다. 바인딩에 myTransport라는 전송이 이미 있으므로 myBinding이라는 바인딩에 myTransport라는 전송을 추가할 수 없습니다. 바인딩에 전송 방식이 하나만 있는지 확인하세요.
오류 전달
SOAP 1.1 및 SOAP 1.2는 모두 오류에 대한 특정 구조를 정의합니다. 두 사양 간에는 몇 가지 차이점이 있지만 일반적으로 Message 및 MessageFault 형식은 오류 생성 및 소비에 사용됩니다.
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 이러한 차이를 하나의 개체 모델로 정규화합니다.
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는 5개의 허용 가능한 값 faultCode
(예: Sender 및 Receiver)을 정의하고 모든 하위 코드 값을 포함할 수 있는 요소를 정의합니다 Subcode
. (허용되는 오류 코드 목록 및 해당 의미는 SOAP 1.2 사양을 참조하세요.) SOAP 1.1에는 약간 다른 메커니즘이 있습니다. 완전히 새로운 값을 정의하거나 점 표기법을 사용하여 확장faultCode
할 수 있는 4개의 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
클래스(및 SOAPenv:Reason/faultString
)는 세계화를 위해 여러 번역을 기본적으로 지원합니다.
public class FaultReason
{
public FaultReason(FaultReasonText translation);
public FaultReason(IEnumerable<FaultReasonText> translations);
public FaultReason(string text);
public SynchronizedReadOnlyCollection<FaultReasonText> Translations
{
get;
}
}
오류 세부 정보 콘텐츠는 TGetDetail
및 <()를 비롯한 다양한 메서드를 사용하여 MessageFault에 >GetReaderAtDetailContents
노출됩니다. 오류 세부 정보는 오류에 대한 추가 세부 정보를 전달하기 위한 불투명 요소입니다. 이 기능은 오류와 함께 수행하려는 임의의 구조화된 세부 정보가 있는 경우에 유용합니다.
오류 생성
이 섹션에서는 채널 또는 채널에서 만든 메시지 속성에서 검색된 오류 조건에 대한 응답으로 오류를 생성하는 프로세스를 설명합니다. 일반적인 예는 잘못된 데이터가 포함된 요청 메시지에 대한 응답으로 오류를 다시 보내는 것입니다.
오류를 생성할 때 사용자 지정 채널은 오류를 직접 보내지 않아야 하며, 대신 예외를 throw하고 위의 계층에서 해당 예외를 오류로 변환할지 여부와 보내는 방법을 결정하도록 해야 합니다. 이 변환을 지원하기 위해 채널은 사용자 지정 채널에서 throw한 예외를 적절한 오류로 변환할 수 있는 구현을 제공해야 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
}
이 패턴의 의미는 오류가 필요한 오류 조건에 대해 계층 간에 throw되는 예외에 해당 오류 생성기가 올바른 오류를 만들 수 있는 충분한 정보를 포함해야 한다는 것입니다. 사용자 지정 채널 작성자는 이러한 예외가 아직 없는 경우 다른 오류 조건에 해당하는 예외 유형을 정의할 수 있습니다. 채널 계층을 트래버스하는 예외는 불투명한 오류 데이터가 아닌 오류 조건을 전달해야 합니다.
오류 범주
일반적으로 다음과 같은 세 가지 범주의 오류가 있습니다.
전체 스택에 걸쳐 만연한 오류입니다. 이러한 오류는 채널 스택의 모든 계층(예: InvalidCardinalityAddressingException)에서 발생할 수 있습니다.
스택의 특정 계층 위에서 발생할 수 있는 오류(예: 흐름된 트랜잭션 또는 보안 역할과 관련된 일부 오류).
스택의 단일 계층에서 전달되는 오류(예: WS-RM 시퀀스 번호 오류와 같은 오류).
범주 1. 오류는 일반적으로 WS-Addressing 오류와 SOAP 오류입니다. WCF에서 제공하는 기본 FaultConverter
클래스는 WS-Addressing 및 SOAP에서 지정한 오류 메시지에 해당하는 오류를 변환하므로 이러한 예외의 변환을 직접 처리할 필요가 없습니다.
범주 2. 계층이 해당 계층과 관련된 메시지 정보를 완전히 사용하지 않는 속성이 메시지에 추가되면 오류가 발생합니다. 더 높은 계층이 메시지 속성을 요청하여 메시지 정보를 추가로 처리하도록 요청하면 나중에 오류가 검색될 수 있습니다. 이러한 채널은 상위 계층이 GetProperty
을 통해 정확한 오류를 다시 보낼 수 있도록 이전에 지정된 사항을 구현해야 합니다. 이 예제는 TransactionMessageProperty입니다. 이 속성은 헤더의 모든 데이터의 유효성을 완전히 검사하지 않고 메시지에 추가됩니다(이렇게 하면 DTC(분산 트랜잭션 코디네이터)에 문의할 수 있습니다.
범주 3. 오류는 프로세서의 단일 계층에서만 생성되고 전송됩니다. 따라서 모든 예외가 계층 내에 포함됩니다. 채널 간의 일관성을 개선하고 유지 관리를 용이하게 하려면 사용자 지정 채널이 이전에 지정한 패턴을 사용하여 내부 오류에 대해서도 오류 메시지를 생성해야 합니다.
받은 오류 해석
이 섹션에서는 오류 메시지를 받을 때 적절한 예외를 생성하기 위한 지침을 제공합니다. 스택의 모든 계층에서 메시지를 처리하기 위한 의사 결정 트리는 다음과 같습니다.
계층이 메시지를 유효하지 않다고 간주하는 경우 계층은 해당 '잘못된 메시지' 처리를 수행해야 합니다. 이러한 처리는 계층에 특화되어 있으며 메시지 삭제, 추적 또는 오류로 변환되는 예외를 발생시킬 수 있습니다. 예를 들어, 보안 시스템이 제대로 보호되지 않은 메시지를 수신하거나 RM이 잘못된 시퀀스 번호가 있는 메시지를 수신할 수 있습니다.
그렇지 않으면 메시지가 계층에 특별히 적용되는 오류 메시지이고 메시지가 계층의 상호 작용 외부에서 의미가 없는 경우 계층에서 오류 조건을 처리해야 합니다. 이 예시는 RM 채널 위의 계층에 의미가 없고, RM 채널에 오류가 발생하여 보류 중인 작업에서 예외를 발생시키는 RM 시퀀스 거부 오류입니다.
그렇지 않으면 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
이 작업에 유용한 두 멤버가 있습니다.
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 있으며 다음으로 구성됩니다.
System.Diagnostics.TraceSource기록할 추적 정보의 원본인 이 클래스는 System.Diagnostics.TraceListener로부터 추적할 정보를 수신하여, 수신기의 구현 형태의 구체적인 대상에 맞춤형으로 정보를 출력하는 추상 기본 클래스입니다. 예를 들어 XmlWriterTraceListener 추적 정보를 XML 파일에 출력합니다. 마지막으로, System.Diagnostics.TraceSwitch애플리케이션 사용자가 추적 세부 정보를 제어할 수 있으며 일반적으로 구성에 지정됩니다.
핵심 구성 요소 외에도 서비스 추적 뷰어 도구(SvcTraceViewer.exe) 를 사용하여 WCF 추적을 보고 검색할 수 있습니다. 이 도구는 WCF에서 생성된 추적 파일을 위해 특별히 설계되었으며, XmlWriterTraceListener을(를) 사용하여 작성되었습니다. 다음 그림에서는 추적과 관련된 다양한 구성 요소를 보여 줍니다.
사용자 지정 채널에서 추적
사용자 지정 채널은 실행 중인 애플리케이션에 디버거를 연결할 수 없는 경우 문제를 진단하는 데 도움이 되는 추적 메시지를 작성해야 합니다. 여기에는 두 가지 고급 작업이 포함됩니다. TraceSource를 인스턴스화하고, 메서드를 호출하여 추적을 작성하는 것입니다.
인스턴스화할 때 지정한 TraceSource문자열이 해당 원본의 이름이 됩니다. 이 이름은 추적 원본을 구성하는 데 사용됩니다(추적 수준 사용/사용 안 함/설정). 추적 출력 자체에도 표시됩니다. 사용자 지정 채널은 추적 출력의 독자가 추적 정보의 출처를 이해하는 데 도움이 되도록 고유한 원본 이름을 사용해야 합니다. 정보를 추적 원본의 이름으로 쓰는 어셈블리의 이름을 사용하는 것이 일반적입니다. 예를 들어 WCF는 System.ServiceModel 어셈블리에서 작성된 정보의 추적 원본으로 System.ServiceModel을 사용합니다.
추적 소스를 얻으면 TraceData, TraceEvent, 또는 TraceInformation 메서드를 호출하여 추적 항목을 추적 수신기에 씁니다. 작성하는 각 추적 항목에 대해 이벤트 형식을 정의된 이벤트 유형 TraceEventType중 하나로 분류해야 합니다. 이 분류 및 구성의 추적 수준 설정은 추적 항목이 수신기에 출력되는지 여부를 결정합니다. 예를 들어, 구성에서 Warning
로 추적 수준을 설정하면 Warning
, Error
, Critical
의 추적 항목은 작성되지만 정보 및 상세한 항목은 차단됩니다. 다음은 추적 원본을 인스턴스화하고 정보 수준에서 항목을 작성하는 예제입니다.
using System.Diagnostics;
//...
TraceSource udpSource = new TraceSource("Microsoft.Samples.Udp");
//...
udpsource.TraceInformation("UdpInputChannel received a message");
중요합니다
추적 출력 판독기에서 출력의 출처를 이해할 수 있도록 사용자 지정 채널에 고유한 추적 원본 이름을 지정하는 것이 좋습니다.
추적 뷰어와 통합
채널에서 생성된 추적은 추적 수신기로 사용하여 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 에는 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 사용자가 데이터를 읽도록 도와야 합니다.