JMeter : utiliser SQLite pour traiter les résultats d’un test de charges par palier

Dans ce billet, j’indique qu’il est possible d’utiliser SQLite pour traiter les données d’un tir de charges par palier (tutoriel ici).

Voici maintenant le mode d’emploi pour utiliser SQLite afin de traiter ses résultats de tir JMeter. Tout d’abord, pour une meilleur compréhension voici le plan de test dans JMeter. Veuillez noter les noms des contrôleurs et requêtes.

Pour une insertion future des données du fichier CSV dans une base de données SQLite, il est préférable de configurer un peu le format d’enregistrement des données CSV par JMeter.

Dans le fichier JMETER_HOME/bin/user.properties, voici le format utilisé pour cet article. Cette configuration est ‘arbitraire’, il est bien entendu possible de la personnaliser en fonction de ce que vous voulez faire (ou voir).

jmeter.save.saveservice.output_format=csv
jmeter.save.saveservice.data_type=false
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
jmeter.save.saveservice.response_data=false
jmeter.save.saveservice.response_message=false
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.bytes=true
jmeter.save.saveservice.url=false
jmeter.save.saveservice.timestamp_format=yyyy-MM-dd;HH:mm:ss
jmeter.save.saveservice.default_delimiter=;
jmeter.save.saveservice.print_field_names=false
jmeter.save.saveservice.hostname=true
jmeter.save.saveservice.thread_counts=true

Après son test de charge, le fichiers de résultats à cette forme :

"2009-04-28;22:01:47";146;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-1";true;7347;11;11;130;ubuntusvr
"2009-04-28;22:01:47";38;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-2";true;7347;11;11;34;ubuntusvr
"2009-04-28;22:01:47";16;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-3";true;7347;12;12;13;ubuntusvr
"2009-04-28;22:01:48";12;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-4";true;7347;13;13;7;ubuntusvr
"2009-04-28;22:01:48";11;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-5";true;7347;15;15;7;ubuntusvr
"2009-04-28;22:01:49";11;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-6";true;7347;15;15;8;ubuntusvr
"2009-04-28;22:01:49";12;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-7";true;7347;17;17;8;ubuntusvr
"2009-04-28;22:01:49";11;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-8";true;7347;17;17;9;ubuntusvr
"2009-04-28;22:01:50";13;Requête HTTP 01_Accueil;200;"Groupe d'unités 1; 1-9";true;7347;18;18;7;ubuntusvr

On notera les points suivants :

La date et l’heure sont entre guillemets à cause du point-virgule ajouté dans le format du timestamp dans user.properties : « 2009-04-28;22:01:47 ». Ce point-virgule va nous permettre de sectionner la date et l’heure (même si en réalité, SQLite3 n’en pas vraiment besoin, mais bon…)

Le nom du groupe d’unités (thread name) est aussi entre guillemets et avec un point-virgule qui sépare le nom (celui dans l’arbre JMeter) et le numéro du thread exécutant. Car j’ai pris soin de mettre un point-virgule en fin de nom.

Dans ces deux champs, les guillemets « nous gênent », il faut donc les supprimer. Pour cela, soit on édite le fichier et on fait un ‘remplacé global’ ( » par vide), soit on passe par la commande SED disponible sous Unix ou Windows.

cat Resultats.csv | sed "s/\"//g" > PourInsertion.csv

Voilà le fichier CSV est prêt pour insertion dans la base SQLite.

La création de la base de données se fait simplement dans le lancement de SQLite.

$ sqlite3 mabase.db

Ensuite au prompt ‘sqlite>’ on peut créer la table qui va recevoir les données.

sqlite> CREATE TABLE resultats (date TEXT,heure TEXT,temps REAL,libelle TEXT,code TEXT,nomTG TEXT,
numTG TEXT,succes TEXT,octets INTEGER, actifTG INTEGER, nbTG INTEGER,latence REAL,hostname TEXT);

Il ne reste plus qu’à indiquer à SQLite le séparateur à utiliser (ici le point-virgule), puis faire l’import.

sqlite> .separator ;
sqlite> .import PourInsert.csv resultats

Et voilà, les données sont importées.

On peut commencer à jouer avec des requêtes SQL :

(je n’explique pas comment faire des requêtes SQL, si besoin, voir la documentation de SQLite)

Compter le nombre de résultats (lignes) :

sqlite> SELECT COUNT(*) FROM resultats;
400249

On se mets en mode headers ON et column sur SQLite pour faciliter la présentation des résultats de requêtes.

sqlite> .headers on
sqlite> .mode column

Moyenne des temps de réponses par libellés :

sqlite> SELECT libelle, COUNT(libelle), AVG(temps) FROM resultats GROUP BY libelle ORDER BY libelle;
libelle                          COUNT(libelle)  AVG(temps)
-------------------------------  --------------  ----------------
Contrôleur Transaction (Login)  1500            8049.02333333333
Contrôleur Transaction Créati   20725           60324.5965741858
Contrôleur Transaction Recherc  21130           120353.20241363
Requête HTTP 01_Accueil         1500            11.66
Requête HTTP 02_Connexion       1500            11.7486666666667
Requête HTTP 03_Accueil Recher  22008           10.4412940748819
Requête HTTP 04_Liste Resultat  21150           12.8220330969267
Requête HTTP 05_Fiche Client    21140           13.4635288552507
Requête HTTP 06_Creation Nouve  21030           10.5896338563956
Requête HTTP 07_Saisie Adresse  20952           11.125190912562
Requête HTTP 08_Verification i  20878           11.4587125203564
Requête HTTP 09_Validation con  20799           11.729265830088
Requête HTTP 12_Ping            205937          13.7524776994906

Moyenne des temps de réponses pour seulement les libellés avec « Requête », à partir de 300 secondes (fin de ma période de montée en charge) et jusqu’à 2100 secondes (fin du palier 1) :

sqlite> SELECT nomTG, libelle, avg(temps), count(temps) FROM resultats WHERE libelle LIKE 'Requête%' AND
 strftime("%H:%M:%S", heure) >= (select min(strftime("%H:%M:%S", heure, '+300 seconds')) from resultats) AND 
strftime("%H:%M:%S", heure) < (select min(strftime("%H:%M:%S", heure, '+2100 seconds')) from resultats) 
GROUP BY libelle, nomTG ORDER BY nomTG, heure ASC LIMIT 100;
nomTG               libelle                   avg(temps)        count(temps)
------------------  ------------------------  ----------------  ------------
Groupe d'unités 1  Requête HTTP 01_Accueil  8.61538461538461  13
Groupe d'unités 1  Requête HTTP 02_Connexi  9.04347826086956  23
Groupe d'unités 1  Requête HTTP 03_Accueil  9.0597121023636   5627
Groupe d'unités 1  Requête HTTP 04_Liste R  10.1990411931818  5632
Groupe d'unités 1  Requête HTTP 05_Fiche C  10.3475252794039  5637
Groupe d'unités 1  Requête HTTP 06_Creatio  9.18982456140351  5700
Groupe d'unités 1  Requête HTTP 07_Saisie   9.10892825820032  5701
Groupe d'unités 1  Requête HTTP 08_Verific  8.85002631117348  5701
Groupe d'unités 1  Requête HTTP 09_Validat  9.96772496053324  5701
Groupe d'unités 1  Requête HTTP 12_Ping     10.6768418636677  56641

Moyenne des temps de réponses par minute (pour seulement les requêtes) :

sqlite> SELECT strftime("%H:%M",heure) AS Heure, AVG(temps) AS Temps FROM resultats WHERE libelle LIKE 'Requête%' 
GROUP BY strftime("%H:%M",heure) ORDER BY heure ASC;
Heure       Temps
----------  ----------------
22:01       14.8518518518519
22:02       11.0076452599388
22:03       10.2652274479568
22:04       12.0887068044175
22:05       9.68851303735025
[...]
23:21       10.9501897533207
23:22       8.98496240601504
23:23       8.85897435897436

Passons aux choses un peu plus sérieuses : les tables pivots :

Moyenne des temps de réponses par palier et par requête :

sqlite> SELECT libelle, COUNT(temps) AS 'Nb Test', AVG(CASE WHEN nbTG = 750 THEN temps END) AS 'Palier 1', 
AVG(CASE WHEN nbTG = 1500 THEN temps END) AS 'Palier 2', AVG(temps) as 'Moy. Temps' FROM resultats 
WHERE libelle LIKE 'Requête%' GROUP BY libelle ORDER BY libelle ASC LIMIT 100;
libelle                   Nb Test     Palier 1    Palier 2    Moy. Temps
------------------------  ----------  ----------  ----------  ----------
Requête HTTP 01_Accueil  1500        8.6         9.0         11.66
Requête HTTP 02_Connexi  1500        9.14285714  11.9047619  11.7486666
Requête HTTP 03_Accueil  22008       8.95963999  11.5854606  10.4412940
Requête HTTP 04_Liste R  21150       10.3961495  14.6102772  12.8220330
Requête HTTP 05_Fiche C  21140       10.6435393  15.6499867  13.4635288
Requête HTTP 06_Creatio  21030       9.09737098  11.5930713  10.5896338
Requête HTTP 07_Saisie   20952       9.12340011  12.4782992  11.1251909
Requête HTTP 08_Verific  20878       8.98065683  13.1458794  11.4587125
Requête HTTP 09_Validat  20799       9.85591098  13.1065624  11.7292658
Requête HTTP 12_Ping     205937      11.0057996  15.6917482  13.7524776

Sans entrer dans les détails, la notion de tables pivot avec SQLite se fait avec l’instruction (CASE WHEN … THEN .. END). Pour plus d’infos, voir ce billet de blog.

Pour revenir à mon billet (celui que vous lisez actuellement), les tableaux sont affichés directement par SQLite, mais comment faire ? pour les avoir dans son tableur préféré : pour cela, il suffit d’exporter les tableaux dans un fichier au format CSV.

Pour cela, on utilise les commandes SQLite suivantes :

sqlite> .mode tabs
sqlite> .header off
sqlite> .output mareq.csv
sqlite> SELECT strftime("%H:%M",heure) AS Heure, AVG(temps) AS Temps FROM resultats WHERE libelle LIKE 'Requête%'
GROUP BY strftime("%H:%M",heure) ORDER BY heure ASC;

Le fichier mareq.csv peut être directement ouvert par son tableur. Ce qui donnera ce graphique.

Si on reprend la requête ‘pivot’, on obtient rapidement le tableau suivant et son graphique associé.

Pour conclure, merci à SQLite. Même si c’est pas du « clic-next », c’est rapide pour faire le ‘tri’ dans ses résultats à condition d’avoir quelques bonnes notions de SQL.

./

Une réflexion sur « JMeter : utiliser SQLite pour traiter les résultats d’un test de charges par palier »

Les commentaires sont fermés.