Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Gunakan DTrace untuk Windows untuk memproses peristiwa ETW yang ada dan untuk menambahkan peristiwa ETW baru.
Pelacakan Peristiwa untuk Windows (ETW) adalah fasilitas pelacakan tingkat kernel yang memungkinkan Anda mencatat kernel atau peristiwa yang ditentukan aplikasi ke file log. Anda dapat mengolah peristiwa secara real-time atau dari file log dan menggunakannya untuk membedah aplikasi atau untuk mengetahui di mana masalah performa terjadi dalam aplikasi. Untuk informasi umum tentang ETW, lihat Tentang Pelacakan Peristiwa.
Nota
DTrace didukung di build Insider Windows setelah versi 18980 dan Windows Server Build 18975.
Untuk informasi umum tentang bekerja dengan DTrace di Windows, lihat DTrace.
Penyedia DTrace Windows ETW
Anda dapat menggunakan DTrace untuk menangkap dan melaporkan kejadian ETW yang berbasis pada pencatatan jejak dan manifes. Untuk menyelidiki kata kunci/level/eventID tertentu, probe ETW akan bekerja jauh lebih andal jika Anda tidak menggunakan karakter pengganti. Sebagai gantinya, tentukan sepenuhnya probe Anda berdasarkan aturan ini:
Probename = etw
Modname = Provider guid dalam bentuk xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, menggunakan karakter huruf kecil semua.
Funcname = Level_Keyword dalam bentuk 0x00_0x0000000000000000. Untuk mencocokkan semuanya, ini harus diatur ke 0xff_0xffffffffffffffff.
Probename = ID Peristiwa Bilangan Bulat (Integer) atau "generic_event" untuk mencocokkan semua ID peristiwa.
Pemfilteran berdasarkan Probename hanya berfungsi untuk peristiwa yang dimanifestasikan. Gunakan kartu liar (*) untuk peristiwa yang dilacak jejaknya.
Payload ETW diakses melalui arg0. Ini terdiri dari nt_EVENT_HEADER diikuti oleh data spesifik acara.
Menentukan penyedia ETW yang tersedia
Gunakan perintah logman untuk menampilkan penyedia ETW aktif dan GUID Penyedia mereka.
C:\>logman query providers
...
Microsoft-Windows-Kernel-Memory {D1D93EF7-E1F2-4F45-9943-03D245FE6C00}
Microsoft-Windows-Kernel-Network {7DD42A49-5329-4832-8DFD-43D979153A88}
Microsoft-Windows-Kernel-PnP {9C205A39-1250-487D-ABD7-E831C6290539}
Microsoft-Windows-Kernel-Power {331C3B3A-2005-44C2-AC5E-77220C37D6B4}
Microsoft-Windows-Kernel-Prefetch {5322D61A-9EFA-4BC3-A3F9-14BE95C144F8}
Microsoft-Windows-Kernel-Process {22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716}
...
Menampilkan informasi penyedia ETW yang ada
DTrace memiliki kemampuan untuk menghasilkan peristiwa ETW. Ini berguna untuk skenario di mana ada alur ETW yang ada untuk melaporkan, mengumpulkan, dan menganalisis.
Gunakan contoh perintah DTrace ini untuk melaporkan kejadian dari penyediaKernel-Memory Microsoft-Windows.
C:\>dtrace -n "etw:d1d93ef7-e1f2-4f45-9943-03d245fe6c00:0xff_0xffffffffffffffff:12"
dtrace: description 'etw:d1d93ef7-e1f2-4f45-9943-03d245fe6c00:0xff_0xffffffffffffffff:12' matched 1 probe
CPU ID FUNCTION:NAME
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
0 3271 0xff_0xffffffffffffffff:12
Menambahkan peristiwa ETW baru
Peristiwa jejak Etw dapat dibuat dengan memanggil makro etw_trace. Peristiwa hanya akan dicatat jika ada pendengar aktif untuk penyedia pelacakan yang ditentukan, jika tidak, peristiwa tersebut akan dilewati.
Makro etw_trace mendukung jenis data dasar seperti int8, uint8, int16, uint16, int32, uint32, int64, uint64, hexint32, hexint64 dan string. Lihat tabel Tipe data ETW yang didukung di bawah ini untuk detail selengkapnya.
Contoh makro ETW_TRACE:
Skrip ini menghasilkan peristiwa ETW kustom saat rutinitas syscall mengembalikan 0xc0000001 - STATUS_UNSUCCESSFUL.
Anda dapat mengubah nilai this->status untuk menggunakan nilai NTSTATUS yang berbeda guna mencatat nilai pengembalian syscall yang berbeda.
syscall:::return
{
this->status = (uint32_t) arg0;
if (this->status == 0xc0000001UL)
{
etw_trace
(
"Tools.DTrace.Platform", /* Provider Name */
"AAD330CC-4BB9-588A-B252-08276853AF02", /* Provider GUID */
"My custom event from DTrace", /* Event Name */
1, /* Event Level (0 - 5) */
0x0000000000000020, /* Flag */
"etw_int32", /* Field_1 Name */
"PID",/* Field_1 Type */
(int32_t)pid, /* Field_1 Value */
"etw_string", /* Field_2 Name */
"Execname", /* Field_2 type */
execname, /* Field_2 Value */
"etw_string", /* Field_3 Name */
"Probefunc", /* Field_3 type */
probefunc /* Field_3 Value */
);
}
}
C:\> dtrace -s addnewetwevent.d
dtrace: script 'addnewetwevent.d' matched 1881 probes
CPU ID FUNCTION:NAME
0 93 NtAlpcSendWaitReceivePort:return
0 93 NtAlpcSendWaitReceivePort:return
0 93 NtAlpcSendWaitReceivePort:return
Kode contoh ETW NUMA MEM STATS
Contoh skrip ini menggunakan penyedia Microsoft-Windows-Kernel-Memory ETW untuk mengeluarkan data memori simpul NUMA. Ukuran halaman dapat dikonversi ke ukuran dalam KB dengan mengalikan dengan 4. Untuk informasi umum tentang NUMA, lihat Dukungan NUMA.
Kode ini juga terletak di https://github.com/microsoft/DTrace-on-Windows/blob/windows/samples/windows/etw/numamemstats.d
typedef struct KernelMemInfoEvent
{
struct nt`_EVENT_HEADER _EH;
uint32_t PartitionId;
uint32_t Count;
uint32_t NodeNumber;
}kmi;
typedef struct MemoryNodeInfo
{
uint64_t TotalPageCount;
uint64_t SmallFreePageCount;
uint64_t SmallZeroPageCount;
uint64_t MediumFreePageCount;
uint64_t MediumZeroPageCount;
uint64_t LargeFreePageCount;
uint64_t LargeZeroPageCount;
uint64_t HugeFreePageCount;
uint64_t HugeZeroPageCount;
}m_nodeinfo;
int printcounter;
BEGIN
{
printcounter = 0;
}
/* MemNodeInfo */
etw:d1d93ef7-e1f2-4f45-9943-03d245fe6c00:0xff_0xffffffffffffffff:12
{
if (printcounter%10 == 0)
{
printf ("\n \n");
printf("Partition ID: %d \n",((kmi *)arg0)->PartitionId);
printf("Count: %d \n", ((kmi *)arg0)->Count);
printf("Node number: %d\n", ((kmi *)arg0)->NodeNumber);
counters = (m_nodeinfo*)(arg0 + sizeof(struct nt`_EVENT_HEADER) + 12);
print(*counters);
/* Dump rest of the NUMA node info */
if (((kmi *)arg0)->Count > 1)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(1)) + (sizeof(uint32_t)*(1)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(1)) + (sizeof(uint32_t)*(1)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 2)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(2)) + (sizeof(uint32_t)*(2)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(2)) + (sizeof(uint32_t)*(2)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 3)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(3)) + (sizeof(uint32_t)*(3)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(3)) + (sizeof(uint32_t)*(3)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 4)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(4)) + (sizeof(uint32_t)*(4)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(4)) + (sizeof(uint32_t)*(4)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 5)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(5)) + (sizeof(uint32_t)*(5)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(5)) + (sizeof(uint32_t)*(5)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 6)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(6)) + (sizeof(uint32_t)*(6)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(6)) + (sizeof(uint32_t)*(6)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 7)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(7)) + (sizeof(uint32_t)*(7)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(7)) + (sizeof(uint32_t)*(7)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 8)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(8)) + (sizeof(uint32_t)*(8)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(8)) + (sizeof(uint32_t)*(8)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 9)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(9)) + (sizeof(uint32_t)*(9)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(9)) + (sizeof(uint32_t)*(9)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 10)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(10)) + (sizeof(uint32_t)*(10)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(10)) + (sizeof(uint32_t)*(10)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 11)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(11)) + (sizeof(uint32_t)*(11)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(11)) + (sizeof(uint32_t)*(11)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 12)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(12)) + (sizeof(uint32_t)*(12)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(12)) + (sizeof(uint32_t)*(12)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 13)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(13)) + (sizeof(uint32_t)*(13)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(13)) + (sizeof(uint32_t)*(13)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 14)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(14)) + (sizeof(uint32_t)*(14)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(14)) + (sizeof(uint32_t)*(14)) + sizeof(uint32_t));
print(*counters);
}
if (((kmi *)arg0)->Count > 15)
{
nodenumber = (uint32_t *) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(15)) + (sizeof(uint32_t)*(15)) );
printf ("Node Number: %d \n", *nodenumber);
counters = (m_nodeinfo*) (arg0 + sizeof(struct nt`_EVENT_HEADER) + 8 + (sizeof(m_nodeinfo)*(15)) + (sizeof(uint32_t)*(15)) + sizeof(uint32_t));
print(*counters);
}
}
exit(1);
printcounter++;
}
Simpan file sebagai etwnumamemstats.d
Buka perintah sebagai Administrator dan jalankan skrip menggunakan opsi -s.
Berjalan pada PC Windows klien, satu simpul NUMA ditampilkan.
C:\> dtrace -s etwnumamemstats.d
trace: script 'etwnumamemstats.d' matched 36 probes
CPU ID FUNCTION:NAME
0 42735 0xff_0xffffffffffffffff:12
Partition ID: 0
Count: 1
Node number: 1
m_nodeinfo {
uint64_t TotalPageCount = 0xab98d
uint64_t SmallFreePageCount = 0
uint64_t SmallZeroPageCount = 0x1bec
uint64_t MediumFreePageCount = 0
uint64_t MediumZeroPageCount = 0x5a
uint64_t LargeFreePageCount = 0
uint64_t LargeZeroPageCount = 0
uint64_t HugeFreePageCount = 0
uint64_t HugeZeroPageCount = 0
}
0 42735 0xff_0xffffffffffffffff:12
Jenis data ETW yang didukung
| Jenis ETW | Tipe data Bahasa D | Notes |
|---|---|---|
| etw_struct | Integer | Nilai payload jenis ini mewakili jumlah anggota yang akan dimiliki struktur baru. |
| etw_string | string | Tidak tersedia |
| etw_mbcsstring | string | Tidak tersedia |
| etw_int8 | Integer | Ukuran tipe harus sesuai, dan pengubahan tipe ke `int8_t` dalam skrip D disarankan |
| etw_uint8 | Integer | Ukuran tipe harus sesuai, dan pengecoran tipe ke `uint8_t` dalam skrip D disarankan. |
| etw_int16 | Integer | Ukuran tipe harus sesuai, dan konversi menjadi `int16_t` dalam skrip D disarankan. |
| etw_uint16 | Integer | Ukuran jenis harus cocok, dan pencastingan menjadi `uint16_t` dalam skrip D disarankan. |
| etw_int32 | Integer | Tidak tersedia |
| etw_uint32 | Integer | Tidak tersedia |
| etw_int64 | Integer | Jenis harus ditetapkan secara eksplisit sebagai `int64_t` karena secara default D menggunakan `int32_t` |
| etw_uint64 | Integer | Jenis harus eksplisit sebagai "int64_t" karena D secara default ke "int32_t". |
| etw_float | Skalar | Konstanta floating-point tidak diperbolehkan dalam skrip D, tetapi diperbolehkan pada simbol yang dimuat. |
| etw_double | Skalar | Konstanta floating-point tidak diperbolehkan dalam skrip D, tetapi diperbolehkan pada simbol yang dimuat. |
| etw_bool32 | Integer | Tidak tersedia |
| etw_hexint32 | Integer | Tidak tersedia |
| etw_hexint64 | Integer | Jenis harus secara eksplisit berupa 'int64_t' karena D secara default menggunakan 'int32_t' |
| etw_countedmbcsstring | Integer | Tidak tersedia |
| etw_intptr | Integer | Ukuran jenis data berubah sesuai dengan arsitektur ('int32_t' vs 'int64_t') |
| etw_uintptr | Integer | Ukuran jenis data berubah sesuai dengan arsitektur ('int32_t' vs 'int64_t') |
| etw_pointer | Integer | Ukuran jenis data berubah sesuai dengan arsitektur ('int32_t' vs 'int64_t') |
| etw_char16 | Integer | Ukuran tipe harus sesuai, dan pencastingan ke `int16_t` dalam skrip D disarankan. |
| etw_char8 | Integer | Ukuran tipe harus sesuai, dan pengubahan tipe ke `int8_t` dalam skrip D disarankan. |
| etw_bool8 | Integer | Ukuran jenis harus cocok, dan transmisi ke 'int8_t' dalam skrip D disarankan |
| etw_hexint8 | Integer | Ukuran jenis harus cocok, dan pengubahan tipe ke `int8_t` dalam skrip D disarankan. |
| etw_hexint16 | Integer | Ukuran jenis harus cocok, dan pengalihan tipe ke 'int16_t' dalam skrip D disarankan |
| etw_pid | Integer | Tidak tersedia |
| etw_tid | Integer | Tidak tersedia |
| etw_mbcsxml | Integer | Tidak tersedia |
| etw_mbcsjson | Integer | Tidak tersedia |
| etw_countedmbcsxml | Integer | Tidak tersedia |
| etw_countedmbcsjson | Integer | Tidak tersedia |
| etw_win32error | Integer | Tidak tersedia |
| etw_ntstatus | Integer | Tidak tersedia |
| etw_hresult | Integer | Tidak tersedia |