RRDTool, ou comment faire des joli graphes

Qu'est-ce que RRDTool ?

RRDTool, ou plus exactement Round Robin Database Tool. Pour la signification exacte de Round Robin, referez vous à la documentation Officielle [1] , car cette définition n'entre pas dans le cadre de cet article, avant tout pratique! RRDTool, c'est une suite d'outils permettant de stocker des données, sous un format ".rrd", de les restaurer, d'afficher un graphique avec ces données...

Que permet de faire RRDTool ?

Conserver des données dans une base rrdtool, pour ensuite en faire un graphique. Par exemple, on peut imaginer l' utilisation classique de ce genre d'outils: on utilise snmp pour récolter des informations sur une interface réseau (par exemple le nombre de kilobits transférés), pour faire un graphique de débits par seconde.
Mais rrdtool ne se limite pas à ça!
A partir du moment ou vous avez des données de type entier (int) ou nombre à virgule (float), vous pouvez en faire des graphiques. Par exemple, on peut monitorer la température de votre ville, la température de votre processeur, le nombre de voitures passant dans votre rue (grâce a des outils pour utiliser votre webcam en mode "détection de mouvements", avec motion [2] par exemple ;-))

Pourquoi RRDTool, et pas MRTG [3]?

RRDTool et MRTG sont du même auteur: Tobias Oetiker [4]. MRTG permet de faire des graphes, tout comme rrdtool, mais est très limité, par exemple, MRTG n'est pas capable d'afficher des valeurs négatives, ce que fait sans aucun soucis rrdtool. MRTG est très limité dans la «customisation» des graphes: mis à part changer la taille du graphique, changer la couleur de fond, l'échelle, ça s'arrête la! RRDTool est lui capable de faire tout ce que vous pouvez imaginer en manipulation graphique, ce que nous allons voir plus loin dans l'article. Dans MRTG, vous êtes obligés d'utiliser l'interface web fournie par MRTG, justement, pas sous RRDTool. MRTG est programmé en perl, et utilise GD pour faire les graphiques, RRDTool est programmé en C, et est nettement plus rapide. Il «stressera» beaucoup moins la machine chargée de faire des statistiques.
MRTG garde un historique de TOUS les enregistrements effectués, contrairement a RRDTool, qui au lieu de garder tout les enregistrements, en fait la moyenne, selon les «RRA» définies...

Installer RRDTool

Très classique:

$ apt-get install rrdtool

Voila une bonne chose de faite

Commençons par créer une première base RRDTool!

Nous allons, pour ne pas faire comme tout le monde, non pas monitorer la vitesse de transfert réseau sur eth0, mais nous allons reprendre l'exemple d'Alex van den Bogaerdt's: la vitesse d'une voiture, dans son tutorial [5] en anglais.

En effet le calcul de la vitesse d'une voiture est très proche du calcul d'un tranfert réseau. Nous avons une unité de temps, et des kilomètres. Par exemple: A 14h10 le compteur kilométrique de la voiture indique 14053Km. A 16h00, le compteur indique 14340Km. Il est facile de calculer la vitesse moyenne de parcours:
En 1h50, la voiture à parcouru 14340-14053 = 287Km
Soit: 287/1,83 (1.5*5/6=1.83) = 156Km/h
Trève de calculs, passons aux choses sérieuses: créons cette fameuse base rrd:

$ rrdtool create test.rrd           \
         --start 1051480800         \
         DS:vitesse:COUNTER:600:U:U \
         RRA:AVERAGE:0.5:1:24       \
         RRA:AVERAGE:0.5:6:10

Notez que les \ sont présents pour une meilleure lisibilité, généralement, votre shell les interprétera correctement, pour donner une commande équivalente à:

$ rrdtool create test.rrd --start 1051480800 [...]

Qu'est-ce que nous venons de créer ?
Nous avons donc crée une première base rrd, appelée test.rrd, qui commence à partir du 28 Avril 2003, date de l'écriture de l'article. Vous pouvez donc constater que rrdtool utilise le format de date spécial provenant du monde unix: le nombre de secondes écoulées depuis le premier janvier 1970 UTC. (vous pouvez retrouver le nombre de secondes en tapant la commande suivante:

$ date +%s -d 20030428

Cette base contiens une source de données (Data Source: DS) de type COMPTEUR (COUNTER): vitesse. Ce compteur sera lu toutes les 300 secondes, autrement dit toute les 5 minutes (600 * 0.5). Dans la même base, nous avons intégré 2 archives Round Robin (RRA): une qui contiendra une «moyenne» des données chaque fois qu'elles seront lues (donc pas de moyenne :p), et contenant 24 échantillons (24 x 5minutes = 2heures). L'autre sera la moyenne de 6 données (soit une demi heure) et comprendra 10 échantillons (5heures).

Supposons que le compteur de notre voiture indique les kilométrages suivants:

 00h05  12345 Km
 00h10  12357 Km
 00h15  12363 Km
 00h20  12363 Km
 00h25  12363 Km
 00h30  12373 Km
 00h35  12383 Km
 00h40  12393 Km
 00h45  12399 Km
 00h50  12405 Km
 00h55  12411 Km
 01h00  12415 Km
 01h05  12420 Km
 01h10  12422 Km
 01h15  12423 Km

Mettons à jour notre base comme suit:

 rrdtool update test.rrd 1051481100:12345 1051481400:12357 1051481700:12363
 rrdtool update test.rrd 1051482000:12363 1051482300:12363 1051482600:12373
 rrdtool update test.rrd 1051482900:12383 1051483200:12393 1051483500:12399
 rrdtool update test.rrd 1051483800:12405 1051484100:12411 1051484400:12415
 rrdtool update test.rrd 1051484700:12420 1051485000:12422 1051485300:12423

J'ai volontairement supprimé les $ que je mets d'habitude devant les commande à taper, pour que ça soit plus facile pour copier/coller. Comme vous pouvez le constater, il est possible de donner plusieurs valeurs en même temps à rrdtool.

Première récupération des données

Cette fois ci, c'est la commande "rrdtool fetch" qui va nous permettre de récupérer les données que nous avons entrées juste plus haut:

$ rrdtool fetch test.rrd AVERAGE --start 1051481100 --end 1051485300

Ce qui logiquement donnera le résultat suivant:

1051481100: nan
1051481400: 4.0000000000e-02
1051481700: 2.0000000000e-02
1051482000: 0.0000000000e+00
1051482300: 0.0000000000e+00
1051482600: 3.3333333333e-02
1051482900: 3.3333333333e-02
1051483200: 3.3333333333e-02
1051483500: 2.0000000000e-02
1051483800: 2.0000000000e-02
1051484100: 2.0000000000e-02
1051484400: 1.3333333333e-02
1051484700: 1.6666666667e-02
1051485000: 6.6666666667e-03
1051485300: 3.3333333333e-03

nan signifie Not A Number. En effet, il est impossible de calculer une vitesse avec seulement une valeur.

Les différents types de données gérés par RRDTool

RRDTool sait gérer 4 types de données:
DERIVE, GAUGE, COUNTER, ABSOLUTE
Commencez par créer ce graph, que j'ai tiré de la doc officielle rrdtool:

 rrdtool create all.rrd --start 978300900 \
          DS:a:COUNTER:600:U:U \
          DS:b:GAUGE:600:U:U \
          DS:c:DERIVE:600:U:U \
          DS:d:ABSOLUTE:600:U:U \
          RRA:AVERAGE:0.5:1:10
 rrdtool update all.rrd \
          978301200:300:1:600:300    \
          978301500:600:3:1200:600   \
          978301800:900:5:1800:900   \
          978302100:1200:3:2400:1200 \
          978302400:1500:1:2400:1500 \
          978302700:1800:2:1800:1800 \
          978303000:2100:4:0:2100    \
          978303300:2400:6:600:2400  \
          978303600:2700:4:600:2700  \
          978303900:3000:2:1200:3000
 rrdtool graph all1.gif -s 978300600 -e 978304200 -h 400 \
          DEF:linea=all.rrd:a:AVERAGE LINE3:linea#FF0000:"Line A" \
          DEF:lineb=all.rrd:b:AVERAGE LINE3:lineb#00FF00:"Line B" \
          DEF:linec=all.rrd:c:AVERAGE LINE3:linec#0000FF:"Line C" \
          DEF:lined=all.rrd:d:AVERAGE LINE3:lined#000000:"Line D"

La ligne A est un compteur, donc il devrait constamment s'incrémenter et RRDtool devrait calculer les différences. De plus, RRDtool a besoin de diviser la différence par l'intervalle de temps écoulé. Cela devrait résulter en une ligne droite à 1 (les deltas sont 300, le temps est 300)
La ligne B est une gauge, les valeurs sont les mêmes que lorsque vous les avez entrées on constate donc une sorte de vague.
La ligne C est de type derive. Cela peut être un compteur décroissant. Les valeurs peuvent donc descendre en dessous de 0...
La lignes D est de type absolute. Ce type est analogue au counter. Cependant, aucune différence n'est faite entre les valeurs, vous retrouvez donc exactement les même valeurs que celles que vous avez entrées.

Un peu de graphique!

Aller, c'est parti, cette fois on va s'amuser, créons notre premier graphique:

$ rrdtool graph vitesse.png                               \
          --start 1051481100 --end 1051485300             \
          --imgformat PNG                                 \
          DEF:vitesse=test.rrd:vitesse:AVERAGE            \
          LINE2:vitesse#FF0000

vitesse
Ceci créera un graphique commençant à minuit, et se terminant a 1h du matin.
Félicitaions, vous venez de créer votre premier graphique sous RRDTool!!
Modifions un peu ce graphique, assez «moche»!
Les couleurs sont en hexadécimal, comme dans une page HTML, par exemple.
Voici quelques bases:
#FF0000 Se lit FF 00 00, soit Rouge Vert Bleu.
Ansi:

#FF0000 sera Rouge
#00FF00 sera Vert
#0000FF sera Bleu
#FF00FF sera Rouge + Bleu
#555555 sera Gris

Vous avez la possibilité avec rrdtool de modifier pas mal de paramètres sur les graphiques, comme dit plus haut dans l'article. Parmi ces paramètres, on notera:

--vertical-label "texte"
--title "titre du graph"
--width x (ou x est en pixels)
--height x (ou x est en pixels)
--color X#xxxxxx (ou X est l'objet à colorer a voir dans la doc
officielle pour le détail [6])

Voici une commande réalisant le même graphique que précédemment, une fois customizé:

$ rrdtool graph vitesse2.png                              \
          --start 1051481100 --end 1051485300             \
          --imgformat PNG                                 \
	  --width 500 --height 200                        \
          --color CANVAS#000000				  \
	  --color BACK#101010				  \
	  --color FONT#C0C0C0				  \
	  --color MGRID#80C080				  \
	  --color GRID#808020				  \
	  --color FRAME#808080				  \
	  --color ARROW#FFFFFF				  \
	  --color SHADEA#404040				  \
	  --color SHADEB#404040				  \
          DEF:vitesse=test.rrd:vitesse:AVERAGE            \
          LINE2:vitesse#FF0000

vitesse2
Vous n'avez qu'à admirer le résultat... Je vous laisse le plaisir de mettre un titre au graphique ;-)
Comme vous pouvez le constater, l'unité n'est pas la bonne (milli...)
Au lieu de modifier directement la base rrd, nous allons donc modifier ça au niveau du graphique, à l'aide des mathématiques :)
Les mathématiques dans rrdtool sont sous forme de RPN: Reverse Polish Notation.

Voici le nouveau graphique:

$ rrdtool graph vitesse3.png                              \
          --start 1051481100 --end 1051485300             \
          --imgformat PNG                                 \
	  --width 500 --height 200                        \
          --color CANVAS#000000				  \
	  --color BACK#101010				  \
	  --color FONT#C0C0C0				  \
	  --color MGRID#80C080				  \
	  --color GRID#808020				  \
	  --color FRAME#808080				  \
	  --color ARROW#FFFFFF				  \
	  --color SHADEA#404040				  \
	  --color SHADEB#404040				  \
          DEF:vitesse=test.rrd:vitesse:AVERAGE            \
	  "CDEF:kmh=vitesse,3600,*"                       \
          LINE2:kmh#FF0000

vitesse3
Et hop nous voila la vitesse en Kilomètres par heures.
Petite explication sur le calcul effectué:
"CDEF:kmh=vitesse,3600,*" << notez que j'ai utilisé les guillements, pour ne pas que l'étoile soit interprétée par votre shell favori :)
signifie: kmh = vitesse * 3600
En RPN, on prononcerait comme suit: prendre vitesse, prendre 3600, les multiplier, mettre le résultat dans kmh.

$ rrdtool graph vitesse4.png                              \
          --start 1051481100 --end 1051485300             \
          --imgformat PNG                                 \
	  --width 500 --height 200                        \
          --color CANVAS#000000				  \
	  --color BACK#101010				  \
	  --color FONT#C0C0C0				  \
	  --color MGRID#80C080				  \
	  --color GRID#808020				  \
	  --color FRAME#808080				  \
	  --color ARROW#FFFFFF				  \
	  --color SHADEA#404040				  \
	  --color SHADEB#404040				  \
          DEF:vitesse=test.rrd:vitesse:AVERAGE            \
	  "CDEF:kmh=vitesse,3600,*"                       \
	  CDEF:rapide=kmh,100,GT,kmh,0,IF                 \
	  CDEF:bonne=kmh,100,GT,0,kmh,IF                  \
	  HRULE:100#0000FF:"Maximum autorisé"             \
	  AREA:bonne#00FF00:"Bonne vitesse"               \
	  AREA:rapide#FF0000:"Trop rapide"

vitesse4
Nous avons l'apparition de la condition IF.
CDEF:rapide=kmh,100,GT,kmh,0,IF
en RPN se lira: prendre kmh, prendre 100, kmh supérieur a 100 ?, si oui, retourner kmh, sinon retourner 0.
Passons à une RPN plus évoluée:

$ rrdtool graph vitesse5.png                              \
          --start 1051481100 --end 1051485300             \
          --imgformat PNG                                 \
	  --width 500 --height 200                        \
          --color CANVAS#000000				  \
	  --color BACK#101010				  \
	  --color FONT#C0C0C0				  \
	  --color MGRID#80C080				  \
	  --color GRID#808020				  \
	  --color FRAME#808080				  \
	  --color ARROW#FFFFFF				  \
	  --color SHADEA#404040				  \
	  --color SHADEB#404040				  \
          DEF:vitesse=test.rrd:vitesse:AVERAGE            \
	  "CDEF:kmh=vitesse,3600,*"                       \
	  CDEF:rapide=kmh,100,GT,kmh,0,IF                 \
	  CDEF:over=kmh,100,GT,100,kmh,-,0,IF             \
	  CDEF:bonne=kmh,100,GT,0,kmh,IF                  \
	  HRULE:100#0000FF:"Maximum autorisé"             \
	  AREA:bonne#00FF00:"Bonne vitesse"               \
	  AREA:rapide#550000:"Trop rapide"                \
	  STACK:over#FF0000:"Vitesse en trop"

vitesse5
On notera l'utilisation de STACK: STACK c'est comme une AREA, sauf qu'au lieu de commencer à 0, elle commencera à la dernière valeur maximale de la dernière AREA, ou LINE. Donc, la place d'une STACK est importante.
Explication sur la RPN utilisé ici:
CDEF:over=kmh,100,GT,100,kmh,-,0,IF
En RPN, on lira: prendre kmh, prendre 100, si kmh > 100, alors retourner 100 - kmh, ou bien, retourner 0.
Et voila un joli résultat de ce que peut faire RRDTool, moyennant quelques minutes de réflexion sur les RPN!
Maintenant, je laisse vos esprits travailler .... :-)

Références

[1] http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/
[2] http://motion.sourceforge.net/
[3] http://people.ee.ethz.ch/~oetiker/webtools/mrtg/
[4] oetiker at ee dot ethz dot ch
[5] http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/tutorial/rrdtutorial.html
[6] http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/rrdgraph.html

Remerciements

Vincent Deffontaines (Corrections orthographiques)


XHTML 1.1 strict. Design & code par Laurent Coustet (générée en 0.000150s )