Menangani Pengecualian dan Kesalahan
Pengecualian digunakan untuk mengomunikasikan kesalahan secara lokal dalam layanan atau implementasi klien. Kesalahan, di sisi lain, digunakan untuk mengomunikasikan kesalahan di seluruh batas layanan, seperti dari server ke klien atau sebaliknya. Selain kesalahan, saluran transportasi sering menggunakan mekanisme khusus transportasi untuk mengomunikasikan kesalahan tingkat transportasi. Misalnya, transportasi HTTP menggunakan kode status seperti 404 untuk mengomunikasikan URL titik akhir yang tidak ada (tidak ada titik akhir untuk mengirimkan kembali kesalahan). Dokumen ini terdiri dari tiga bagian yang memberikan panduan kepada penulis saluran kustom. Bagian pertama menyediakan panduan tentang kapan dan bagaimana menentukan dan membuat pengecualian. Bagian kedua memberikan panduan tentang membuat dan mengonsumsi kesalahan. Bagian ketiga menjelaskan cara memberikan informasi pelacakan untuk membantu pengguna saluran kustom Anda dalam memecahkan masalah aplikasi yang sedang berjalan.
Pengecualian
Ada dua hal yang perlu diingat saat membuat pengecualian: Pertama harus dari jenis yang memungkinkan pengguna menulis kode yang benar yang dapat bereaksi dengan tepat terhadap pengecualian. Kedua, harus memberikan informasi yang cukup bagi pengguna untuk memahami apa yang salah, dampak kegagalan, dan cara memperbaikinya. Bagian berikut memberikan panduan tentang jenis pengecualian dan pesan untuk saluran Windows Communication Foundation (WCF). Ada juga panduan umum terkait pengecualian di .NET dalam dokumen Pedoman Desain untuk Pengecualian.
Jenis Pengecualian
Semua pengecualian yang dibuat oleh saluran harus berupa System.TimeoutException, System.ServiceModel.CommunicationException, atau jenis yang berasal dari CommunicationException. (Pengecualian seperti ObjectDisposedException juga dapat dibuat, tetapi hanya untuk menunjukkan bahwa kode panggilan telah menyalahgunakan saluran. Jika saluran digunakan dengan benar, saluran hanya boleh memberikan pengecualian yang diberikan.) WCF menyediakan tujuh jenis pengecualian yang berasal dari CommunicationException dan dirancang untuk digunakan oleh saluran. Ada pengecualian turunan CommunicationException lain yang dirancang untuk digunakan oleh bagian lain dari sistem. Jenis pengecualian ini adalah:
Tipe Pengecualian | Makna | Isi Pengecualian Dalam | Strategi Pemulihan |
---|---|---|---|
AddressAlreadyInUseException | Alamat titik akhir yang ditentukan untuk mendengarkan sudah digunakan. | Jika ada, berikan detail selengkapnya tentang kesalahan transportasi yang menyebabkan pengecualian ini. Contohnya. PipeException, HttpListenerException, atau SocketException. | Coba alamat lain. |
AddressAccessDeniedException | Proses ini tidak memiliki izin akses ke alamat titik akhir yang ditentukan untuk mendengarkan. | Jika ada, berikan detail selengkapnya tentang kesalahan transportasi yang menyebabkan pengecualian ini. Misalnya, PipeException atau HttpListenerException. | Coba dengan mandat yang berbeda. |
CommunicationObjectFaultedException | ICommunicationObject yang digunakan berada dalam status Bermasalah (untuk informasi selengkapnya, lihat Memahami Perubahan Status). Perhatikan bahwa saat objek dengan beberapa panggilan tertunda beralih ke status Bermasalah, hanya satu panggilan yang membuat pengecualian yang terkait dengan kegagalan dan sisa panggilan membuat CommunicationObjectFaultedException. Pengecualian ini biasanya dilemparkan karena aplikasi mengabaikan beberapa pengecualian dan mencoba menggunakan objek yang bermasalah, mungkin pada rangkaian selain yang menangkap pengecualian asli. | Jika ada memberikan detail tentang pengecualian dalam. | Buat objek baru. Perhatikan bahwa tergantung pada apa yang menyebabkan ICommunicationObject bermasalah pada awalnya, mungkin ada pekerjaan lain yang diperlukan untuk pulih. |
CommunicationObjectAbortedException | ICommunicationObject yang sedang digunakan telah Dibatalkan (untuk informasi selengkapnya, lihat Memahami Perubahan Status). Mirip dengan CommunicationObjectFaultedException, pengecualian ini menunjukkan aplikasi telah memanggil objek Abort, mungkin dari rangkaian lain, dan objek tidak lagi dapat digunakan karena alasan itu. | Jika ada memberikan detail tentang pengecualian dalam. | Buat objek baru. Perhatikan bahwa tergantung pada apa yang menyebabkan ICommunicationObject dibatalkan pada awalnya, mungkin ada pekerjaan lain yang diperlukan untuk pulih. |
EndpointNotFoundException | Titik akhir jarak jauh target tidak mendengarkan. Ini dapat mengakibatkan bagian mana pun dari alamat titik akhir menjadi salah, tidak dapat diselesaikan, atau titik akhir tidak berfungsi. Contohnya termasuk kesalahan DNS, Queue Manager tidak tersedia, dan layanan tidak berjalan. | Pengecualian dalam memberikan detail, biasanya dari transportasi yang mendasar. | Coba alamat lain. Atau, pengirim mungkin menunggu beberapa saat dan mencoba lagi jika layanan tidak berfungsi |
ProtocolException | Protokol komunikasi, seperti yang dijelaskan oleh kebijakan titik akhir, tidak cocok di antara titik akhir. Misalnya, pembingkaian jenis konten tidak cocok atau ukuran pesan maksimal terlampaui. | Jika ada, berikan informasi selengkapnya tentang kesalahan protokol tertentu. Misalnya, QuotaExceededException adalah pengecualian dalam saat penyebab kesalahan melebihi MaxReceivedMessageSize. | Pemulihan: Pastikan pengaturan protokol pengirim dan penerima cocok. Salah satu cara untuk melakukan ini adalah dengan mengimpor kembali metadata (kebijakan) titik akhir layanan dan menggunakan pengikatan yang dihasilkan untuk membuat ulang saluran. |
ServerTooBusyException | Titik akhir jarak jauh mendengarkan tetapi tidak siap untuk memproses pesan. | Jika ada, Pengecualian dalam memberikan kesalahan SOAP atau detail kesalahan tingkat transportasi. | Pemulihan: Tunggu dan coba lagi operator nanti. |
TimeoutException | Operasi gagal diselesaikan dalam periode waktu habis. | Dapat memberikan detail tentang batas waktu. | Tunggu dan coba lagi operator nanti. |
Tentukan jenis pengecualian baru hanya jika jenis tersebut sesuai dengan strategi pemulihan tertentu yang berbeda dari semua jenis pengecualian yang ada. Jika Anda menentukan jenis pengecualian baru, jenis tersebut harus berasal dari CommunicationException atau salah satu kelas turunannya.
Pesan pengecualian
Pesan pengecualian ditargetkan kepada pengguna bukan program sehingga pesan harus memberikan informasi yang memadai untuk membantu pengguna memahami dan menyelesaikan masalah. Tiga bagian penting dari pesan pengecualian yang baik adalah:
Apa yang terjadi. Berikan deskripsi yang jelas tentang masalah menggunakan istilah yang terkait dengan pengalaman pengguna. Misalnya, pesan pengecualian yang buruk adalah "Bagian konfigurasi tidak valid". Ini membuat pengguna bertanya-tanya bagian konfigurasi mana yang salah dan alasannya bisa salah. Pesan yang ditingkatkan adalah "<customBinding> bagian konfigurasi tidak valid". Pesan yang lebih baik adalah "Tidak dapat menambahkan transportasi bernama myTransport ke pengikatan bernama myBinding karena pengikatan sudah memiliki transportasi bernama myTransport". Ini adalah pesan yang sangat spesifik yang menggunakan istilah dan nama yang dapat dengan mudah diidentifikasi pengguna dalam file konfigurasi aplikasi. Namun, masih ada beberapa komponen utama yang hilang.
Signifikansi kesalahan. Kecuali pesan menyatakan dengan jelas apa arti kesalahan, pengguna cenderung bertanya-tanya apakah itu kesalahan fatal atau apakah dapat diabaikan. Secara umum, pesan harus mengarah dengan arti atau signifikansi kesalahan. Untuk meningkatkan contoh sebelumnya, pesan dapat berupa "ServiceHost gagal Dibuka karena kesalahan konfigurasi: Tidak dapat menambahkan transportasi bernama myTransport ke pengikatan bernama myBinding karena pengikatan sudah memiliki transportasi bernama myTransport".
Cara pengguna harus memperbaiki masalah. Bagian terpenting dari pesan adalah membantu pengguna memperbaiki masalah. Pesan harus menyertakan beberapa panduan atau petunjuk tentang apa yang harus diperiksa atau diperbaiki untuk memperbaiki masalah. Misalnya, "ServiceHost gagal Dibuka karena kesalahan konfigurasi: Tidak dapat menambahkan transportasi bernama myTransport ke pengikatan bernama myBinding karena pengikatan sudah memiliki transportasi bernama myTransport. Harap pastikan hanya ada satu transportasi dalam pengikatan".
Kesalahan Komunikasi
SOAP 1.1 dan SOAP 1.2 mendefinisikan struktur tertentu untuk kesalahan. Ada beberapa perbedaan antara dua spesifikasi, tetapi secara umum, jenis Message dan MessageFault digunakan untuk membuat dan mengonsumsi kesalahan.
SOAP 1.2 Fault (kiri) dan SOAP 1.1 Fault (kanan). Dalam SOAP 1.1, hanya elemen Fault yang memenuhi syarat namespace.
SOAP mendefinisikan pesan kesalahan sebagai pesan yang hanya berisi elemen kesalahan (elemen yang namanya <env:Fault>
) sebagai turunan dari <env:Body>
. Isi elemen kesalahan sedikit berbeda antara SOAP 1.1 dan SOAP 1.2 seperti yang ditunjukkan pada gambar 1. Namun, kelas System.ServiceModel.Channels.MessageFault menormalkan perbedaan ini menjadi satu model objek:
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
}
Properti Code
sesuai dengan env:Code
(atau faultCode
di SOAP 1.1) dan mengidentifikasi jenis kesalahan. SOAP 1.2 mendefinisikan lima nilai yang diizinkan untuk faultCode
(misalnya, Pengirim dan Penerima) dan menentukan elemen Subcode
yang dapat berisi nilai subkode apa pun. (Lihat spesifikasi SOAP 1.2 untuk daftar kode kesalahan yang diizinkan dan maknanya.) SOAP 1.1 memiliki mekanisme yang sedikit berbeda: Ini mendefinisikan empat nilai faultCode
(misalnya, Klien dan Server) yang dapat diperluas baik dengan mendefinisikan yang sepenuhnya baru atau dengan menggunakan notasi titik untuk membuat faultCodes
yang lebih spesifik, misalnya, Client.Authentication.
Saat Anda menggunakan MessageFault untuk memprogram kesalahan, FaultCode.Name dan FaultCode.Namespace memetakan ke nama dan namespace SOAP 1.2 env:Code
atau SOAP 1.1 faultCode
. FaultCode.SubCode memetakan ke env:Subcode
untuk SOAP 1.2 dan null untuk SOAP 1.1.
Anda harus membuat subkode kesalahan baru (atau kode kesalahan baru jika menggunakan SOAP 1.1) jika menarik untuk membedakan kesalahan secara terprogram. Ini dianalogikan untuk membuat jenis pengecualian baru. Anda harus menghindari penggunaan notasi titik dengan kode kesalahan SOAP 1.1. (Profil Dasar WS-I juga mencegah penggunaan notasi titik kode kesalahan.)
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
}
Properti Reason
sesuai dengan env:Reason
(atau faultString
di SOAP 1.1) deskripsi yang dapat dibaca manusia tentang kondisi kesalahan yang dianalogikan dengan pesan pengecualian. Kelas FaultReason
(dan SOAP env:Reason/faultString
) memiliki dukungan bawaan untuk memiliki beberapa terjemahan untuk kepentingan globalisasi.
public class FaultReason
{
public FaultReason(FaultReasonText translation);
public FaultReason(IEnumerable<FaultReasonText> translations);
public FaultReason(string text);
public SynchronizedReadOnlyCollection<FaultReasonText> Translations
{
get;
}
}
Konten detail kesalahan diekspos pada MessageFault menggunakan berbagai metode termasuk GetDetail
<T> dan GetReaderAtDetailContents
(). Detail kesalahan adalah elemen buram untuk membawa detail tambahan tentang kesalahan. Ini berguna jika ada beberapa detail terstruktur arbitrer yang ingin Anda bawa dengan kesalahan.
Menghasilkan Kesalahan
Bagian ini menjelaskan proses pembuatan kesalahan sebagai respons terhadap kondisi kesalahan yang terdeteksi di saluran atau di properti pesan yang dibuat oleh saluran. Contoh umumnya adalah mengirim kembali kesalahan sebagai respons terhadap pesan permintaan yang berisi data yang tidak valid.
Saat menghasilkan kesalahan, saluran kustom tidak boleh mengirim kesalahan secara langsung, melainkan harus membuat pengecualian dan membiarkan lapisan di atas memutuskan apakah akan mengonversi pengecualian itu menjadi kesalahan dan cara mengirimkannya. Untuk membantu dalam konversi ini, saluran harus memberikan implementasi FaultConverter
yang dapat mengonversi pengecualian yang dibuat oleh saluran kustom ke kesalahan yang sesuai. FaultConverter
didefinisikan sebagai:
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);
}
Setiap saluran yang menghasilkan kesalahan kustom harus menerapkan FaultConverter
dan mengembalikannya dari panggilan ke GetProperty<FaultConverter>
. Implementasi OnTryCreateFaultMessage
kustom harus mengonversi pengecualian menjadi kesalahan atau mendelegasikan ke FaultConverter
saluran dalam. Jika saluran adalah transportasi, saluran harus mengonversi pengecualian atau mendelegasikan ke FaultConverter
encoder atau FaultConverter
default yang disediakan dalam WCF. FaultConverter
default mengonversi kesalahan yang sesuai dengan pesan kesalahan yang ditentukan oleh WS-Addressing dan SOAP. Berikut adalah contoh implementasi 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
}
Implikasi dari pola ini adalah bahwa pengecualian yang dilemparkan di antara lapisan untuk kondisi kesalahan yang memerlukan kesalahan harus berisi informasi yang cukup untuk pembuat kesalahan yang sesuai untuk membuat kesalahan yang benar. Sebagai penulis saluran kustom, Anda dapat menentukan jenis pengecualian yang sesuai dengan kondisi kesalahan yang berbeda jika pengecualian tersebut belum ada. Perhatikan bahwa pengecualian yang melintas lapisan saluran harus mengomunikasikan kondisi kesalahan daripada data kesalahan buram.
Kategori Kesalahan
Umumnya ada tiga kategori kesalahan:
Kesalahan yang pervasif di seluruh tumpukan. Kesalahan ini dapat ditemui pada lapisan apa pun di tumpukan saluran, misalnya InvalidCardinalityAddressingException.
Kesalahan yang dapat ditemui di mana saja di atas lapisan tertentu dalam tumpukan, misalnya beberapa kesalahan yang berkaitan dengan transaksi yang mengalir atau ke peran keamanan.
Kesalahan yang diarahkan pada satu lapisan dalam tumpukan, misalnya kesalahan seperti kesalahan nomor urut WS-RM.
Kategori 1. Kesalahan umumnya adalah kesalahan WS-Addressing dan SOAP. Kelas FaultConverter
dasar yang disediakan oleh WCF mengonversi kesalahan yang sesuai dengan pesan kesalahan yang ditentukan oleh WS-Addressing dan SOAP sehingga Anda tidak perlu menangani konversi pengecualian ini sendiri.
Kategori 2. Kesalahan terjadi saat lapisan menambahkan properti ke pesan yang tidak sepenuhnya menggunakan informasi pesan yang berkaitan dengan lapisan tersebut. Kesalahan dapat dideteksi nanti saat lapisan yang lebih tinggi meminta properti pesan memproses informasi pesan lebih lanjut. Saluran tersebut harus mengimplementasikan GetProperty
yang ditentukan sebelumnya untuk memungkinkan lapisan yang lebih tinggi mengirim kembali kesalahan yang benar. Contohnya adalah TransactionMessageProperty. Properti ini ditambahkan ke pesan tanpa sepenuhnya memvalidasi semua data di header (melakukannya mungkin melibatkan menghubungi koordinator transaksi terdistribusi (DTC).
Kategori 3. Kesalahan hanya dihasilkan dan dikirim oleh satu lapisan dalam prosesor. Oleh karena itu, semua pengecualian terkandung dalam lapisan. Untuk meningkatkan konsistensi di antara saluran dan kemudahan pemeliharaan, saluran kustom Anda harus menggunakan pola yang ditentukan sebelumnya untuk menghasilkan pesan kesalahan bahkan untuk kesalahan internal.
Menginterpretasikan Kesalahan yang Diterima
Bagian ini menyediakan panduan untuk menghasilkan pengecualian yang sesuai saat menerima pesan kesalahan. Pohon keputusan untuk memproses pesan di setiap lapisan dalam tumpukan adalah sebagai berikut:
Jika lapisan menganggap pesan tidak valid, lapisan harus melakukan pemrosesan 'pesan tidak valid'. Pemrosesan tersebut khusus untuk lapisan tetapi dapat mencakup menghilangkan pesan, melacak, atau membuat pengecualian yang dikonversi menjadi kesalahan. Contohnya termasuk keamanan yang menerima pesan yang tidak diamankan dengan benar, atau RM menerima pesan dengan nomor urut yang buruk.
Jika tidak, jika pesan adalah pesan kesalahan yang berlaku khusus untuk lapisan, dan pesan tidak bermakna di luar interaksi lapisan, lapisan harus menangani kondisi kesalahan. Contohnya adalah kesalahan RM Sequence Refused yang tidak berarti lapisan di atas saluran RM dan yang menyiratkan kesalahan saluran RM dan membuat dari operasi yang tertunda.
Jika tidak, pesan harus dikembalikan dari Request() atau Receive(). Ini termasuk kasus saat lapisan mengenali kesalahan, tetapi kesalahan hanya menunjukkan bahwa permintaan gagal dan tidak menyiratkan kesalahan saluran dan melempar dari operasi yang tertunda. Untuk meningkatkan kegunaan dalam kasus seperti itu, lapisan harus mengimplementasikan
GetProperty<FaultConverter>
dan mengembalikan kelasFaultConverter
turunan yang dapat mengonversi kesalahan menjadi pengecualian dengan mengambil alihOnTryCreateException
.
Model objek berikut mendukung konversi pesan menjadi pengecualian:
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);
}
Lapisan saluran dapat menerapkan GetProperty<FaultConverter>
untuk mendukung konversi pesan kesalahan menjadi pengecualian. Untuk melakukannya, ambil alih OnTryCreateException
dan periksa pesan kesalahan. Jika dikenali, lakukan konversi, jika tidak, minta saluran dalam untuk mengonversinya. Saluran transportasi harus mendelegasikan ke FaultConverter.GetDefaultFaultConverter
untuk mendapatkan SOAP/WS-Addressing FaultConverter default.
Implementasi semacam ini terlihat seperti ini:
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
}
Untuk kondisi kesalahan tertentu yang memiliki skenario pemulihan yang berbeda, pertimbangkan untuk menentukan kelas turunan dari ProtocolException
.
Pemrosesan MustUnderstand
SOAP mendefinisikan kesalahan umum untuk memberi sinyal bahwa header yang diperlukan tidak dipahami oleh penerima. Kesalahan ini dikenal sebagai kesalahan mustUnderstand
. Di WCF, saluran kustom tidak pernah menghasilkan kesalahan mustUnderstand
. Sebaliknya, WCF Dispatcher, yang terletak di bagian atas tumpukan komunikasi WCF, memeriksa untuk melihat bahwa semua header yang ditandai sebagai MustUnderstand=true dipahami oleh tumpukan yang mendasar. Jika ada yang tidak dipahami, kesalahan mustUnderstand
dihasilkan pada saat itu. (Pengguna dapat memilih untuk menonaktifkan pemrosesan mustUnderstand
ini dan meminta aplikasi menerima semua header pesan. Dalam hal ini, aplikasi bertanggung jawab untuk melakukan pemrosesan mustUnderstand
.) Kesalahan yang dihasilkan mencakup header NotUnderstood yang berisi nama semua header dengan MustUnderstand=true yang tidak dipahami.
Jika saluran protokol Anda mengirim header kustom dengan MustUnderstand=true dan menerima kesalahan mustUnderstand
, saluran protokol harus mencari tahu apakah kesalahan tersebut disebabkan oleh header yang dikirimnya. Ada dua anggota di kelas MessageFault
yang berguna untuk ini:
public class MessageFault
{
...
public bool IsMustUnderstandFault { get; }
public static bool WasHeaderNotUnderstood(MessageHeaders headers,
string name, string ns) { }
...
}
IsMustUnderstandFault
mengembalikan true
jika kesalahan adalah kesalahan mustUnderstand
. WasHeaderNotUnderstood
mengembalikan true
jika header dengan nama dan namespace yang ditentukan disertakan dalam kesalahan sebagai header NotUnderstood. Jika tidak, ia kembali false
.
Jika saluran memancarkan header yang ditandai MustUnderstand = true, lapisan tersebut juga harus menerapkan pola Exception Generation API dan harus mengonversi kesalahan mustUnderstand
yang disebabkan oleh header tersebut ke pengecualian yang lebih berguna seperti yang dijelaskan sebelumnya.
Menelusuri
.NET Framework menyediakan mekanisme untuk melacak eksekusi program sebagai cara untuk membantu mendiagnosis aplikasi produksi atau masalah terputus-terputus yang mana tidak mungkin untuk hanya melampirkan debugger dan melangkah melalui kode. Komponen inti dari mekanisme ini berada di namespace System.Diagnostics dan terdiri dari:
System.Diagnostics.TraceSource, yang merupakan sumber informasi jejak yang akan ditulis, System.Diagnostics.TraceListener, yang merupakan kelas dasar abstrak untuk pendengar konkret yang menerima informasi untuk dilacak dari TraceSource dan menghasilkannya ke tujuan khusus pendengar. Misalnya, XmlWriterTraceListener output melacak informasi ke file XML. Terakhir, System.Diagnostics.TraceSwitch, yang memungkinkan pengguna aplikasi mengontrol verbositas pelacakan dan biasanya ditentukan dalam konfigurasi.
Selain komponen inti, Anda dapat menggunakan Alat Penampil Jejak Layanan (SvcTraceViewer.exe) untuk melihat dan mencari jejak WCF. Alat ini dirancang khusus untuk file pelacakan yang dihasilkan oleh WCF dan ditulis menggunakan XmlWriterTraceListener. Gambar berikut menunjukkan berbagai komponen yang terlibat dalam pelacakan.
Melacak dari Saluran Kustom
Saluran kustom harus menulis pesan pelacakan untuk membantu mendiagnosis masalah saat tidak dimungkinkan untuk melampirkan debugger ke aplikasi yang sedang berjalan. Ini melibatkan dua tugas tingkat tinggi: Membuat instans TraceSource dan memanggil metodenya untuk menulis jejak.
Saat membuat instans TraceSource, string yang Anda tentukan menjadi nama sumber tersebut. Nama ini digunakan untuk mengonfigurasi (mengaktifkan/menonaktifkan/mengatur tingkat pelacakan) sumber pelacakan. Ini juga muncul dalam output jejak itu sendiri. Saluran kustom harus menggunakan nama sumber unik untuk membantu pembaca output jejak memahami asal informasi pelacakan. Menggunakan nama rakitan yang menulis informasi sebagai nama sumber pelacakan adalah praktik umum. Misalnya, WCF menggunakan System.ServiceModel sebagai sumber pelacakan untuk informasi yang ditulis dari rakitan System.ServiceModel.
Setelah memiliki sumber pelacakan, Anda memanggil metode TraceData, TraceEvent, atau TraceInformation untuk menulis entri jejak ke pendengar pelacakan. Untuk setiap entri jejak yang Anda tulis, Anda perlu mengklasifikasikan jenis peristiwa sebagai salah satu jenis peristiwa yang ditentukan dalam TraceEventType. Klasifikasi ini dan pengaturan tingkat pelacakan dalam konfigurasi menentukan apakah entri pelacakan merupakan output ke pendengar. Misalnya, mengatur tingkat pelacakan dalam konfigurasi untuk Warning
memungkinkan entri pelacakan Warning
, Error
, dan Critical
ditulis tetapi memblokir entri Informasi dan Verbose. Berikut adalah contoh membuat instans sumber pelacakan dan menulis entri di tingkat Informasi:
using System.Diagnostics;
//...
TraceSource udpSource = new TraceSource("Microsoft.Samples.Udp");
//...
udpsource.TraceInformation("UdpInputChannel received a message");
Penting
Sangat disarankan agar Anda menentukan nama sumber pelacakan yang unik untuk saluran kustom Anda guna membantu melacak pembaca output memahami dari mana output berasal.
Mengintegrasikan dengan Penampil Jejak
Jejak yang dihasilkan oleh saluran Anda dapat menjadi output dalam format yang dapat dibaca oleh Alat Penampil Jejak Layanan (SvcTraceViewer.exe) dengan menggunakan System.Diagnostics.XmlWriterTraceListener sebagai pendengar jejak. Ini bukan sesuatu yang perlu Anda lakukan, sebagai pengembang saluran. Sebaliknya, ini adalah pengguna aplikasi (atau orang yang memecahkan masalah aplikasi) yang perlu mengonfigurasi pendengar jejak ini dalam file konfigurasi aplikasi. Misalnya, konfigurasi berikut menghasilkan informasi pelacakan dari System.ServiceModel dan Microsoft.Samples.Udp
ke file bernama 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>
Melacak Data Terstruktur
System.Diagnostics.TraceSource memiliki metode TraceData yang mengambil satu atau beberapa objek yang akan disertakan dalam entri pelacakan. Secara umum, metode Object.ToString dipanggil pada setiap objek dan string yang dihasilkan ditulis sebagai bagian dari entri jejak. Saat menggunakan System.Diagnostics.XmlWriterTraceListener untuk mengeluarkan jejak, Anda dapat meneruskan System.Xml.XPath.IXPathNavigable sebagai objek data ke TraceData. Entri jejak yang dihasilkan mencakup XML yang disediakan oleh System.Xml.XPath.XPathNavigator. Berikut adalah contoh entri dengan data aplikasi 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>
Penampil jejak WCF memahami skema elemen TraceRecord
yang ditampilkan sebelumnya dan mengekstrak data dari elemen turunannya dan menampilkannya dalam format tabular. Saluran Anda harus menggunakan skema ini saat melacak data aplikasi terstruktur untuk membantu pengguna Svctraceviewer.exe membaca data.