Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Исключения используются для передачи информации об ошибках локально в службе или реализации клиента. С другой стороны, ошибки используются для передачи ошибок через границы службы, например с сервера на клиент или наоборот. В дополнение к сбоям транспортные каналы часто используют механизмы, зависящие от транспорта, для сообщения об ошибках на транспортном уровне. Например, транспорт HTTP использует такие коды состояния, как 404, чтобы сообщить об отсутствии URL-адреса конечной точки (нет конечной точки, чтобы отправить назад ошибку). Этот документ состоит из трех разделов, которые предоставляют рекомендации авторам настраиваемых каналов. В первом разделе приводятся рекомендации по определению и вызову исключений. Второй раздел содержит рекомендации по созданию и использованию ошибок. В третьем разделе объясняется, как предоставить информацию о трассировке, чтобы помочь пользователю вашего пользовательского канала в устранении неполадок с запущенными приложениями.
Исключения
При создании исключения следует учитывать два способа: сначала необходимо иметь в виду тип, позволяющий пользователям писать правильный код, который может соответствующим образом реагировать на исключение. Во-вторых, он должен предоставить достаточно информации для пользователя, чтобы понять, что пошло не так, влияние сбоя и как исправить его. В следующих разделах приводятся рекомендации по типам исключений и сообщениям для каналов Windows Communication Foundation (WCF). Существует также общее руководство по исключениям в .NET в документе "Рекомендации по проектированию исключений".
Типы исключений
Все исключения, создаваемые каналами, должны быть либо System.TimeoutException, либо System.ServiceModel.CommunicationException, либо производным типом от CommunicationException. (Такие исключения также могут быть вызваны ObjectDisposedException , но только чтобы указать, что вызывающий код неправильно использует канал. Если канал используется правильно, он должен вызывать только заданные исключения.) WCF предоставляет семь типов исключений, производных от CommunicationException и предназначенных для использования каналами. Существуют другие CommunicationException, производные исключения, предназначенные для использования другими частями системы. Ниже перечислены следующие типы исключений:
Тип исключения | Значение | Содержимое внутреннего исключения | Стратегия восстановления |
---|---|---|---|
AddressAlreadyInUseException | Адрес конечной точки, указанный для прослушивания, уже используется. | При наличии предоставляет дополнительные сведения об ошибке транспорта, вызвавшей это исключение. Например. PipeException, HttpListenerException или SocketException. | Попробуйте другой адрес. |
AddressAccessDeniedException | Процесс не допускает доступ к адресу конечной точки, указанному для прослушивания. | При наличии предоставляет дополнительные сведения об ошибке транспорта, вызвавшей это исключение. Например, PipeException или HttpListenerException. | Попробуйте использовать разные учетные данные. |
CommunicationObjectFaultedException | Используется ICommunicationObject в состоянии сбоя (дополнительные сведения см. в разделе Понимание изменения состояний). Обратите внимание, что при переходе объекта с несколькими ожидающими вызовами в состояние ошибки только один вызов вызывает исключение, связанное с ошибкой, а остальные вызовы вызывают исключение CommunicationObjectFaultedException. Это исключение обычно возникает, так как приложение игнорирует некоторые исключения и пытается использовать уже неисправный объект, возможно, в потоке, отличном от того, который поймал исходное исключение. | Если они присутствуют, предоставляются сведения о внутреннем исключении. | Создание нового объекта. Обратите внимание, что в зависимости от того, что изначально вызвало ошибку 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>
элемента. Содержимое элемента сбоя немного отличается от SOAP 1.1 и SOAP 1.2, как показано на рисунке 1.
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
(или faultCode
в SOAP 1.1) и определяет тип сбоя. SOAP 1.2 определяет пять допустимых значений faultCode
(например, Sender и Receiver) и определяет Subcode
элемент, который может содержать любое значение подкода. (См. спецификацию SOAP 1.2 для списка допустимых кодов сбоев и их значения.) SOAP 1.1 имеет немного другой механизм: он определяет четыре faultCode
значения (например, клиент и сервер), которые можно расширить, определяя совершенно новые или используя нотацию точки для создания более конкретных faultCodes
, например Client.Authentication.
При использовании MessageFault для программирования ошибок, имя и пространство имен FaultCode.Name и FaultCode.Namespace сопоставляются с именем и пространством имен SOAP 1.2 env:Code
или SOAP 1.1 faultCode
. Код FaultCode.SubCode сопоставляется с env:Subcode
SOAP 1.2 и имеет значение NULL для SOAP 1.1.
Необходимо создать новые подкоды сбоя (или новые коды сбоя при использовании 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
(или faultString
в SOAP 1.1) удобочитаемому описанию условия ошибки, аналогичному сообщению исключения. Класс 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;
}
}
Содержимое сведений об ошибке предоставляется в MessageFault с помощью различных методов, включая GetDetail
<T> и GetReaderAtDetailContents
(). Сведения об ошибке — это неявный элемент для включения дополнительных сведений об ошибке. Это полезно, если есть произвольно структурированные детали, которые необходимо сопровождать ошибку.
Генерация сбоев
В этом разделе объясняется процесс создания сбоя в ответ на условие ошибки, обнаруженное в канале или в свойстве сообщения, созданном каналом. Типичный пример — отправка ошибки в ответ на сообщение запроса, содержащее недопустимые данные.
При создании сбоя пользовательский канал не должен отправлять ошибку напрямую, а вызывать исключение и разрешать приведенному выше уровню решить, следует ли преобразовать это исключение в ошибку и как отправить его. Чтобы помочь в этом преобразовании, канал должен предоставить 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
или стандартному FaultConverter
, предусмотренному в WCF. Значение по умолчанию 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
}
Это связано с тем, что исключения, создаваемые между слоями для условий ошибок, для которых требуются ошибки, должны содержать достаточно сведений для соответствующего генератора сбоев, чтобы создать правильную ошибку. В качестве автора пользовательского канала можно определить типы исключений, соответствующие разным условиям сбоя, если такие исключения еще не существуют. Обратите внимание, что исключения, проходящие через уровни каналов, должны сообщать о состоянии ошибки, а не передавать непонятные данные об ошибке.
Категории ошибок
Как правило, существует три категории ошибок:
Ошибки, которые являются распространенными во всем стеке. Эти ошибки могут быть обнаружены на любом уровне в стеке каналов, например InvalidCardinalityAddressingException.
Ошибки, которые могут возникнуть в любом месте над определенным слоем в стеке, например некоторые ошибки, относящиеся к потоковой транзакции или ролям безопасности.
Ошибки, направленные на один слой в стеке, например, ошибки с номером последовательности WS-RM.
Категория 1. Ошибки обычно делятся на WS-Addressing и SOAP ошибки. Базовый FaultConverter
класс, предоставляемый WCF, преобразует ошибки, соответствующие сообщениям об ошибках, указанным в 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
и проверьте сообщение об ошибке. Если распознано, выполните преобразование, в противном случае попросите внутренний канал преобразовать его. Каналы транспорта должны делегировать FaultConverter.GetDefaultFaultConverter
для получения стандартного преобразователя ошибок SOAP/WS-Addressing.
Типичная реализация выглядит следующим образом:
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
обработки.) В случае ошибки создается заголовок NotUnderstood, содержащий имена всех заголовков с параметром MustUnderstand=true, которые система не поняла.
Если канал протокола отправляет пользовательский заголовок с 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
возвращает true
, если заголовок с указанным именем и пространством имен включен в сообщение об ошибке в качестве заголовка NotUnderstood. В противном случае возвращается значение false
.
Если канал выдает заголовок, помеченный MustUnderstand = true, этот слой также должен реализовать шаблон API создания исключений и преобразовать mustUnderstand
ошибки, вызванные этим заголовком, в более полезное исключение, как описано ранее.
Отслеживание
Платформа .NET Framework предоставляет механизм трассировки выполнения программы в качестве способа для диагностики рабочих приложений или периодических проблем, когда невозможно просто подключить отладчик и выполнить шаг по коду. Основные компоненты этого механизма находятся в System.Diagnostics пространстве имен и состоят из следующих компонентов:
System.Diagnostics.TraceSource— источник записываемой информации трассировки, который является абстрактным базовым классом для конкретных прослушивателей, System.Diagnostics.TraceListener получающих отслеживаемую информацию от TraceSource и выводящих её в целевое место для каждого прослушивателя. Например, 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");
Это важно
Настоятельно рекомендуется указать имя источника трассировки, уникальное для вашего пользовательского канала, чтобы помочь читателям выходных данных трассировки понять, откуда пришли эти данные.
Интеграция с инструментом трассировки
Трассировки, созданные вашим каналом, можно выводить в формате, доступном для чтения средством просмотра трассировки службы (SvcTraceViewer.exe) с использованием System.Diagnostics.XmlWriterTraceListener в качестве прослушивателя трассировки. Это не то, что вы, как разработчик канала, должны сделать. Скорее, это пользователь приложения (или пользователь, устраняющий неполадки с приложением), который должен настроить этот прослушиватель трассировки в файле конфигурации приложения. Например, следующая конфигурация выводит сведения трассировки как из System.ServiceModel, так и из Microsoft.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. Результирующая запись трассировки содержит XML-код, предоставленный этим элементом System.Xml.XPath.XPathNavigator. Ниже приведен пример записи с данными 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 пользователи могли читать данные.