Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A Windows DTrace használatával feldolgozhatja a meglévő ETW-eseményeket, és új ETW-eseményeket vehet fel.
Az Event Tracing for Windows (ETW) egy kernelszintű nyomkövetési eszköz, amellyel naplózhatja a kernel- vagy alkalmazás által meghatározott eseményeket egy naplófájlba. Az eseményeket valós időben vagy naplófájlból is felhasználhatja, és segítségével hibakeresést végezhet egy alkalmazáson, vagy meghatározhatja, hogy hol fordulnak elő teljesítményproblémák az alkalmazásban. Az ETW-vel kapcsolatos általános információkért tekintse meg az eseménykövetést ismertető témakört.
Megjegyzés:
A DTrace az 18980-es és a Windows Server 18975-ös build után támogatott a Windows Insider-buildjeiben.
A DTrace windowsos használatával kapcsolatos általános információkért lásd: DTrace.
ETW Windows DTrace Provider
A DTrace használatával rögzítheti és jelentheti a naplózott és jegyzékalapú ETW-eseményeket. Adott kulcsszavak/szintek/eventID-k vizsgálatához az ETW vizsgálatok sokkal megbízhatóbbak lesznek, ha nem használ helyettesítő karaktereket. Ehelyett határozza meg pontosan a szondát az alábbi szabályok alapján:
Mintavétel neve = etw
Modname = Szolgáltató GUID a következő formában: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, minden karakter kisbetűvel van.
Funcname = a Level_Keyword formátuma: 0x00_0x0000000000000000. Annak érdekében, hogy minden illeszkedjen, ezt 0xff_0xffffffffffffffff értékre kell beállítani.
Probename = Egész szám eseményazonosító vagy "generic_event," hogy megfeleljen az összes eseményazonosítónak.
A Mintavételnév alapján történő szűrés csak a nyilvánult események esetében működik. A nyomkövetési eseményekhez használjon helyettesítő karaktert (*).
Az ETW hasznos terhelése az arg0-en keresztül érhető el. Ez az nt'_EVENT_HEADER és az eseményspecifikus dátumból áll.
Elérhető ETW-szolgáltatók meghatározása
A logman paranccsal megjelenítheti az aktív ETW-szolgáltatókat és azok szolgáltatói GRAFIKUS AZONOSÍTÓit.
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}
...
Meglévő ETW-szolgáltató adatainak megjelenítése
A DTrace képes az ETW-események kimenetére. Ez olyan helyzetekben hasznos, ahol már létezik ETW-folyamat jelentésére, gyűjtésére és elemzésére.
Ebben a példában a DTrace paranccsal jelentheti a Microsoft-WindowsKernel-Memory szolgáltatói eseményeket.
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
Új ETW-események hozzáadása
Az Etw nyomkövetési események a etw_trace makró meghívásával hozhatók létre. Az események csak akkor lesznek naplózva, ha a megadott nyomkövetési szolgáltató aktív figyelője van, ellenkező esetben a rendszer kihagyja őket.
Az etw_trace makró olyan alapvető adattípusokat támogat, mint az int8, az uint8, az int16, az uint16, az int32, az uint32, az int64, az uint64, az hexint32, az hexint64 és a string. További részletekért tekintse meg az alábbi támogatott ETW-adattípusok táblázatot.
Példa ETW_TRACE makróra:
Ez a szkript létrehoz egy egyéni ETW-eseményt, amikor a syscall rutin 0xc0000001 - STATUS_UNSUCCESSFUL ad vissza.
Az értéket módosíthatja this->status úgy, hogy egy másik NTSTATUS-értéket használjon a különböző syscall-visszatérési értékek naplózásához.
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
ETW NUMA MEM STATS példakód
Ez a példaszkript a Microsoft-WindowsKernel-Memory ETW szolgáltatót használja a NUMA-csomópont memóriájának kiírásához. Az oldalméretet át lehet alakítani KB méretté, ha megszorozzuk 4-gyel. A NUMA-ról általános információkért lásd: NUMA-támogatás.
Ez a kód itt található: 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++;
}
Mentse a fájlt etwnumamemstats.d néven
Nyisson meg egy parancssort rendszergazdaként, és futtassa a szkriptet a -s beállítással.
Egy ügyfélszámítógépen futtatva egyetlen NUMA-csomópont jelenik meg.
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
Támogatott ETW-adattípusok
| ETW típus | D Nyelv adattípusa | Jegyzetek |
|---|---|---|
| etw_struct | Egész szám | Az ilyen típusú hasznos teher érték azt a tagszámot adja meg, amely az új struktúrának lesz. |
| etw_string | karakterlánc | Nincs adat. |
| etw_mbcsstring | karakterlánc | Nincs adat. |
| etw_int8 | Egész szám | A típus méretének meg kell egyeznie, és az 'int8_t'-re való kasztolás javasolt a D szkriptben. |
| etw_uint8 | Egész szám | A típus méretének meg kell egyeznie, és a D szkriptben a "uint8_t" értéket kell megadni |
| etw_int16 | Egész szám | A típus méretének meg kell felelnie, és a D szkriptben az `int16_t` típusra történő konvertálás javasolt |
| etw_uint16 | Egész szám | A típusméretnek meg kell egyeznie, és a D szkriptben az `uint16_t` típusra való átalakítást javasolt elvégezni. |
| etw_int32 | Egész szám | Nincs adat. |
| etw_uint32 | Egész szám | Nincs adat. |
| etw_int64 | Egész szám | A típusnak explicit módon "int64_t" kell lennie, mivel a D alapértelmezett értéke "int32_t" |
| etw_uint64 | Egész szám | A típusnak explicit módon "int64_t" kell lennie, mivel a D alapértelmezett értéke "int32_t" |
| etw_float | Skaláris | A lebegőpontos állandók nem engedélyezettek a D szkriptben, de a betöltött szimbólumokon engedélyezik |
| etw_double | Skaláris | A lebegőpontos állandók nem engedélyezettek a D szkriptben, de a betöltött szimbólumokon engedélyezik |
| etw_bool32 | Egész szám | Nincs adat. |
| etw_hexint32 | Egész szám | Nincs adat. |
| etw_hexint64 | Egész szám | A típusnak explicit módon "int64_t" kell lennie, mivel a D alapértelmezett értéke "int32_t" |
| etw_countedmbcsstring | Egész szám | Nincs adat. |
| etw_intptr | Egész szám | Az adattípus mérete az architektúra szerint változik ("int32_t" és "int64_t") |
| etw_uintptr | Egész szám | Az adattípus mérete az architektúra szerint változik ("int32_t" és "int64_t") |
| etw_pointer | Egész szám | Az adattípus mérete az architektúra szerint változik ("int32_t" és "int64_t") |
| etw_char16 | Egész szám | A típus méreteinek egyezniük kell egymással, és a D szkriptben ajánlott az `int16_t` típusra való kényszerítés. |
| etw_char8 | Egész szám | A típus méretének meg kell egyeznie, és a D szkriptben az `int8_t` típusra történő konvertálás javasolt. |
| etw_bool8 | Egész szám | A típus méretének meg kell egyeznie, és a D szkriptben javasolt az `int8_t` típusra történő konvertálás. |
| etw_hexint8 | Egész szám | A típus méretének meg kell egyeznie, és a D szkriptben az `int8_t` típusra történő átalakítás javasolt. |
| etw_hexint16 | Egész szám | A típus méretének meg kell egyeznie, és a D szkriptben a `int16_t` típusra történő kényszerítés javasolt. |
| etw_pid | Egész szám | Nincs adat. |
| etw_tid | Egész szám | Nincs adat. |
| etw_mbcsxml | Egész szám | Nincs adat. |
| etw_mbcsjson | Egész szám | Nincs adat. |
| etw_countedmbcsxml | Egész szám | Nincs adat. |
| etw_countedmbcsjson | Egész szám | Nincs adat. |
| etw_win32error | Egész szám | Nincs adat. |
| etw_ntstatus | Egész szám | Nincs adat. |
| etw_hresult | Egész szám | Nincs adat. |