Selon l’utilisation que l’on en fait, il est souvent intéressant d’avoir un suivi de son débit et s’assurer que celui-ci reste au delà d’un minimum nécessaire et déclaré par le FAI.
Mesurer son débit à une fréquence donnée peut permettre de détecter si celui-ci reste constant sur 24h, sur la semaine, le week-end, etc.
Exemple, lorsqu’on utilise une « box 4G », comme avec un smartphone, le débit est très souvent bien en dessous des débits déclarés par les FAI. Cela dépend par exemple du nombre d’appareils attaché à l’antenne 4G utilisée dans les kilomètres à la ronde, et cela peut varier fortement selon le moment de la journée. Mais cela, on peut réellement le constater qu’en enregistrant son débit.
Autre utilisation, la mesure de débit entre deux serveurs, de sorte à s’assurer que la communication reste de qualité selon les besoins.
Outils utilisés
- iperf3
- sqlite
- dygraph
iperf3 : Outil de mesure de débit multiplateforme
iperf3 est un outil en ligne de commande permettant de mesurer son débit descendant (download) et ascendant (upload) par rapport à un serveur sur internet. Il est possible de l’utiliser en tant que client et en tant que serveur, permettant des mesures avec un serveur personnel. Cet outil existe aussi bien sous Linux que sous Windows.
Dans cet exemple, on utilisera des serveurs publiques choisis sur internet.
Voici la syntaxe de la commande iperf3 utilisée :
iperf3 -c <serveur> -p <port> -O 2 -R -J
- -c <serveur> : Utilise iperf3 en mode client en utilisant le serveur dont l’hôte est <serveur>.
- -p : Défini le numéro de port du serveur sur lequel se connecter pour le test (par défaut 5200).
- -O 2 : Ignore les deux premières secondes de test.
- -R : Inverse le sens de mesure du débit, nécessaire pour mesurer le débit descendant (download).
- -J : Afficher le résultat au format JSON.
Afficher le résultat au format JSON permet de récupérer la donnée de test facilement par script avec jq pour l’insertion dans une base SQLite.
iperf3 -c paris.testdebit.info -p 9200 -O 2 -R -J > /tmp/debit_download.json
Exemple de résultat (contenu du fichier /tmp/debit_download.json) :
{
"start": {
"connected": [{
"socket": 5,
...
"remote_host": "89.84.1.186",
"remote_port": 9200
}],
"version": "iperf 3.6",
...
"end": {
...
"sum_sent": {
"start": 0,
"end": 10.891007,
"seconds": 10.891007,
"bytes": 1382582,
"bits_per_second": 1015576.9801635422,
"retransmits": 0
},
"sum_received": {
"start": 0,
"end": 9.9996500015258789,
"seconds": 9.9996500015258789,
"bytes": 789482,
"bits_per_second": 631607.70617334032
},
...
}
}
La donnée intéressante pour la mesure de débit est end.sum_sent.bits_per_second que l’on récupère avec la commande suivante :
jq -r ".end.sum_sent.bits_per_second" /tmp/debit_download.txt
Ce procédé est à faire une deuxième fois pour l’ascendant (upload) avec les commandes suivantes :
iperf3 -c paris.testdebit.info -p 9200 -O 2 -J > /tmp/debit_upload.json
On retire le paramètre -R et on renvoi le résultat dans un fichier différent (/tmp/debit_upload.json)
La commande jq est identique pour ce nouveau fichier :
jq -r ".end.sum_sent.bits_per_second" /tmp/debit_upload.txt
Enregistrement des données dans un fichier SQLite
SQLite est un système permettant le stockage de données dans un fichier en utilisant le langage SQL. Il évite d’utiliser des SGBD robuste et lourd en mode client serveur pour du stockage de données en quantité relativement moins importante.
On utilise la commande sqlite3 et on crée dans un premier temps le fichier de données et la table qui contiendra nos mesures :
sqlite3 ~/data/mesures_debit.db
L’exécution de cette commande crée le fichier ~/data/mesure_debit.db (le répertoire data doit exister dans le home) et donne un prompt prêt à exécuter des requêtes SQL.
Voici la requête de création de la table des mesures :
CREATE TABLE debit (
id integer primary key autoincrement,
dateheure datetime,
download double,
upload double
);
- id : Par convention, je crée toujours un champs id, souvent utile pour la maintenance, servant de clé primaire.
- dateheure : Date et heure de la mesure.
- download et upload : Valeur des mesures en bits par seconde.
La requête SQL d’insertion d’une mesure de débit est de la forme suivante :
INSERT INTO debit (dateheure, download, upload)
VALUES (datetime('now'), '$down', '$up');
Script d’enregistrement des mesures
En combinant les commandes spécifiées précédemment, voici un exemple de script SH simple :
#!/bin/bash
server=paris.testdebit.info
port=9200
echo Mesure download via $server port $port
iperf3 -c $server -p $port -O 2 -R -J > /tmp/debit_download.txt
echo Mesure upload via $server port $port
iperf3 -c $server -p $port -O 2 -J > /tmp/debit_upload.txt
echo Mesures terminées
echo Insertion dans la base debit.db
# Enregistrement de la mesure descendante dans la variable $down
down=`jq -r ".end.sum_sent.bits_per_second" /tmp/debit_download.txt`
# Enregistrement de la mesure
ascendante dans la variable $up
up=`jq -r ".end.sum_sent.bits_per_second" /tmp/debit_upload.txt`
# Enregistrement des mesures dans le fichier SQLite
sqlite3 ~/data/mesure_debit.db "insert into debit (dateheure, download, upload) values (datetime('now'), '$down', '$up');"
Ce script peut être optimisé, par exemple en vérifiant le code de retour des commandes iperf3, les mesures pouvant échouées, en ajoutant d’autres serveurs et ports aléatoires parmis ceux disponibles trouvés sur internet, etc.
Pour une exécution répétée de façon automatique, il suffit de l’ajouter à une crontab. Par exemple, toutes les 30 minutes :
*/30 * * * * pi /home/pi/src/sh/mesure_debit/mesure_debit.sh
Cette exemple montre que j’ai effectué ce test sur un Raspberry PI.
Affichage des résultats sous forme graphique web dynamique avec dygraph
dygraph est une librairie javascript permettant la génération de graphique.
Dans un premier temps, il faut gérer une extraction des données au format CSV pour l’interprétation des données en graphique, que l’on fera avec l’aide de PHP.
Une requête simple est la suivante :
select
datetime(dateheure,'localtime') as dateheure,
round(download/(1024*1024),1) as download,
round(upload/(1024*1024),1) as upload
from debit
order by dateheure
- dateheure : On utilise la fonction SQLite datetime sur le champs dateheure avec le paramètre ‘localtime’ pour afficher la date et heure dans notre fuseau horaire.
- download et upload : Les valeurs sont divisées par 1024*1024 pour obtenir les résultats en mbit/s, arrondis au dixième.
- Le résultat de la requête est trié par dateheure.
Voici le script PHP nommé datas.php qui extrait les données au format CSV attendu par la librairie dygraph :
<?php
header('Content-type: text/plain');
echo "dh,download,upload\n";
$db = new SQLite3("/home/pi/data/mesure_debit/debit.db");
$resultats = $db->query("
select
datetime(dateheure,'localtime') as dateheure,
round(download/(1024*1024),1) as download,
round(upload/(1024*1024),1) as upload
from debit
");
while ( $row = $resultats->fetchArray() )
echo
(new DateTime($row['dateheure']))->format("Y/m/d H:i").",".
$row['download'].",".
$row['upload']."\n";
?>
On génère le graphique dygraph via un fichier HTML, en utilisant les librairies javasript de dygraph et JQuery :
<html>
<head>
<meta charset="UTF-8">
<script src="/js/dygraph.min.js"></script>
<script src="/js/jquery-3.5.1.min.js"></script>
<link rel="stylesheet" href="/css/dygraph.css" />
<style type="text/css">
#div_g {
width: 100%;
height: 320px;
margin-bottom: 10px;
}
.chart { border: 1px dashed black; margin: 5px 5px 5px 50px; padding: 2px; width: 100% }
</style>
</head>
<body>
<div id="div_g"></div>
<script>
$(document).ready(function() {
new Dygraph(
document.getElementById("div_g"),
"datas.php",
{
legend:'always',
ylabel:'Mbits/s',
showRoller:true,
width:'100%'
}
);
});
</script>
</body>
</html>
Voici un exemple avec mes tests de box 4G :
Il est possible de zoomer à la souris en sélectionnant une zone. Sur des appareils tactiles (smartphone, tablette), il est possible de zoomer et déplacer le graphique avec le tactile. Un double clic sur le graphique permet de réinitialiser les échelles.
Et pour aller plus loin, voici une requête permettant de moyenner toutes les valeurs enregistrer par demi heure, tout en récupérant également les valeurs minimums et maximums :
select
'01/01/01 '||time(round(strftime('%s',dateheure)/(30.0*60))*(30*60),'unixepoch') as heure,
round(min(download/(1024*1024)),1) as min_download,
round(avg(download/(1024*1024)),1) as download,
round(max(download/(1024*1024)),1) as max_download,
round(min(upload/(1024*1024)),1) as min_upload,
round(avg(upload/(1024*1024)),1) as upload,
round(max(upload/(1024*1024)),1) as max_upload
from debit
group by time(round(strftime('%s',dateheure)/(30.0*60))*(30*60),'unixepoch')
On regroupe les valeurs par demi heure la plus proche, techniquement en appliquant une division entière par 30 minutes à la valeur timestamp Unix des dates et heures d’enregistrement.
Pour chaque demi heure, on sélectionne la moyenne, le minimum et le maximum des débits ascendants et descendants.
Voici un exemple avec mes tests de box 4G :
Ce dernier graphique est très intéressant, car il montre facilement qu’en moyenne, le débit est très bas en journée, aux alentours de 5mbit/s, et même entre 1 et 2mbit/s à partir de 17h, il augmente qu’aux environs de 23h pour atteindre une moyenne de 50mbit/s la nuit, mais commence à baisser à 6h du matin.
Deux zones verte et bleue apparaissent pour faire ressortir l’amplitude des mesures.
Ces enregistrements et affichages graphiques me montrent ainsi clairement dans cet exemple que l’antenne 4G utilisée par la box est surchargée en journée.
Conclusion
Cet article montre l’utilisation de plusieurs outils utilisables dans de multiples situations :
- iperf3 pour la mesure de débit.
- sqlite3 pour l’enregistrement de données.
- shell pour du scripting sous Linux, utilisation notamment de jq pour la lecture de données json.
- php pour la lecture de données SQLite, leur affichage en CSV.
- dygraph pour la génération de graphique dynamique en javascript.
N’hésitez pas à me contacter via la page Me contacter pour de plus amples informations ou demande quelconque.