Les nouvelles API de Windows Vista et Windows Serveur 2008 : Performance Logs & Alert

Auteur : Eric Vernié, responsable technique en charge des relations développeurs


Document de référence

Révision 1.0


Table des matières

IntroductionIntroduction

Performance Logs AlertPerformance Logs & Alert

Reliability and Performance MonitorReliability and Performance Monitor

  • Création d'un collecteur de données manuellement
  • Démarrer une collection via les API COM de PLA
  • Utilisation des API COM de PLA
  • Création du jeu de collecteurs
  • Créations des collecteurs IAlertDataCollector et IPerformanceCounterDataCollector

ConclusionConclusion

Introduction

Dans la série d'articles consacrés à la robustesse et à la fiabilité nous avons exploré jusqu'à présent 3 Jeux d'API

Laissez-moi vous conter aujourd'hui l'histoire du 4ième jeu d'API, Performance Logs & Alert(PLA)

** Technologies utilisées:**

C/C++

MFC

Visual Studio 2008 Beta 2

(disponible en téléchargement ici : https://msdn2.microsoft.com/en-us/vstudio/aa700831.aspx)

Software development Kit Vista  : https://www.microsoft.com/downloads/details.aspx?familyid=FF6467E6-5BBA-4BF5-B562-9199BE864D29&mg_id=10114

Performance Logs & Alert

Performance Logs and Alert (PLA) est un composant de Windows qui permet de loguer, des compteurs de performances, de tracer des événements, de tracer des appels d'API, et fournit enfin la possibilité d'ajouter des alertes lorsqu'un seuil de compteur de performance est atteint ou dépassé.

Basé sur un jeu d'interfaces COM pour configurer des collecteurs de données (Data Collector), telles que les compteurs de performance par exemple, ces collecteurs de données peuvent être planifiées pour tourner sur le système local ou sur un système distant.

PLA a été introduit avec Windows XP, mais a été amélioré avec Windows vista et Windows Serveur 2008.

  • PLA est désormais un jeu d'API COM que les éditeurs de logiciels peuvent utiliser dans leurs applications ou via des scripts type VBScript.
  • Les collecteurs de données tournent dans leur propre contexte de sécurité, plutôt que dans le contexte du service qui fournit les données. Ceci améliore la sécurité et la fiabilité du système.
  • Il est possible d'utiliser des modèles de collecteurs de données dans un format XML sous forme d'un modèle.
  • La planification de plusieurs jeux de collecteurs de données, rend possible la collection de plusieurs sessions simultanément.
  • PLA supporte désormais ETW (Event Tracing & Warning) et le nouveau fournisseur de logue d'événement Windows
  • Il est également possible via WMI.Job de planifier des collecteurs de données

Le jeu d'API de PLA est disponible sous la forme d'API COM, qui permettent de :

Collecter les données suivantes :

  • Les compteurs de performances
  • De tracer les événements en accord avec un fournisseur
  • Des données de configuration du système
  • De tracer des appels d'API

De planifier la collection des données.

D'ajouter des alertes en fonction de seuils.

Avant de rentrer plus dans le détail de ce jeu d'API, il est important de connaitre comment créer et démarrer manuellement des jeux de collection.

Reliability and Performance Monitor

Dans cette démonstration, nous allons utiliser l'outil central Reliability and Performance Monitor, pour créer un collecteur de données, qui permettra de nous alerter lorsque le seuil de 40% d'utilisation de la CPU est dépassé.

Création d'un collecteur de données manuellement

Pour créer un collecteur de données, procédez comme suit:

  1. Lancez l'outil "Reliability and Performance Monitor".
    Lancez l'outil 'Reliability and Performance Monitor'.
    Comme vous le voyez cet outil est assez complet, car il vous donne la santé de votre système à un instant T, et mesure tous types de données.

  2. Ouvrez l'élément : "Data Collector Set"
    Data Collector Set

    par défaut plusieurs collecteurs de données existent, comme le collecteur System, et le collecteur Event Trace Sessions.

  3. Pour créer son propre collecteur, sélectionnez l'élément "User Defined"

  4. Cliquez sur le bouton droit de la souris, et choisissez "New" puis "Data Collector Set"

  5. Nommez votre collecteur "MonCollecteur" et cochez la case "Create manually (Advanced)" comme sur la figure suivante, puis le bouton "Next"
    Data Collector Set

  6. Sélectionnez "Performance Counter Alert" puis le bouton "Next"
    Performance Counter Alert

  7. Vous allez ensuite choisir le compteur à ajouter en sélectionnant le bouton "Add"
    Performance Counter Alert

  8. Nous choisiront le compteur de performance "Processor" et "% Processor Time"
    Processor

  9. Indiquez dans la zone "Limit" un seuil à 40 puis appuyez sur le bouton Finish
    Limit

  10. Double-cliquez sur "DataCollector01"
    DataCollector01

  11. Sélectionnez l'onglet "Alert Action" et cochez la case, "Log an entry in the application event log", puis activez le bouton "Apply".
    Log an entry in the application event log

Vous noterez qu'il est possible avec cette interface, de démarrer la collection en sélectionnant le boutonbouton.

Ce que je vous propose maintenant c'est de démarrer ce collecteur de données via les API COM de PLA.

Démarrer une collection via les API COM de PLA

Dans cette démonstration, nous allons donc démarrer par programmation notre collecteur de données "MonCollecteur", et nous allons également l'expérimenter en ajoutant du code qui consomme de la CPU.

Nous utiliserons les MFC pour le faire

  1. Dans Visual Studio 2008, créez un projet "Boite de dialogue"

  2. Ajoutez-y un bouton

  3. Les interfaces COM de PLA sont définies dans le fichier d'entête pla.h, que vous devez inclure.

  4. Pour manipuler des collecteurs de données, vous devez créer en premier, une instance de l'interface IDataCollectorSet
    HRESULT hr=S_OK;
          IDataCollectorSet* pMonJeuDeCollecteur;
          hr = CoCreateInstance (CLSID_DataCollectorSet,
                                 NULL,CLSCTX_SERVER,
                                 IID_IDataCollectorSet,
                                 (void**)&pMonJeuDeCollecteur);

  5. Ensuite il faut demander à PLA si le collecteur "MonCollecteur" existe

     hr= pMonJeuDeCollecteur->Query (L"MonCollecteur,L"");
    if (FAILED(hr))
    {
        //Le collecteur n'existe pas
    }

  6. Si le collecteur existe, il possible de le démarrer. (Ici on le démarre en mode asynchrone)

    hr=pMonJeuDeCollecteur->Start(VARIANT_FALSE);

    Il est bien évidement possible de l'arrêter également avec la méthode Stop()

  7. Pour simuler une activité, vous allez ajouter une boucle infinie (for(;;);) sur l'événement clique d'un bouton.

  8. Exécutez le programme, démarrez le collecteur de données "MonCollecteur".
    MonCollecteur

  9. Puis démarrez la boucle infinie, pour simuler une activité processeur.

  10. Le collecteur étant un collecteur d'alerte, nous devrions donc voir dans le journal des événements, un message, nous précisant que le seuil de 40% du temps processeur est dépassé.

  11. Ouvrez le journal des événements

  12. Choisissez la section "Applications and Services Logs"

  13. Puis Microsoft, puis Windows, puis Diagnosis-PLA
    puis Diagnosis-PLA

Vous devriez voir le message **" Performance counter \Processor(_Total)\% Processor Time has tripped its alert threshold. The counter value of 74.259830 is over the limit value of 40.000000.40.000000 is the alert threshold value."**Vous précisant que le seuil est dépassé.

Utilisation des API COM de PLA pour créer des collecteurs.

Dans ce chapitre, nous allons par programmation, créer un jeu de collecteur de données qui regroupe :

  • Un collecteur de données qui devra nous alerter si
    • Le temps processeur dépasse 40%
    • Si la mémoire disponible est inférieure à 500 MO
  • Un collecteur de données qui logue dans l'outil "Performance Monitor" les compteurs suivants :
    • La mémoire utilisée
    • La consommation disque
    • La consommation Processeur

Pour ce faire, procédez comme suit :

Création du jeu de collecteurs.

Pour créer un jeu de collecteur, il faut en premier lieu utiliser l'interface IDataCollectorSet.

  

HRESULT hr=S_OK;

      IDataCollectorSet* pMonJeuDeCollecteur;

      hr = CoCreateInstance (CLSID_DataCollectorSet,

                              NULL,

                              CLSCTX_SERVER,

                              IID_IDataCollectorSet,

                              (void**)&pMonJeuDeCollecteur);

      if (FAILED(hr))

      {

            this->MessageBox (L"Impossible de créer le jeu de collecteurs",L"Erreur",0);

      }

      pMonJeuDeCollecteur->put_Description(L"Test de création d'un jeu de collecteur");

      pMonJeuDeCollecteur->put_DisplayName (L"MonCollecteur2");

      pMonJeuDeCollecteur->put_Duration (60);

      pMonJeuDeCollecteur->put_RootPath (L"%systemdrive%\\perflogs\\");

      pMonJeuDeCollecteur->put_Subdirectory (L"MercrediDuDev");

      pMonJeuDeCollecteur ->put_SubdirectoryFormat     (plaYearMonthDayHour);

Dans ce listing, le nom de mon jeu de collecteur sera "MonCollecteur2", son temps d'exécution sera limité à 60 Secondes, et les fichiers de logues seront sauvegardés dans le répertoire c:\perflogs\MercrediDuDev_xxx.

Une fois que nous avons crée ce jeu, il faut lui ajouter des collecteurs.

Il existe 5 collecteurs avec PLA. ITraceDataCollector , IApiTracingDataCollector, IConfigurationDataCollector, IAlertDataCollector, IPerformanceCounterDataCollector.

Dans notre démonstration, nous utiliserons les deux derniers, à savoir :

  • IAlertDataCollector
  • IPerformanceCounterDataCollector

Créations des collecteurs IAlertDataCollector et IPerformanceCounterDataCollector

Tout d'abord il faut retrouver la collection des collecteurs au travers de l'interfaceIDataCollectorCollection

  

IDataCollectorCollection* pMaCollectionDeCollector;

hr=pMonJeuDeCollecteur->get_DataCollectors (&pMaCollectionDeCollector);

Ensuite, nous allons instancier notre collecteur d'alerte à l'aide de la méthode CreateDataCollector de l'interface IDataCollectorCollection.
Cette méthode prend deux paramètres, le premier est une énumération qui précise le type de collecteur, iciplaAlert, le second est l'interface IDataCollector, dont dérive tous nos collecteurs.
Puis nous instancions à l'aide de QueryInterface, notre collecteur d'alerte.

  

      IDataCollector* pdc;

      hr=pMaCollectionDeCollector->CreateDataCollector (plaAlert,&pdc);

      IAlertDataCollector* monAlertCollector;

      hr=pdc->QueryInterface (IID_IAlertDataCollector, (void**)&monAlertCollector);

A partir de maintenant nous pouvons ajouter des propriétés à notre collecteur d'alerte.

Tout d'abord un nom.

  

pMonAlertCollector->put_Name (L"MonAlert");

Un intervalle de 5 secondes entre chaque la collecte des données.

  

pMonAlertCollector ->put_SampleInterval(5);

Oui je veux loguer dans le journal des événements.

  

pMonAlertCollector->put_EventLog(VARIANT_TRUE);

Et le plus important nos deux seuils d'alertes

  

long index = 0;

      SAFEARRAY *psa=SafeArrayCreateVector(VT_BSTR, 0, 2);

      if (psa)

      {

            BSTR seuil=SysAllocString (L"\\Processor(_Total)\\% Processor Time>40");

            hr = SafeArrayPutElement(psa, &index,seuil);

            SysFreeString (seuil);

            index=1;

            seuil=SysAllocString (L"\\Memory \\Available MBytes < 500");

            hr = SafeArrayPutElement(psa, &index,seuil);

            SysFreeString (seuil);

            //Ajouts de deux seuils d'alertes

            pMonAlertCollector->put_AlertThresholds (psa);

      }

      SafeArrayDestroy(psa);

      psa=NULL;

Enfin il faut ajouter le collecteur à la collection des collecteurs.

  

pMaCollectionDeCollector->Add (pMonAlertCollector);

Créons maintenant notre collecteur de compteur de performance

Instancions le collecteurIPerformanceCounterDataCollector de la même manière que précédemment avec la méthode CreateDataCollector(), en lui passant un type plaPerformanceCounter

  

hr=pMaCollectionDeCollector->CreateDataCollector (plaPerformanceCounter,&pdc);
IPerformanceCounterDataCollector* pMonPerfCollector;

hr=pdc->QueryInterface (IID_IPerformanceCounterDataCollector, (void**)&pMonPerfCollector);

Ajoutons des propriétés à notre collecteur

Un Nom

  

pMonPerfCollector->put_Name (L"MonCompteurDePerf");

Le fichier dans lequel sera logué les compteurs

  

pMonPerfCollector->put_FileName (L"Test PerfCounter")

L'intervalle de temps

  

pMonPerfCollector->put_SampleInterval (5);

Et le plus important, les compteurs de performances à loguer.

  

index=0;

      psa=SafeArrayCreateVector(VT_BSTR, 0, 4);

      if (psa)

      {

            BSTR perfcompteur=SysAllocString (L"\\memory\\*");

            hr = SafeArrayPutElement(psa, &index,perfcompteur);

            SysFreeString (perfcompteur);

            index=1;

            perfcompteur=SysAllocString (L"\\PhysicalDisk(*)\\*");

            hr = SafeArrayPutElement(psa, &index,perfcompteur);

            SysFreeString (perfcompteur);

            index=2;

            perfcompteur=SysAllocString (L"\\Processor(*)\\*");

            hr = SafeArrayPutElement(psa, &index,perfcompteur);

            SysFreeString (perfcompteur);

            index=3;

            perfcompteur=SysAllocString (L"\\Process(*)\\*");

            hr = SafeArrayPutElement(psa, &index,perfcompteur);

            SysFreeString (perfcompteur);

            //Ajouts des compteurs de performances

            pMonPerfCollector->put_PerformanceCounters (psa);

      }

Enfin nous ajoutons ce collecteur de performances à notre collection de collecteurs

  

pMaCollectionDeCollector->Add(pMonPerfCollector);

En dernier, il faut valider la transaction, pour qu'elle soit prise en compte à l'aide de la méthode Commit de l'interface IDataCollectorSet

  

IValueMap* pValidation = NULL;

pMonJeuDeCollecteur->Commit (L"Service\\MonCollecteur2",L"",  plaCreateOrModify,&pValidation);

FakePre-2268f941a5264f1797763818dda52ea3-b4cd28405ad3470bb22f20c10f24aa3b

Testons notre code,

  1. Lancez l'application, puis appuyez sur le bouton de création de collecteurs de données. Attention, pour que l'exemple fonctionne, il faut que vous lanciez l'application en mode Administrateur (cliquez droit sur l'exécutable et "run as administrator")
  2. Vous pouvez lancer "Reliability and Performance Monitor" pour vérifier que tout a bien fonctionné
    Reliability and Performance Monitor
  3. En double cliquant sur "MonCompteurDePerf, vous pouvez vérifier que les compteurs sont bien disponibles.
    MonCompteurDePerf
  4. Démarrez une collection à l'aide du bouton bouton,  au bout de 60 Secondes la collection s'arrête.
  5. Ouvrez le rapport comme sur la figure pour vérifier que les compteurs ont bien été logués.
    Ouvrez le rapport comme sur la figure pour vérifier que les compteurs ont bien été logués.
  6. Vous devez obtenir une espèce de gribouillage comme sur cette figure.
    Vous devez obtenir une espèce de gribouillage comme sur cette figure.

C'est une photo à un instant T de tous nos compteurs. Bien évidement dans mon exemple j'ai ajouté beaucoup trop de compteurs, à vous d'être plus fin et de n'ajouter que ceux qui vous intéresse.

Conclusion

Dans cet article nous venons de voir comment il était facile de créer manuellement et par programmation des collecteurs de données, qui permettent de superviser la santé de votre système.

Nous avons utilisé pour ce faire l'outil "Reliability and Performance Monitor" en concordance avec le jeu d'API COM "Performance Logs & Alert" pour la partie programmation.

La prochaine fois nous explorerons les API:

  • Wait Chain Traversal, pour la détection des étreintes fatales (deadlock).
  • Perflib V2 : La nouvelle manière de créer simplement et de consommer des compteurs de performances

Téléchargement

Téléchargez les sources