Apprentissage du traçage d'événements pour Windows: théorie et pratique

Bonne après-midi. Récemment, j'ai dû gérer le service de trace de Windows. Ce service est apparu dans Windows 2000. Cependant, il y avait très peu d'articles sur ce service sur Internet. L'idée d'écrire cet article est donc apparue. Commençons donc!

Aujourd'hui, je vais essayer de parler de:

  1. Théorie du service de traçage Windows
  2. Création de votre session ETW
  3. Utilisation de l'API de suivi des événements pour travailler avec ETW
  4. Utilisation de tracerpt et xperf pour travailler avec ETW

Théorie du service de traçage Windows


Le suivi des événements pour Windows (ETW) est un service qui vous permet de recevoir des événements d'un ou plusieurs fournisseurs d'événements en temps réel ou d'un fichier * .etl pendant une certaine période. Pas clair? Voyons maintenant!

Pour comprendre le fonctionnement d'ETW, vous devez comprendre la structure de ce service. L'

image

architecture ETW comprend 4 éléments

  1. fournisseurs d'événements
  2. consommateurs d'événements
  3. Contrôleurs ETW
  4. Sessions ETW (sessions de suivi d'événements)

Le principe de fonctionnement est le suivant.

Un certain nombre de fournisseurs d'événements sont enregistrés dans le système, c'est-à-dire des applications qui peuvent partager leurs expériences avec les sessions ETW. Dans ce système, il existe également un certain nombre de sessions ETW actives qui peuvent consommer les événements d'un ou plusieurs fournisseurs et les fournir à l'utilisateur en temps réel ou écrire tous les événements des fournisseurs dans un fichier journal (* .etl). Et les contrôleurs contrôlent tout ce mouvement.

Et maintenant, nous allons examiner chaque élément de l'architecture considéré ci-dessus plus en détail pour enfin comprendre le principe du travail!

Fournisseurs d'événements


Les fournisseurs d'événements sont des applications qui contiennent des outils de suivi des événements. Une fois le fournisseur enregistré, le contrôleur peut activer ou désactiver le suivi des événements dans le fournisseur. Le fournisseur détermine son interprétation de marche ou arrêt. En règle générale, un fournisseur activé génère des événements, mais pas un fournisseur désactivé. Cela vous permet d'ajouter le suivi des événements à notre application sans qu'il soit nécessaire de générer des événements tout le temps.

Un fournisseur peut partager ses événements avec plusieurs sessions ETW à la fois.

Chaque événement se compose de deux éléments: un en-tête et des données! L'en-tête d'événement comprend des informations sur l'événement: identifiant du fournisseur, identifiant d'événement, horodatage, etc. Le reste des données est déterminé par un fournisseur spécifique: ETW reçoit toutes les données et les écrit dans le tampon, et leur interprétation est attribuée aux consommateurs d'informations.
Il existe quatre principaux types de fournisseurs: les fournisseurs

MOF (classiques) les
fournisseurs WPP
basés sur les
fournisseurs de manifeste TraceLogging.

Les fournisseurs d'événements diffèrent dans les types de champs qu'ils stockent dans les charges utiles des événements.

Les fournisseurs d'événements semblent être triés. Passez!

Contrôleurs


Un contrôleur est une application qui est responsable du fonctionnement d'une ou plusieurs sessions ETW. C'est le contrôleur qui détermine la taille et l'emplacement du fichier journal, démarre et arrête les sessions de suivi des événements (sessions ETW) et permet aux fournisseurs d'enregistrer des événements dans la session. Comme mentionné précédemment, c'est le contrôleur qui permet au fournisseur de partager ses événements!

Les consommateurs


Les consommateurs sont des applications qui reçoivent et traitent des événements d'une ou plusieurs sessions de trace en même temps. Les consommateurs peuvent recevoir des événements stockés dans des fichiers journaux ou à partir de sessions qui fournissent des événements en temps réel. Comme nous le savons déjà, une session ETW peut avoir plusieurs fournisseurs. La question se pose: y aura-t-il de la confusion? Comment les événements des différentes sessions ETW seront-ils liés les uns aux autres? Les événements sont triés selon le moment où ils se produisent, c'est-à-dire le système délivre les événements par ordre chronologique!

Sessions ETW


Les sessions de suivi des événements (sessions ETW) enregistrent les événements d'un ou plusieurs fournisseurs autorisés par le contrôleur. La session est également responsable de la gestion et du vidage des tampons.

Le suivi des événements prend en charge jusqu'à 64 sessions de suivi des événements qui s'exécutent simultanément. De ces sessions, il y a deux sessions spéciales. Les sessions restantes sont disponibles pour une utilisation générale. Deux sessions spéciales:

  • Session d'enregistrement global
  • Session d'enregistrement du noyau NT

Une session de trace d'événement Global Logger enregistre les événements qui se produisent au début du processus de démarrage du système d'exploitation, tels que ceux générés par les pilotes de périphérique.
Un enregistreur de noyau de session de suivi des événements NT enregistre les événements système prédéfinis générés par le système d'exploitation, tels que les événements d'E / S disque ou les échecs de page.

Alors maintenant, allons nous entraîner !!!

Création de votre session ETW


Avant de commencer à travailler, nous avons besoin de connaître plusieurs utilitaires, à savoir: une

liste de fournisseurs disponibles sur un système d'exploitation particulier

logman query providers

obtenir des informations complètes sur le fournisseur

wevtutil gp < > /ge /gm

liste de toutes les sessions ETW actives

xperf -loggers

De plus, pour visualiser des fichiers, il est conseillé d'avoir Notepad ++.

Après avoir regardé la liste des fournisseurs sur votre ordinateur (et il y en a plus de 1000 sur Windows 10), nous en choisirons un pour notre session:

image

j'ai choisi Microsoft-Windows-WinINet (ce service enregistre toutes nos actions lorsque l'on travaille dans le navigateur Microsoft Edge).

1. Win + R -> compmgmt.msc
2. «Performance»
3. «Data Collector Sets»
4. «Event Trace Sessions»
5. "Nouveau"
6. "Ensemble de collecteurs de données"
7. Spécifiez le nom du collecteur de données
8. "Créer manuellement (avancé)" ("Créer manuellement (pour expérimenté)")

image
9. Ajouter des informations intéressantes fournisseurs américains par session
10. Spécifiez les mots-clés qui nous intéressent dans le champ "Mots-clés (Tout)" - 0xFFFFFFFFFFFFFFFFFF
11. Spécifiez le niveau de journalisation 0xFF
= image

12. Sélectionnez le chemin où le fichier journal de session sera enregistré
13. Sélectionnez le " Démarrez cet ensemble de collecteurs de données maintenant »(« Exécuter le groupe de collecteurs de données maintenant »)

Maintenant, la session que nous avons créée fonctionne. Microsoft Edge a besoin d'un peu de travail pour que la session collecte des informations sur nous!

Après un certain temps, nous allons à l'endroit où nous avons enregistré le fichier journal. Nous y exécutons la commande suivante.

tracerpt "   .etl" -o -report -summary -lr

Après avoir exécuté cette commande, 4 fichiers seront générés.

image

Nous sommes actuellement intéressés par dumpfile.xml. Vous pouvez ouvrir ce fichier via notepad ++, vous pouvez également le faire dans Excel.

Après avoir soigneusement étudié ce dossier, vous pouvez voir que cette session a rassemblé presque toutes les informations sur notre mouvement sur Internet !!! Vous pouvez en savoir plus ici: nous étudions ETW et en tirons des bénéfices .

Eh bien, et nous continuons. Nous venons de créer une session avec un seul fournisseur d'événements. Données de session reçues du fichier journal. Il est temps de coder!

Utilisation de l'API de suivi des événements pour travailler avec ETW


Sur habr il y a un article intéressant, la pire API jamais créée .

Dans cet article, vous trouverez des réponses à de nombreuses questions que vous vous poserez probablement lors de la rédaction des candidatures!

Nous allons coder en C ++.

Commençons par le plus simple.

Configurer et démarrer une session de suivi des événements


Considérons d'abord l'idée générale.

Pour démarrer une session de trace:

1) Définissez la structure EVENT_TRACE_PROPERTIES

2) Démarrez la session à l'aide de StartTrace
Ensuite, activez les fournisseurs d'événements

3) Activez les fournisseurs à l'aide de EnableTrace | EnableTraceEx | EnableTraceEx2
Pour arrêter la session de trace, vous devez:

4) Avant d'arrêter la session de trace, vous devez désactiver les fournisseurs à l'aide de EnableTrace | EnableTraceEx | EnableTraceEx2, en passant EVENT_CONTROL_CODE_DISABLE_PROVIDER

5) Appelez la fonction ControlTrace et passez-la EVENT_TRACE_CONTROL_STOP

Dans l'exemple ci-dessous, je crée une session appelée MyEventTraceSession. Le fichier journal du répertoire en cours s'appelle WriteThePuth.etl.

Le fournisseur d'événements est Microsoft-Windows-Kernel-Process. Vous pouvez découvrir son GUID en utilisant

wevtutil gp Microsoft-Windows-Kernel-Process /ge /gm

Coder directement:

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <strsafe.h>
#include <wmistr.h>
#include <evntrace.h>
#include <iostream>
#define LOGFILE_PATH L"WriteThePuth.etl"
#define LOGSESSION_NAME L"MyEventTraceSession"


// GUID,     .
//      GUID .

// {AE44CB98-BD11-4069-8093-770EC9258A12}
static const GUID SessionGuid =
{ 0xae44cb98, 0xbd11, 0x4069, { 0x80, 0x93, 0x77, 0xe, 0xc9, 0x25, 0x8a, 0x12 } };


// GUID,   ,   
//    .

//{22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716} Microsoft-Windows-Kernel-Process
static const GUID ProviderGuid =
{ 0xd22FB2CD6, 0x0E7B, 0x422B, {0xA0, 0xC7, 0x2F, 0xAD, 0x1F, 0xD0, 0xE7, 0x16 } };

void wmain(void)
{
    setlocale(LC_ALL, "ru");
    ULONG status = ERROR_SUCCESS;
    TRACEHANDLE SessionHandle = 0;
    EVENT_TRACE_PROPERTIES* pSessionProperties = NULL;
    ULONG BufferSize = 0;
    BOOL TraceOn = TRUE;

    
    BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGFILE_PATH) + sizeof(LOGSESSION_NAME);
    pSessionProperties = (EVENT_TRACE_PROPERTIES*)malloc(BufferSize);
    if (NULL == pSessionProperties)
    {
        wprintf(L"Unable to allocate %d bytes for properties structure.\n", BufferSize);
        goto cleanup;
    }

    ZeroMemory(pSessionProperties, BufferSize);
    pSessionProperties->Wnode.BufferSize = BufferSize;
    pSessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    pSessionProperties->Wnode.ClientContext = 1; //QPC clock resolution
    pSessionProperties->Wnode.Guid = SessionGuid;
    pSessionProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;
    pSessionProperties->MaximumFileSize = 1024;  // 1024 MB
    pSessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
    pSessionProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGSESSION_NAME);
    StringCbCopy((LPWSTR)((char*)pSessionProperties + pSessionProperties->LogFileNameOffset), sizeof(LOGFILE_PATH), LOGFILE_PATH);
    

    status = StartTrace((PTRACEHANDLE)&SessionHandle, LOGSESSION_NAME, pSessionProperties);
    if (ERROR_SUCCESS != status)
    {
        wprintf(L"StartTrace() failed with %lu\n", status);
        goto cleanup;
    }

    //  ,   ,      .

    status = EnableTraceEx2(
        SessionHandle,
        (LPCGUID)&ProviderGuid,
        EVENT_CONTROL_CODE_ENABLE_PROVIDER,
        TRACE_LEVEL_INFORMATION,
        0,
        0,
        0,
        NULL
        );

    if (ERROR_SUCCESS != status)
    {
        wprintf(L"EnableTrace() failed with %lu\n", status);
        TraceOn = FALSE;
        goto cleanup;
    }

    //   .    ,   
    wprintf(L"Run the provider application. Then hit any key to stop the session.\n");
    _getch();
   

cleanup:
    if (SessionHandle)
    {
        if (TraceOn)
        {
            status = EnableTraceEx2(
                SessionHandle,
                (LPCGUID)&ProviderGuid,
                EVENT_CONTROL_CODE_DISABLE_PROVIDER,
                TRACE_LEVEL_INFORMATION,
                0,
                0,
                0,
                NULL
                );
        }

        status = ControlTrace(SessionHandle, LOGSESSION_NAME, pSessionProperties, EVENT_TRACE_CONTROL_STOP);

        if (ERROR_SUCCESS != status)
        {
            wprintf(L"ControlTrace(stop) failed with %lu\n", status);
        }
    }

    if (pSessionProperties)
    {
        free(pSessionProperties);
        pSessionProperties = NULL;
    }
}

Nous analyserons le programme ci-dessus plus en détail.

1) Définissez la structure EVENT_TRACE_PROPERTIES

Pour configurer une session de suivi d'événements, vous devez utiliser la structure EVENT_TRACE_PROPERTIES pour spécifier les propriétés de la session. La mémoire que vous allouez à la structure EVENT_TRACE_PROPERTIES doit être suffisamment grande pour contenir également les noms des fichiers de session et de journal qui suivent la structure en mémoire.

2) Démarrer la session à l'aide de StartTrace

Après avoir spécifié les propriétés de la session, appelez la fonction StartTrace pour démarrer la session. Si la fonction réussit, le paramètre SessionHandle contiendra le descripteur de session et la propriété LoggerNameOffset contiendra le décalage de nom de session.

3) Activez les fournisseurs à l'aide de EnableTrace | EnableTraceEx | EnableTraceEx2

Pour activer les fournisseurs auxquels vous souhaitez autoriser l'enregistrement d'événements dans votre session, appelez la fonction EnableTrace pour activer les fournisseurs classiques et la fonction EnableTraceEx pour activer les fournisseurs basés sur des manifestes. Dans d'autres cas - EnableTraceEx2.

4) Avant d'arrêter la session de trace, vous devez désactiver les fournisseurs à l'aide de EnableTrace | EnableTraceEx | EnableTraceEx2 en passant EVENT_CONTROL_CODE_DISABLE_PROVIDER

Pour arrêter la session de trace après la collecte des événements, appelez la fonction ControlTrace et passez EVENT_TRACE_CONTROL_STOP comme code de contrôle. Pour spécifier une session à arrêter, vous pouvez transmettre le descripteur de session de trace d'événement obtenu à partir d'un appel antérieur à la fonction StartTrace, ou le nom d'une session précédemment démarrée. Assurez-vous de déconnecter tous les fournisseurs avant d'arrêter la session. Si vous arrêtez la session avant de désactiver le fournisseur pour la première fois, ETW déconnectera le fournisseur et tentera d'appeler la fonction de contrôle de rappel du fournisseur. Si l'application qui a démarré la session se termine sans déconnecter le fournisseur ou appeler la fonction ControlTrace, le fournisseur reste activé.

5) Pour arrêter la session de trace, appelez la fonction ControlTrace et passez-la EVENT_TRACE_CONTROL_STOP

Comme nous l'avons vu dans l'exemple ci-dessus, l'utilisation de l'API Event Tracing n'est pas la plus simple. Selon ce que vous faites, vous pouvez continuer à écrire des fournisseurs d'événements ou des consommateurs d'événements. Cependant, ces deux tâches sont assez volumineuses et ne seront pas prises en compte dans cet article! Une complexité supplémentaire est créée par 4 types de fournisseurs d'événements et, par conséquent, 4 options pour écrire des événements et 4 options pour leur consommation. Le travail avec l'API Event Tracing est décrit en détail et bien sur le site officiel de Microsoft. Utilisation de Event Tracing

Après avoir travaillé pendant un certain temps avec l'API Event Tracing, j'avais une question: existe-t-il des utilitaires qui me simplifieront la vie?

Utilisation de tracerpt et xperf pour travailler avec ETW


Dans ce chapitre, je ne considérerai pas ces utilitaires d'un point de vue théorique.

Vous pouvez utiliser la commande Tracerpt pour analyser les journaux de suivi des événements, les fichiers journaux générés par le moniteur de performances et les fournisseurs de trace des événements en temps réel. Il crée des fichiers de vidage, des fichiers de rapport et des schémas de rapport. Cet utilitaire a un grand nombre de paramètres, mais le "minimum" suivant convient pour commencer le travail

tracerpt " 1- .etl" ... " n- .etl" -o <   > -report <    > -summary<    > 

L'utilitaire xperf.exe est un contrôleur à part entière. Il prend en charge les arguments de ligne de commande pour gérer les fournisseurs et les sessions ETW. Les contrôleurs peuvent demander l'état des sessions actuellement actives et recevoir des listes de tous les fournisseurs enregistrés dans le système. Par exemple, pour obtenir toutes les sessions actives, utilisez la commande suivante:

C:\>xperf -loggers

et pour obtenir une liste de tous les fournisseurs enregistrés dans le système, utilisez la commande:

C:\>xperf -providers

Les contrôleurs ont quelques fonctionnalités clés supplémentaires. Ils peuvent mettre à jour les sessions et vider les tampons sur le disque.

C'est tout pour le moment!

Malheureusement, dans cet article, je n'ai pas abordé un certain nombre de questions intéressantes (par exemple, la consommation d'événements en temps réel ou le travail avec des sessions spéciales).

Vous pouvez en lire plus sur les sites suivants:

Event Tracing - documentation officielle de Microsoft
Nous étudions ETW et tirons les avantages du
Event Tracing pour Windows du mauvais côté. Mais ce n'est pas exactement la
pire API jamais créée

All Articles