Moniteur en SVG avec javascript et données en server-sent-event
-
© 2008 Félix Hauri -
EMail -
Web
Toutes les informations sur ces pages sont publiées sous les termes de la license LGPL v2.1
Ce système utilise des standard publiés. Il fonctionne sans greffons additionnels dans une version récente de FireFox, Safari, Opera ou Google Chrome.
Il ne fonctionne malheureusement pas sous Microsoft Internet Explorer, mais ce n'est pas moi que cela va contrarier... Microsoft n'a qu'à respecter les standards.
Il s'agissait d'un essai (prototype) avec pour but de- utiliser le moins de bande passante en faisant passer un minimum de données (moins de 100 octets par secondes)
- consomer le moins de ressources possible, sur le serveur
- obtenir des graphiques agréables du coté client
- avoir un maximum d'informations, du coté client
- créer des outils de monitoring intéractifs
- déléguer les tâches de programmation et de réalisation graphiques à des personnes différentes
Premier essai: Le moniteur CPU
Les deux seules informations transmises périodiquement sont UPTIME (Le temps écoulé depuis que l'ordinateur est allumé) et IDLETIME (Le temps écoulé pendant lequel le processeur est resté inactif). Le script connait l'heure à laquelle l'ordinateur é démarré (wasup), ainsi il peut calculer la totalité du temps de travail, la quantité de temps de travail depuis le dernier intervalle et l'heure interne du serveur (wasup + UPTIME).
Le dessin à été réalisé ``vite-fait'' avec skencil et sodipodi.
La documentation pour javascript/ecmascript à été trouvée à: Core JavaScript 1.5 Reference - Mozilla Developer Center
Moniteur CPU - Mode d'emploi:
Le moniteur affiche le travail du processeur en %, toutes les secondes, avec une aiguille blanche.
La valeur correspondante s'affiche en haut du cadran.
Une aiguille bleue affiche la moyenne sur 5 minutes (moyenne du graphique en dessous).
Une aiguille violette affiche la moyenne absolue depuis que l'ordinateur à été mis sous tension.Afin d'économiser les ressources sur le poste client, le graphique peut être masqué. Il suffit de cliquer dessus pour le faire disparaitre et ainsi réduire la consomation du navigateur web (les données sont toujours mémorisées).
Un click sur le logo le fera ré-apparaitre et mettre à jour.Le cadran présente un bouton ``S'' pour Snapshot qui permet de placer un repère temporel à partir duquel le moniteur calculera la moyenne. A chaque pression sur ce bouton, le moniteur positionnera ou repositionnera son repère temporel.
Un bouton ``R'' permet de supprimer le Snap pour afficher à nouveau l'aiguille violette représentant la moyenne totale.-
Voici le script perl qui envoie périodiquement les données.
#!/usr/bin/perl -w use strict; use CGI qw/:standard :push -nph/; my $q=CGI->new; $| = 1; open FH,"</proc/uptime"; sub readprocuptime { seek FH,0,0; return <FH>; } print $q->header(-type=>'text/event-stream',-charset=>"utf-8"); $SIG{'PIPE'}=sub { close FH; exit 0; }; while (1) { printf "event: ut\ndata:%s\n\n", readprocuptime; sleep 1; };
-
Ici, un example de flux de données (5 secondes).
HTTP/1.0 200 OK Server: Apache/1.3.33 (Debian GNU/Linux) PHP/4.3.10-22 mod_auth_pgsql/0.9.12.1 mod_ssl/2.8.22 OpenSSL/0.9.7e mod_jk/1.2.5 Date: Sat, 20 Jul 2013 06:35:18 GMT Content-Type: text/event-stream; charset=utf-8 event: ut data:6671695.72 2570693.36 event: ut data:6671696.72 2570694.02 event: ut data:6671697.72 2570695.01
-
Et voici la première version du ecmascript / javascript , (originalement en server-push, modifiée pour server-sent-event) que j'ai écrite pour faire le job.
<script type="text/ecmascript"> var uptm = 0; var idle = 0; var wasup = 1200903924000; var snapu = 0; var snapi = 0; var evtSock; var deviation = .014656302035730131832815841454; // deviation = 41.987deg * pi / 180 / (100/2) ; function rpltxt(fieldid,newtext) { var targettext = document.getElementById(fieldid); var os=targettext.lastChild; var ns=document.createTextNode(newtext); targettext.replaceChild(ns,os); } function fn(event) { var maarray = event.data.split(' '); var duptim = maarray[0] - uptm; var didle = maarray[1] - idle; uptm = maarray[0]; idle = maarray[1]; var dte= new Date( Math.ceil(uptm)*1000+wasup ); rpltxt('tspan931','System time: '+dte.toLocaleDateString()+ ', '+dte.toLocaleTimeString()); var prct = Math.abs(duptim-didle)/duptim*100; var aiguille=document.getElementById('aiguille'); var xpos = 231 + 270 * Math.sin( ( prct - 50 ) * deviation ); var ypos = 371 - 270 * Math.cos( ( prct - 50 ) * deviation ); aiguille.setAttribute('d','M 231 371L '+xpos+','+ypos); rpltxt('tspan923',prct.toFixed(2)+'%'); aiguille=document.getElementById('average'); if (snapu == 0) { aiguille.setAttribute('style','stroke:#ffaaff;stroke-opacity:.7;stroke-width:7;'); var avgtxt = document.getElementById('tspan925'); avgtxt.setAttribute('fill','#dd88dd'); var mprct = Math.abs(uptm - idle)/uptm*100; rpltxt('tspan925','Average: '+mprct.toFixed(2)+'%'); dte= new Date( wasup ); rpltxt('tspan929','Was up: '+dte.toLocaleDateString()+ ', '+dte.toLocaleTimeString()); } else { aiguille.setAttribute('style','stroke:#ffffaa;stroke-opacity:.7;stroke-width:7;'); var avgtxt = document.getElementById('tspan925'); avgtxt.setAttribute('fill','#dddd88'); var mprct = Math.abs((uptm-snapu) - (idle-snapi))/(uptm-snapu)*100; rpltxt('tspan925','SnapAvg: '+mprct.toFixed(2)+'%'); dte= new Date( Math.ceil(snapu)*1000+wasup ); rpltxt('tspan929','Snap: '+dte.toLocaleDateString()+ ', '+dte.toLocaleTimeString()); } xpos = 231 + 270 * Math.sin( ( mprct - 50 ) * deviation ); ypos = 371 - 270 * Math.cos( ( mprct - 50 ) * deviation ); aiguille.setAttribute('d','M 231 371L '+xpos+','+ypos); } function first(event) { evtSock=new EventSource('/cgi-bin/nph-cpu.txt'); evtSock.addEventListener("ut", fn,false); } function snap() { snapu=uptm; snapi=idle; } function desnap() { snapu=0; snapi=0; } window.onload = first; </script>