Megosztás:


Streamelés használata a TraceProcessor használatával

A TraceProcessor alapértelmezés szerint úgy fér hozzá az adatokhoz, hogy betölti a memóriába a nyomkövetés feldolgozása során. Ez a pufferelési módszer könnyen használható, de memóriahasználat szempontjából költséges lehet.

A TraceProcessor biztosítja a trace.UseStreaming() funkciót is, amely támogatja a nyomkövetési adatok több típusának streamelt elérését (az adatok feldolgozását közvetlenül a nyomkövetési fájlból történő beolvasáskor, ahelyett, hogy az adatokat a memóriában pufferelné). Például egy rendszerhívás-nyomkövetés elég nagy lehet, és a rendszerhívások teljes listájának pufferelése meglehetősen költséges lehet.

Pufferelt adatok elérése

Az alábbi kód a syscall-adatok normál, pufferelt módon való elérését mutatja be nyomkövetéssel. UseSyscalls():

using Microsoft.Windows.EventTracing;
using Microsoft.Windows.EventTracing.Processes;
using Microsoft.Windows.EventTracing.Syscalls;
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: <trace.etl>");
            return;
        }

        using (ITraceProcessor trace = TraceProcessor.Create(args[0]))
        {
            IPendingResult<ISyscallDataSource> pendingSyscallData = trace.UseSyscalls();

            trace.Process();

            ISyscallDataSource syscallData = pendingSyscallData.Result;

            Dictionary<IProcess, int> syscallsPerCommandLine = new Dictionary<IProcess, int>();

            foreach (ISyscall syscall in syscallData.Syscalls)
            {
                IProcess process = syscall.Thread?.Process;

                if (process == null)
                {
                    continue;
                }

                if (!syscallsPerCommandLine.ContainsKey(process))
                {
                    syscallsPerCommandLine.Add(process, 0);
                }

                ++syscallsPerCommandLine[process];
            }

            Console.WriteLine("Process Command Line: Syscalls Count");

            foreach (IProcess process in syscallsPerCommandLine.Keys)
            {
                Console.WriteLine($"{process.CommandLine}: {syscallsPerCommandLine[process]}");
            }
        }
    }
}

Streamelési adatok elérése

Nagy syscalls-nyomkövetés esetén a syscall-adatok memóriabeli pufferelése meglehetősen költséges lehet, vagy akár nem is lehetséges. Az alábbi kód bemutatja, hogyan férhet hozzá szisztematikusan ugyanazokhoz a syscall-adatokhoz streamelési módon, azáltal hogy lecseréli a trace.UseSyscalls()-t a trace.UseStreaming().UseSyscalls()-ra.

using Microsoft.Windows.EventTracing;
using Microsoft.Windows.EventTracing.Processes;
using Microsoft.Windows.EventTracing.Syscalls;
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.Error.WriteLine("Usage: <trace.etl>");
            return;
        }

        using (ITraceProcessor trace = TraceProcessor.Create(args[0]))
        {
            IPendingResult<IThreadDataSource> pendingThreadData = trace.UseThreads();

            Dictionary<IProcess, int> syscallsPerCommandLine = new Dictionary<IProcess, int>();

            trace.UseStreaming().UseSyscalls(ConsumerSchedule.SecondPass, context =>
            {
                Syscall syscall = context.Data;
                IProcess process = syscall.GetThread(pendingThreadData.Result)?.Process;

                if (process == null)
                {
                    return;
                }

                if (!syscallsPerCommandLine.ContainsKey(process))
                {
                    syscallsPerCommandLine.Add(process, 0);
                }

                ++syscallsPerCommandLine[process];
            });

            trace.Process();

            Console.WriteLine("Process Command Line: Syscalls Count");

            foreach (IProcess process in syscallsPerCommandLine.Keys)
            {
                Console.WriteLine($"{process.CommandLine}: {syscallsPerCommandLine[process]}");
            }
        }
    }
}

A streamelés működése

Alapértelmezés szerint az összes streamelési adat a nyomkövetés első áthaladása során lesz megadva, és más forrásokból származó pufferelt adatok nem érhetők el. A fenti példa bemutatja, hogyan kombinálható a streamelés és a pufferelés – a száladatok pufferelése a syscall-adatok streamelése előtt. Ennek eredményeképpen a nyomkövetést kétszer kell beolvasni – egyszer a pufferelt száladatok lekéréséhez, majd egy második alkalommal a streamelési syscall-adatok eléréséhez a pufferelt száladatokkal. A folyamatos lejátszás és a pufferelés ilyen módon történő kombinálásához a példa a ConsumerSchedule.SecondPass-t továbbítja a trace-en keresztül a trace.UseStreaming().UseSyscalls() útvonalon, ami miatt a syscall feldolgozása egy második áthaladás során történik. A második futtatásban a syscall-visszahívás hozzáférhet a trace.UseThreads() függőben lévő eredményéhez, amikor az egyes syscallokat feldolgozza. Ezen opcionális argumentum nélkül a syscall-streamelés az első lépésben futott volna végig a nyomkövetésen (csak egy lépés lenne), és a trace.UseThreads() funkcióból származó függőben lévő eredmény még nem lenne elérhető. Ebben az esetben a visszahívásnak továbbra is hozzáférése lenne a ThreadId-hez a syscallból, de nem férne hozzá a szál folyamatához (mivel az összekapcsolt adatok feldolgozásához használt szál más eseményeken keresztül érhető el, amelyek még nem lettek feldolgozva).

Néhány fontos különbség a pufferelés és a streamelés közötti használatban:

  1. A pufferelés egy IPendingResult<T>értéket ad vissza, és az ebben lévő eredmény csak addig érhető el, amíg a nyomkövetés feldolgozása meg nem történik. A nyomkövetés feldolgozása után az eredmények számba vehetők olyan technikákkal, mint a foreach és a LINQ.
  2. Az streamelés egy void típusú függvényt ad vissza, és ehelyett egy visszahívási függvényt vesz át. Az egyes elemek elérhetővé válásakor egyszer hívja meg a visszahívást. Mivel az adatok nincsenek pufferelve, a foreach vagy LINQ használatával soha nem lehet számba venni az eredményeket – a streamelési visszahívásnak pufferelnie kell az adatok bármely részét, amelyet a feldolgozás befejezése után menteni szeretne használatra.
  3. A pufferelt adatok feldolgozására szolgáló kód a nyomkövetési hívás után jelenik meg. Folyamat(), amikor a függőben lévő eredmények elérhetők.
  4. A streamelési adatok feldolgozására szolgáló kód a trace.Process() hívás előtt jelenik meg, a trace.UseStreaming.Use...() metódus visszahívásaként.
  5. Egy streamfelhasználó dönthet úgy, hogy csak a stream egy részét dolgozza fel, és a jövőbeli visszahívásokat megszakíthatja a context.Cancel() függvény hívásával. A pufferelő fogyasztó mindig kap egy teljes, pufferelt listát.

Korrelált streamelési adatok

Előfordulhat, hogy a nyomkövetési adatok események sorozatában jelennek meg – a rendszer például külön be- és kilépési eseményeken keresztül naplózza a syscallokat, de a két esemény összesített adatai hasznosak lehetnek. A trace.UseStreaming().UseSyscalls() metódus korrelálja mindkét esemény adatait, és biztosítja azokat, amint a pár elérhetővé válik. A korrelált adatok néhány típusa nyomkövetéssel érhető el. UseStreaming():

Kód Leírás
Előnézet. UseStreaming(). UseContextSwitchData() Az adatfolyamok korrelált kapcsolóadatokat közvetítenek környezeti kapcsolókból (kompakt és nem kompakt eseményekből), pontosabb SwitchInThreadId-ket biztosítva, mint a nyers, nem kompakt események.
Trace.UseStreaming().UseScheduledTasks() Korrelált ütemezett feladatok adatait folyamokba rendezi.
nyom. UseStreaming(). UseSyscalls() Streameli az összefüggésbe hozott rendszerhívási adatokat.
nyom. UseStreaming(). UseWindowInFocus() A streamek a fókuszban lévő ablak adataival korrelálnak.

Önálló streamelési események

Továbbá, a trace.UseStreaming() különféle önálló eseménytípusokhoz biztosít elemzett eseményeket.

Kód Leírás
trace. UseStreaming(). UseLastBranchRecordEvents() Az adatfolyamok elemeznek utolsó ágrekord (LBR) eseményeket.
nyom. UseStreaming(). UseReadyThreadEvents() A streamek kész száleseményeket elemeznek.
nyom. UseStreaming(). UseThreadCreateEvents() A streamek elemzik a szál létrehozási eseményeit.
nyomkövetés.UseStreaming().UseThreadExitEvents() A stream-ek feldolgozzák a szál kilépési eseményeit.
nyom. UseStreaming(). UseThreadRundownStartEvents() Streamek szállefutáskezdési eseményeket elemeztek.
Trace.UseStreaming().UseThreadRundownStopEvents() A stream-ok parsolják a szál-lefutás leállítási eseményeit.
nyom. UseStreaming(). UseThreadSetNameEvents() Streamek elemezik a szálkészlet néveseményeit.

Alapvető adatfolyam-események korrelált adatokhoz

Végül, a trace.UseStreaming() a fenti listában szereplő adatok korrelációjának alapjául szolgáló eseményeket is biztosítja. Ezek a mögöttes események a következők:

Kód Leírás Belefoglalva
követ.UseStreaming().UseCompactContextSwitchEvents() A streamek elemeznek kompakt kontextusváltási eseményeket. Előnézet. UseStreaming(). UseContextSwitchData()
trace. UseStreaming(). UseContextSwitchEvents() Streamek elemezték a környezeti kapcsoló eseményeit. Előfordulhat, hogy a SwitchInThreadIds bizonyos esetekben nem pontos. Előnézet. UseStreaming(). UseContextSwitchData()
nyomkövetés.UseStreaming().UseFocusChangeEvents() Az adatfolyamok feldolgozzák az ablakfókuszváltási eseményeket. nyom. UseStreaming(). UseWindowInFocus()
nyom. UseStreaming(). AzScheduledTaskStartEvents() használata Streamek elemezték az ütemezett tevékenységindítási eseményeket. Trace.UseStreaming().UseScheduledTasks()
Nyomkövetés.HasználStreaming().HasználScheduledTaskStopEvents() Streamek elemezték az ütemezett feladat-leállítási eseményeket. Trace.UseStreaming().UseScheduledTasks()
trace.UseStreaming().UseScheduledTaskTriggerEvents() használata Streamek elemezték az ütemezett tevékenység eseményindító eseményeit. Trace.UseStreaming().UseScheduledTasks()
nyomkövetés. UseStreaming(). UseSessionLayerSetActiveWindowEvents() Streamek elemezték a munkamenet-réteg által beállított aktív ablakeseményeket. nyom. UseStreaming(). UseWindowInFocus()
nyomkövetés.UseStreaming().UseSyscallEnterEvents() A streamek az "enter" syscall eseményeket elemzik. nyom. UseStreaming(). UseSyscalls()
követés.UseStreaming().UseSyscallExitEvents() Streamek feldolgozták a rendszerhívás kilépési eseményeit. nyom. UseStreaming(). UseSyscalls()

Következő lépések

Ebben az oktatóanyagban megtanulta, hogyan használhatja a streamelést a nyomkövetési adatok azonnal való eléréséhez, és hogyan használhat kevesebb memóriát.

A következő lépés a nyomkövetési adatokból a kívánt adatok elérése. Tekintse meg a mintákat, hogy ötleteket merítsen. Vegye figyelembe, hogy nem minden nyomkövetés tartalmazza az összes támogatott adattípust.