Munin est un outil de surveillance système et réseau open source sous licence publique générale GNU, basé sur l’outil RRDtool.
Il présente ses résultats sous forme de graphiques disponibles via une interface web. Il possède une structure de plugins particulièrement simple qui permet d’enrichir rapidement l’outil.
Source : Wikipedia
Nous allons donc écrire ensemble notre premier plugin. Ce dernier aura pour objectif de monitorer la consommation en RAM du serveur web Nginx.
Le choix du langage de programmation utilisé importe peu. En fait, la seule condition imposée par Munin est le format dans lequel les données sont retournées. Pour ce plugin, j’ai choisi le langage Perl, c’était une occasion pour moi de toucher à un nouveau language de programmation, étant donné que j’avais constaté qu’une grande partie des plugins l’utilisaient.
Ce plugin aurait très bien pu être codé en script Shell ou en Ruby, cela n’aurait eu aucune incidence sur le résultat final.
Pour commencer, nous allons donc créer le fichier source et le rendre exécutable :
touch /usr/share/munin/plugins/nginx_memory chmod +x /usr/share/munin/plugins/nginx_memory
Ensuite, il faudra que notre script se comporte de deux manières différentes, suivant que son appel comporte ou non le paramètre config
.
- Appellé sans paramètre, Munin attend de notre script qu’il retourne la valeur à monitorer, soit, la consommation en RAM de notre serveur Web.
- Appelé avec le paramètre
config
, Munin s’attend à recevoir les paramètres de configuration lui permettant de tracer le graph selon nos attentes.
Nous pouvons donc écrire la première partie de notre script comme ceci :
#!/usr/bin/env perl if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { # Affichage de la configuration } else { # Affichage des données }
Configuration
La première partie de notre code devra donc indiquer à Munin commentafficher les données. L’exemple ci-dessous est assez minimaliste, mais vous pourrez trouver la liste des arguments supporté dans la documentation.
if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { print "graph_title NGINX ram usage\n"; print "graph_vlabel ram\n"; print "graph_category nginx\n"; print "ram.label ram\n"; print "graph_args --base 1024\n"; } else { }
Vérifions que les données s’affichent correctement :
akyrho@gus:~$ perl /usr/share/munin/plugins/nginx_memory config graph_title NGINX ram usage graph_vlabel ram graph_category nginx ram.label ram graph_args --base 1024
- graph_title : Défini l’intitulé du graphique
- graph_vlabel : Défini le libélé de l’axe des Y
- graph_category : Permet de classer le graphique dans une catégorie, par exemple, pour rassembler toutes les données concernant Nginx dans une même catégorie à l’affichage
- ram.label : Libellé de la ligne tracée sur le graph
- graph_args –base 1024 : Dans cet exemple précis, notre unité de mesure est l’octet, qui se converti par paliers de 1024 unité, et non 1000 (valeur par défaut). Pour permettre à Munin de convertir proprement les unités, il est utile de le lui préciser.
Calcul et retour des données
La seconde partie de notre script va devoir dire à Munin quoi afficher sur notre graph. Pour ce faire, nous allons récupérer, via la commande Unix ad-hoc, la consommation en RAM de chaque processus Nginx en cours d’exécution. Pour ce faire, nous utiliserons la commande ps :
akyrho@gus:~$ ps auwx | grep nginx root 3296 0.0 0.1 4600 764 ? Ss Apr23 0:00 nginx: master process /usr/sbin/nginx www-data 3297 0.0 0.3 5264 1892 ? S Apr23 0:07 nginx: worker process akyrho 17274 0.0 0.1 1788 536 pts/0 S+ 17:38 0:00 grep nginx
Nous remarquons que la commande nous retourne également le processus grep nginx
qui risque de fausser notre mesure. De plus, lorsque cette commande sera exécutée par notre script, le script en lui-même sera retourné dans les résultats. Nous allons donc modifier la syntaxe de notre commande comme suit :
akyrho@gus:~$ ps auwx | grep nginx | grep -v grep | grep -v nginx_memory root 3296 0.0 0.1 4600 764 ? Ss Apr23 0:00 nginx: master process /usr/sbin/nginx www-data 3297 0.0 0.3 5264 1864 ? S Apr23 0:07 nginx: worker process
La consommation en RAM de chaque processus est représentée sur la sixième colonne, soit 764+1864 = 2628ko.
Il nous faut donc, pour chaque ligne retournée, récupérer la valeur de la sixième colonne, exprimée en kilo-octet. En Perl :
if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { } else { my $i = Integer; @cmd = `ps auwx | grep nginx | grep -v grep | grep -v nginx_memory`; foreach (@cmd) { @return = split(/ +/, $_); $i += @return[5]*1024; } print "ram.value ".$i."\n"; }
Remarquez que l’on multiplie la valeur récupérée par 1024, ce qui nous permet de renvoyer une valeur exprimée en octets à Munin.
akyrho@gus:~$ perl /usr/share/munin/plugins/nginx_memory ram.value 2691072
Notre script nous retourne donc une consommation de 2691072 octets, soit 2628ko, soit 2.56Mo.
Activation du plugin et visualisation du résultat
Notre plugin est maintenant terminé, il ne reste qu’à l’activer en créant un lien symbolique vers le dossier de plugins, et à redémarrer le processus munin-node
:
akyrho@gus:~$ sudo ln -s /usr/share/munin/plugins/nginx_memory /etc/munin/plugins/ akyrho@gus:~$ sudo /etc/init.d/munin-node restart
Et nous pouvons admirer notre résultat :
Code complet et téléchargement
#!/usr/bin/env perl # # Munin plugin for monitoring Nginx memory usage # # Written by AkyRhO # # First release (v0.1) 2009-04-20 # Last release (v0.1a) 2009-04-26 # if ( exists $ARGV[0] and $ARGV[0] eq "config" ) { print "graph_title NGINX ram usage\n"; print "graph_vlabel ram\n"; print "graph_category nginx\n"; print "ram.label ram\n"; print "graph_args --base 1024\n"; } else { my $i = Integer; @cmd = `ps auwx | grep nginx | grep -v grep | grep -v nginx_memory`; foreach (@cmd) { @return = split(/ +/, $_); $i += @return[5]*1024; } print "ram.value ".$i."\n"; }
Le code du plugin est également disponible sur Munin Exchange :nginx_memory.