tag:linuxfr.org,2005:/tags/supervision/publicLinuxFr.org : les contenus étiquetés avec « supervision »2022-12-11T14:01:31+01:00/favicon.pngtag:linuxfr.org,2005:Post/432922022-12-05T00:15:24+01:002022-12-05T00:15:24+01:00zabbix et modbus<p>Bonjour,</p>
<p>au boulot, nous envisageons d'installer un compteur de courant/de puissance pour pouvoir tracer nos consommations électriques de manière précise.</p>
<p>J'ai trouvé des matériels type compteur triphasé 3x100A, qui peuvent être interrogés en <a href="https://fr.wikipedia.org/wiki/Modbus">modbus</a> sur TCP. J'ai aussi vu que Zabbix, qui est l'outil de supervision que nous utilisons, a un <a href="https://www.zabbix.com/integrations/modbus">module modbus</a>. Le combo parfait, quoi. Au pire, il existe une bibliothèque Python pour modbus.</p>
<p>Mais… Je me méfie, étant donné le prix de ce genre de compteur (et de son installation), je n'ai pas trop envie de me lancer sans demander conseil avant !</p>
<p>Quelqu'un a-t-il une expérience dans le domaine de la récupération de données sur modbus, sans utiliser aucun outil propriétaire côté client ?</p>
<p>Merci !</p>
<div><a href="https://linuxfr.org/forums/linux-general/posts/zabbix-et-modbus.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/129510/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/linux-general/posts/zabbix-et-modbus#comments">ouvrir dans le navigateur</a>
</p>
cghttps://linuxfr.org/nodes/129510/comments.atomtag:linuxfr.org,2005:Post/418702021-02-12T17:18:45+01:002021-02-23T10:20:01+01:00[CDI] Admins / Ingés sys Linux confirmés - Capensis - Lille (H/F)<p><em><strong>Capensis en quelque mots :</strong></em> <br>
Fondée en 2002, Capensis est une société d'informatique <strong>spécialisée en Logiciels Libres</strong> basée sur Lille, Nantes et Tours. Depuis sa création, Capensis s'est développée avec un but constant : fournir à ses clients des solutions d'infrastructures pérennes et fiables autour des technologies Linux et Open Source.</p>
<p>Nous recherchons pour notre <strong>agence de Lille : 2 Administrateurs / Ingénieurs Systèmes Linux confirmés (H/F) 3 à 5 ans d'expérience</strong></p>
<p><em><strong>Vos missions si vous les acceptez ?</strong></em> <br>
Intégrez notre équipe sur des <strong>projets Open Source innovants ! Cultivez vos compétences et participez au développement de notre société</strong>. <br>
Nos clients (régionaux et nationaux), nous sollicitent pour les accompagner dans l'évolution de leur infrastructure vers le Cloud dans un contexte d'automatisation, de Dockerisation de leurs applications, de maintien en conditions opérationnelles de leur infra Libre et la mise en place d'outillages associés pour le pilotage (monitoring). </p>
<p>Managé par le responsable technique, vous serez chargé de : <br>
- Administrer et <strong>optimiser les infrastructures Open Source</strong> de nos clients <br>
- Mettre en place et maintenir des <strong>solutions d’orchestration et d’automatisation</strong> <br>
- Rédiger des <strong>documentations</strong> (techniques, exploitation, utilisateurs…) <br>
- Assister les commerciaux sur des démonstrations / <strong>avant-ventes techniques</strong> <br>
- <strong>Conseiller</strong> nos clients <br>
- Réaliser des <strong>maquettes</strong> (POC) <br>
- Faire de la <strong>veille technologique</strong></p>
<p><em><strong>Et les technos dans tout cela ? Les voici !</strong></em> <br>
<strong>Socle Linux</strong> : <br>
Infrastructure : <strong>Red Hat / CentOs, Debian</strong> <br>
Virtualisation/conteneurisation : <strong>Proxmox, Docker</strong></p>
<p><strong>Vision du SI</strong> : <br>
Supervision : <strong>Icinga, Zabbix, Centreon</strong> <br>
Centralisation de logs : ELK</p>
<p><strong>Industrialisation</strong> : <br>
Config management : <strong>Ansible, Puppet</strong> <br>
Provisioning : <strong>Foreman, Vagrant, Terraform</strong> <br>
Intégration continue : <strong>Jenkins</strong></p>
<p><strong>Solutions Collaboratives</strong> : <strong>Zimbra, Git, Samba, Owncloud</strong></p>
<p><em><strong>Votre profil</strong> (mais on vous aimera aussi de face…)</em><br>
Issu d’une formation en informatique (min BAC +2/3), vous avez déjà une expérience de 3 à 5 ans en tant qu’administrateur / ingénieur systèmes avec une forte orientation Open Source. <br>
Au-delà de votre formation et de votre expérience, <strong>ce qui nous plaira le plus chez vous… c’est vous !</strong><br>
Vous êtes passionné par le domaine du Libre, un brin communicant(e), vous avez le sens du service et surtout vous aimez les frites, la raclette et les jeux de société ?! Alors nous sommes faits pour nous entendre ! <br>
Vous souhaitez en savoir plus ou vous voulez candidater ? Envoyez un mail recrutement[at]capensis.fr ou venez faire un tour sur la page carrière sur notre site web capensis[dot]fr. </p>
<p><em><strong>Poste :</strong></em><br>
En CDI<br>
Rémunération 30/45K€ annuel sur 12 mois (selon profil) hors avantages<br>
Temps plein : 37h hebdo + RTT<br>
Recrutement urgent</p>
<p><strong>On vous attend !</strong> ;-)</p>
<div><a href="https://linuxfr.org/forums/general-petites-annonces/posts/cdi-admins-inges-sys-linux-confirmes-capensis-lille-h-f.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/123287/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/general-petites-annonces/posts/cdi-admins-inges-sys-linux-confirmes-capensis-lille-h-f#comments">ouvrir dans le navigateur</a>
</p>
CapenRechttps://linuxfr.org/nodes/123287/comments.atomtag:linuxfr.org,2005:Bookmark/3352018-11-13T15:31:20+01:002018-11-13T15:31:20+01:00Service discovery avec Netbox et Prometheus<a href="https://enix.io/fr/blog/service-discovery-avec-netbox-et-prometheus/">https://enix.io/fr/blog/service-discovery-avec-netbox-et-prometheus/</a> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/115718/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/naps/liens/service-discovery-avec-netbox-et-prometheus#comments">ouvrir dans le navigateur</a>
</p>
Antoine https://linuxfr.org/nodes/115718/comments.atomtag:linuxfr.org,2005:Post/395072018-09-19T22:03:41+02:002018-10-07T18:09:00+02:00Petit partage - Conky pour logs apache2, DNSChef, OpenVPN, HaProxy<p>Source de l'article (workflow) : <a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=99&t=817">Conky - Display logs files</a></p>
<p><em>Après avoir parcourus les tréfonds du Regex, avoir emboîté les briques du puzzle ancestrale du grand dieu Sed; notre héro au grand Shell vient nous partager ses créations infernales de la semaine.<br>
D'autres skins à venir, plus que probablement.<br>
Bon amusement !</em> 😉</p>
<h2 id="toc-les-conkys">Les Conkys</h2>
<h3 id="toc-conky-pour-afficher-les-logs-dapache2">Conky pour afficher les Logs d'Apache2</h3>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f617061636865322f426c61636b2f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f617061636865322d426c61636b2e706e67/Screenshot_2018-09-19__conky_logs_apache2-Black.png" alt="Screenshot_2018-09-19__conky_logs_apache2-Black" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_apache2/Black/Screenshot_2018-09-19__conky_logs_apache2-Black.png"></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f617061636865322f42656967652f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f617061636865322d42656967652e706e67/Screenshot_2018-09-19__conky_logs_apache2-Beige.png" alt="Screenshot_2018-09-19__conky_logs_apache2-Beige" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_apache2/Beige/Screenshot_2018-09-19__conky_logs_apache2-Beige.png"></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f617061636865322f57686974652f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f617061636865322d57686974652e706e67/Screenshot_2018-09-19__conky_logs_apache2-White.png" alt="Screenshot_2018-09-19__conky_logs_apache2-White" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_apache2/White/Screenshot_2018-09-19__conky_logs_apache2-White.png"></p>
<p>Source Code : <a href="https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_apache2">https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_apache2</a><br>
Ce conky affiche les 15 dernières lignes d'un fichier log apache2 (par défaut <em>/tmp/remote_logs/access.log</em>) avec colorisation des différents éléments.<br>
Il affiche un petit /!\ lorsqu'un code http d'erreur est repéré. Le conky est aussi capable de détecter certains bot voir d'en reconnaître (entre autre actuellement Google, Yahoo et Qwant *1)</p>
<p>*1 j'ai voulu ajouter le bot de linuxfr, mais j'attends que son user agent soit bien établi/pérenne.</p>
<h3 id="toc-conky-pour-afficher-les-logs-de-dnschef">Conky pour afficher les Logs de DNSChef</h3>
<p>Source Code : <a href="https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_dnschef">https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_dnschef</a><br>
Ce conky affiche les 15 dernières lignes d'un fichier log de DNSChef (par défaut <em>/tmp/remote_logs/dnschef.log</em>) avec colorisation des différents éléments.<br>
Ce conky est beaucoup plus simple que son frangin ci-haut, dnschef ne transmettant en effet pas énormément d'informations dans ses logs.<br>
Petit rappel : par défaut dnschef ne log rien, il faut ajouter l'option à la commande de lancement pour qu'il log les infos. N'oubliez surtout pas de configurer <a href="https://www.digitalocean.com/community/tutorials/how-to-manage-logfiles-with-logrotate-on-ubuntu-16-04">logrotate</a> car ses logs grossissent très très vite.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f646e73636865662f53637265656e73686f745f323031382d30392d31375f636f6e6b792d646973706c61795f72656d6f74655f444e53436865665f6c6f67732e676966/Screenshot_2018-09-17_conky-display_remote_DNSChef_logs.gif" alt="Screenshot_2018-09-17_conky-display_remote_DNSChef_logs" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_dnschef/Screenshot_2018-09-17_conky-display_remote_DNSChef_logs.gif"></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f646e73636865662f73656d692d426c61636b2f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f646e73636865662d73656d692d426c61636b2e6a7067/Screenshot_2018-09-19__conky_logs_dnschef-semi-Black.jpg" alt="Screenshot_2018-09-19__conky_logs_dnschef-semi-Black" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_dnschef/semi-Black/Screenshot_2018-09-19__conky_logs_dnschef-semi-Black.jpg"></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f646e73636865662f4f72616e67652f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f646e73636865662d4f72616e67652e6a7067/Screenshot_2018-09-19__conky_logs_dnschef-Orange.jpg" alt="Screenshot_2018-09-19__conky_logs_dnschef-Orange" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_dnschef/Orange/Screenshot_2018-09-19__conky_logs_dnschef-Orange.jpg"></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f646e73636865662f536b656c65746f6e2f53637265656e73686f745f323031382d30392d31395f5f636f6e6b795f6c6f67735f646e73636865662d536b656c65746f6e2e6a7067/Screenshot_2018-09-19__conky_logs_dnschef-Skeleton.jpg" alt="Screenshot_2018-09-19__conky_logs_dnschef-Skeleton" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_dnschef/Skeleton/Screenshot_2018-09-19__conky_logs_dnschef-Skeleton.jpg"></p>
<h3 id="toc-conky-pour-afficher-les-logs-de-haproxy">Conky pour afficher les Logs de HaProxy</h3>
<p>Source Code : <a href="https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_haproxy">https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_haproxy</a></p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6769746c61622e636f6d2f766f7864656d6f6e69782f636f6e6b792f7261772f6d61737465722f636f6e6b795f6c6f67735f686170726f78792f42656967652f53637265656e73686f745f323031382d31302d30375f436f6e6b792d4c6f67732d486150726f78792d42656967652e706e67/Screenshot_2018-10-07_Conky-Logs-HaProxy-Beige.png" alt="Screenshot_2018-10-07_Conky-Logs-HaProxy-Beige" title="Source : https://gitlab.com/voxdemonix/conky/raw/master/conky_logs_haproxy/Beige/Screenshot_2018-10-07_Conky-Logs-HaProxy-Beige.png"></p>
<h3 id="toc-conky-pour-afficher-les-logs-de-openvpn">Conky pour afficher les Logs de OpenVPN</h3>
<p>Source Code : <a href="https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_openvpn">https://gitlab.com/voxdemonix/conky/tree/master/conky_logs_openvpn</a></p>
<h3 id="toc-exporter-vos-derniers-logs-depuis-votre-serveur-">Exporter vos derniers logs depuis votre serveur :</h3>
<p><strong>Sur votre serveur où sont situés vos logs, générez des clés SSH.</strong></p>
<pre><code>( ssh-keygen -t ed25519 -o -a 666 ; ssh-keygen -t rsa -b 4096 -o -a 666 )
</code></pre>
<p><strong>Exportez votre clé publique depuis votre serveur où sont vos logs vers votre ordi perso.</strong></p>
<pre><code>ssh-copy-id -i ~/.ssh/id_ed25519.pub your_desktop_user@your_desktop_hostname_in_vpn
</code></pre>
<p><strong>Téléchargez <a href="https://gitlab.com/voxdemonix/divers-script/blob/master/exportLog_scp.bash">ce script</a>, rangez le où vous souhaitez et accordez dessus la permission d’exécution.</strong></p>
<pre><code>cd /opt/scripts
wget https://gitlab.com/voxdemonix/divers-script/raw/master/exportLog_scp.bash
chmod +x ./exportLog_scp.bash
</code></pre>
<p><strong>Éditez cron.</strong></p>
<pre><code>sudo crontab -e
</code></pre>
<p><strong>Choisissez votre taux de rafraîchissement favoris.</strong><br>
Note : le script copie les données dans un fichier dans /tmp/ avant de l'envoyer au desktop. Je vous conseil de passer par un dossier en mémoire ram (<a href="https://askubuntu.com/questions/173094/how-can-i-use-ram-storage-for-the-tmp-directory-and-how-to-set-a-maximum-amount">par exemple</a>).</p>
<pre><code> # each minute
* * * * * /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log
# each 15s ( use only on ram storage )
* * * * * /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log
* * * * * ( sleep 15 ; /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log )
* * * * * ( sleep 30 ; /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log )
* * * * * ( sleep 45 ; /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log )
# each 30s ( use only on ram storage )
* * * * * ( /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log ; sleep 30 ; /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log )
# each hour
@hourly ( /opt/scripts/exportLog_scp.bash myOwnDesktop.vpn your_desktop_user /var/log/dnschef/ dnschef.log )
</code></pre>
<h3 id="toc-farm-link">Farm Link</h3>
<ul>
<li><a href="https://www.0rion.netlib.re/forum4/viewtopic.php?f=99&t=818">(quelques) regex pour conky</a></li>
</ul>
<p>N'hésitez pas à apporter votre pierre à l'édifice voir aussi partager le rendu que ça donne sur vos propres bureaux. 🙂 Si vous souhaitez que le conky colore quelque chose en plus, c'est le bon moment pour demander :)</p>
<div><a href="https://linuxfr.org/forums/linux-debian-ubuntu/posts/petit-partage-conky-pour-logs-apache2-dnschef-openvpn-haproxy.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/115328/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/linux-debian-ubuntu/posts/petit-partage-conky-pour-logs-apache2-dnschef-openvpn-haproxy#comments">ouvrir dans le navigateur</a>
</p>
voxdemonixhttps://linuxfr.org/nodes/115328/comments.atomtag:linuxfr.org,2005:Bookmark/232018-03-23T17:09:12+01:002018-03-23T17:09:12+01:00My Philosophy on Alerting -- Rob Ewaschuk<a href="https://docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q/preview">https://docs.google.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q/preview</a> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/114054/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/anonyme/liens/my-philosophy-on-alerting-rob-ewaschuk#comments">ouvrir dans le navigateur</a>
</p>
Anonymehttps://linuxfr.org/nodes/114054/comments.atomtag:linuxfr.org,2005:News/383592018-01-31T10:43:27+01:002018-02-24T12:02:52+01:00Découverte de l’outil de supervision PrometheusLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Par le passé, j’ai été un grand utilisateur de Nagios et ses différents <em>forks</em>. J’avais pour habitude de le coupler avec un PNP4Nagios pour obtenir de jolies courbes sur les métriques remontées par mes greffons de surveillance. J’ai également commencé à utiliser l’outil <a href="https://www.elastic.co/fr/products/beats">Beats</a> d’Elastic.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f70726f6d6574686575732e696f2f6173736574732f70726f6d6574686575735f6c6f676f5f677265792e737667/prometheus_logo_grey.svg" alt="Prometheus" title="Source : https://prometheus.io/assets/prometheus_logo_grey.svg"></p>
<p>Pour diverses raisons, j’ai arrêté d’utiliser ces outils, pour passer sur une <em>stack</em> très différente basée sur Prometheus et Grafana.</p></div><ul><li>lien nᵒ 1 : <a title="https://fr.slideshare.net/FabianReinartz/prometheus-storage-57557499" hreflang="en" href="https://linuxfr.org/redirect/101214">Time series in Prometheus (SlideShare.net)</a></li><li>lien nᵒ 2 : <a title="https://prometheus.io" hreflang="en" href="https://linuxfr.org/redirect/101274">Projet Prometheus</a></li><li>lien nᵒ 3 : <a title="https://prometheus.io/download/" hreflang="en" href="https://linuxfr.org/redirect/101275">Téléchargement de Prometheus</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#un-peu-de-contexte">Un peu de contexte</a></li>
<li>
<a href="#d%C3%A9couverte-de-prometheus-principe-de-fonctionnement">Découverte de Prometheus : principe de fonctionnement</a><ul>
<li>
<a href="#principe-de-fonctionnement-du-stockage-prometheus">Principe de fonctionnement du stockage Prometheus</a><ul>
<li><a href="#pr%C3%A9sentation-des-donn%C3%A9es-%C3%A0-stocker">Présentation des données à stocker</a></li>
<li><a href="#stockage-par-double-delta">Stockage par double delta</a></li>
<li><a href="#pour-aller-plus-loin">Pour aller plus loin</a></li>
</ul>
</li>
</ul>
</li>
<li>
<a href="#prometheus-server">Prometheus server</a><ul>
<li><a href="#installation-du-serveur-prometheus">Installation du serveur Prometheus</a></li>
<li><a href="#configuration-du-serveur-prometheus">Configuration du serveur Prometheus</a></li>
</ul>
</li>
<li>
<a href="#jobs-exporter">Jobs exporter</a><ul>
<li><a href="#installation-dun-node-exporter">Installation d'un node exporter</a></li>
<li><a href="#installation-dun-nodeexporter">Installation d’un node exporter</a></li>
<li><a href="#configuration-de-prometheus">Configuration de Prometheus</a></li>
</ul>
</li>
<li>
<a href="#web-ui-d%C3%A9couverte-de-grafana">Web UI : découverte de Grafana</a><ul>
<li><a href="#installation-de-grafana">Installation de Grafana</a></li>
<li><a href="#interfa%C3%A7age-avec-prometheus">Interfaçage avec Prometheus</a></li>
<li><a href="#ajout-dun-dashboard">Ajout d’un dashboard</a></li>
</ul>
</li>
<li><a href="#d%C3%A9finition-dalertes">Définition d’alertes</a></li>
<li>
<a href="#alertmanager">Alertmanager</a><ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#configuration-du-gestionnaire-dalertes">Configuration du gestionnaire d’alertes</a></li>
<li><a href="#branchement-sur-prometheus">Branchement sur Prometheus</a></li>
</ul>
</li>
<li><a href="#pour-conclure">Pour conclure</a></li>
</ul><h2 id="un-peu-de-contexte">Un peu de contexte</h2>
<p>Pour diverses raisons, j’ai eu de nouveau à gérer la mise en place d’une surveillance pour des plates‐formes d’intégration ainsi que pour une plate‐forme servant principalement à faire du <em>benchmark</em>. Là encore, j’aurais pu ressortir mes scripts de suivi sous Nagios couplé à PNP4Nagios, me tourner vers un Cacti ou encore me mettre à Zabbix. Un autre candidat intéressant était la suite Beats d’Elastic.</p>
<p>Sauf que tous ces outils ne m’emballaient pas et avaient tous un défaut :</p>
<ul>
<li>Nagios, PNP4Nagios et Cacti étaient clairement vieillots (avec ça, je vais me faire des amis) ;</li>
<li>je ne connaissais pas Zabbix mais je n’avais pas envie de m’y mettre (même si l’on m’en avait dit du bien) ;</li>
<li>Enfin, même si Beats d’Elastic est relativement intéressant, j’ai de plus en plus tendance à trouver Elasticsearch lourdaud et grand consommateur de ressource (grâce notamment à la légèreté de Java).</li>
</ul><p>Bref, je trouvais que ces outils restaient en deçà de ce qu’on pourrait attendre d’une <em>stack</em> de supervision moderne. Autre point relativement contraignant : une intégration toujours complexe à réaliser alors que la tendance est plutôt vers des outils de moins en moins intrusifs (je suis un grand consommateur d’Ansible pour cette raison).</p>
<p>C’est donc dans cet état d’esprit que je m’apprêtais à mettre en place Beats d’Elasticsearch. Un peu par hasard, j’ai entendu parler de Prometheus et devant l’enthousiasme de la personne qui m’en parlait, j’ai décidé d’y jeter un coup d’œil.</p>
<h2 id="découverte-de-prometheus-principe-de-fonctionnement">Découverte de Prometheus : principe de fonctionnement</h2>
<p>Avant de passer à la mise en place de Prometheus, attardons‐nous sur l’architecture de ce logiciel :<br><img src="//img.linuxfr.org/img/68747470733a2f2f70726f6d6574686575732e696f2f6173736574732f6172636869746563747572652e737667/architecture.svg" alt="https://prometheus.io/assets/architecture.svg" title="Source : https://prometheus.io/assets/architecture.svg"></p>
<p>Dans les éléments qui vont particulièrement nous intéresser, nous retiendrons les briques suivantes :</p>
<ul>
<li>
<strong>Prometheus server</strong> : c’est le moteur permettant de stocker les métriques collectées ;</li>
<li>
<strong>Jobs exporters</strong> : il s’agit d’agents sur lesquels Prometheus viendra collecter les différentes métriques ;</li>
<li>
<strong>Web UI</strong> : restitution des métriques à l’utilisateur ;</li>
<li>
<strong>Alertmanager</strong> : gestionnaire d’envoi des alertes aux utilisateurs.</li>
</ul><h3 id="principe-de-fonctionnement-du-stockage-prometheus">Principe de fonctionnement du stockage Prometheus</h3>
<p>Prometheus utilise un stockage spécifique pour ses métriques. De ce stockage découlent les atouts et inconvénients de ce moteur. Avant la version 2, il existait trois formats v0, v1 et v2 (ce n’est plus le cas depuis la version 2). Dans la suite, nous reviendrons sur cette évolution et en quoi elle permet d’en retirer des avantages.</p>
<p>Au niveau de ce stockage, certains aspects ne seront pas abordés comme, par exemple, la structure des tampons utilisés ou l’écriture sur disque. Si vous voulez une description un peu plus poussée, vous pouvez vous tourner vers la présentation de Fabian Reinartz : <a href="https://fr.slideshare.net/FabianReinartz/prometheus-storage-57557499"><em>Time Series in Prometheus</em></a> (sur <em>Slideshare.net</em>).</p>
<p>Le format de cette base de données est spécifique (<a href="https://fr.wikipedia.org/wiki/S%C3%A9rie_temporelle">série temporelle</a> ou <a href="https://en.wikipedia.org/wiki/Time_series"><em>time series</em></a> dans la langue de Shakespeare) et diffère de celui qu’on pourrait retrouver dans une base de données classique (SQL ou NoSQL). En effet, les données collectées ont des caractéristiques connues :</p>
<ul>
<li>collecte de métrique à intervalle connu (toutes les 60 secondes) ;</li>
<li>similarité des données d’une collecte sur l’autre (généralement, l’espace disque des partitions sur un serveur ne change pas).</li>
</ul><p>Du fait de ces caractéristiques, Prometheus compresse les données en mémoire et sur disque. Il en résulte une bien meilleure utilisation des ressources mémoire, processeur et disque.</p>
<h4 id="présentation-des-données-à-stocker">Présentation des données à stocker</h4>
<p>Chaque collecte de métrique ramènera un groupe de métriques. Ces métriques seront toutes associées à une date stockée sous la forme d’un entier représentant le nombre de millisecondes écoulées depuis le 1<sup>er</sup> janvier 1970. Chaque métrique sera représentée sous la forme d’un chiffre à virgule flottante de type <code>float64</code>.</p>
<p>Ci‐dessous un exemple de valeurs que nous allons stocker dans le moteur Prometheus :</p>
<table>
<thead><tr>
<th> <strong>Métrique</strong> </th>
<th> <strong>Horodatage</strong> </th>
<th><strong>Valeur</strong></th>
</tr></thead>
<tbody>
<tr>
<td>http_requests_total</td>
<td> 1434317560938</td>
<td>1500</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> 1434317562939</td>
<td>1520</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> 1434317564939</td>
<td>1531</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> 1434317566945</td>
<td>1554</td>
</tr>
</tbody>
</table><h4 id="stockage-par-double-delta">Stockage par double delta</h4>
<p>Comme on peut le voir, les données ont comme caractéristiques d’être collectées à intervalles réguliers (ici, environ toutes les deux secondes) et d’avoir des valeurs proches d’une collecte à une autre. Afin de réduire la place prise par les données, il est possible de ne stocker que le delta de ces mesures.</p>
<p>Ainsi, une première façon de réduire la place prise par ces données est de les stocker sous la forme d'un delta :</p>
<table>
<thead><tr>
<th><strong>Métrique</strong></th>
<th> <strong>Delta horodatage</strong> </th>
<th><strong>Valeur</strong></th>
</tr></thead>
<tbody>
<tr>
<td>http_requests_total </td>
<td> 1434317560938</td>
<td> 1500</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> +2001</td>
<td> +20</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> +2000</td>
<td> +22</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> +2006</td>
<td> +20</td>
</tr>
</tbody>
</table><p>Lors de la première mesure, l’horodatage consommera bien huit octets (un entier sur 64 bits). La donnée quant à elle consommera huit octets (Prometheus stocke toutes ses valeurs au format <code>float64</code>), soit 16 octets au total.</p>
<p>Dans le cas de l’horodatage, le delta pourra être stocké sous forme d’un entier de longueur variable fonction du delta avec la valeur précédente.</p>
<p>Pour le stockage de la métrique, le moteur fait appel à un <a href="https://fr.wikipedia.org/wiki/Fonction_OU_exclusif">ou exclusif</a> (opération <code>XOR</code>) pour comparer l’ancienne et la nouvelle valeur. En fonction de ce résultat, le moteur stockera une représentation compressée de la différence constatée. Si ça n’est pas possible, le moteur utilisera une valeur sur huit octets.</p>
<p>Mais en réalité, Prometheus fait appel à un stockage par double delta. Le principe est simple : pour la première mesure, il utilise un stockage brut, pour la seconde mesure, il fait la différence par rapport à la première mesure et toutes les autres mesures sont stockées par rapport au delta du delta de la valeur précédente. Ci‐dessous le stockage que nous obtenons avec le jeu de données :</p>
<table>
<thead><tr>
<th><strong>Métrique</strong></th>
<th><strong>Delta delta horodatage</strong></th>
<th> <strong>Valeur</strong>
</th>
</tr></thead>
<tbody>
<tr>
<td>http_requests_total</td>
<td> 1434317560938</td>
<td> 1500</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> +2001</td>
<td> +20</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> +-1</td>
<td> ++2</td>
</tr>
<tr>
<td>http_requests_total</td>
<td> ++6</td>
<td> +-2</td>
</tr>
</tbody>
</table><p>Sur une grande quantité de données, cet algorithme permet de réduire l’espace consommé pour arriver à une moyenne de l’ordre de 1,37 octet par échantillon de métrique (au lieu des 16 octets initiaux).</p>
<h4 id="pour-aller-plus-loin">Pour aller plus loin</h4>
<p>Cette technique de stockage par mots de longueurs variables est similaire à celle décrite dans un papier sur l’outil Gorilla (produit interne de FaceBook). Ci‐après, le lien vers le PDF de l’article en question : <a href="http://www.vldb.org/pvldb/vol8/p1816-teller.pdf">http://www.vldb.org/pvldb/vol8/p1816-teller.pdf</a>.</p>
<h2 id="prometheus-server">Prometheus server</h2>
<p>Ce processus a en charge la collecte à intervalles réguliers de l’état des différents <em>exporters</em>. Il stocke les métriques collectées dans sa base de données et peut ensuite être interrogé au travers de son API (via HTTP).<br>
Un autre rôle du serveur Prometheus est d’évaluer à intervalles réguliers les définitions d’alertes. Ces dernières s’appuient sur l’état des métriques internes collectées.</p>
<h3 id="installation-du-serveur-prometheus">Installation du serveur Prometheus</h3>
<p>Les inconditionnels de Docker pourront lancer l’installation à l’aide de la commande suivante :</p>
<pre><code>docker run -p 9090:9090 prom/prometheus
</code></pre>
<p>Pour les personnes ayant <s>toujours</s> recours à des machines système classiques, vous devrez récupérer l’archive de Prometheus à depuis le <a href="https://prometheus.io/download/">site Web du projet</a>. Vous aurez ensuite à :</p>
<ul>
<li>
<p>décompresser l’archive avec la commande suivante :</p>
<p><code>tar xfvz prometheus-2.0.0.linux-amd64.tar.gz</code></p>
</li>
<li>
<p>lancer Prometheus de la manière suivante :</p>
<p><code>./prometheus-2.0.0.linux-amd64/prometheus --config.file=prometheus-2.0.0.linux-amd64/prometheus.yml</code></p>
</li>
</ul><p>La console Prometheus est maintenant joignable à l’URL suivante : <code>http://localhost:9090</code>.</p>
<h3 id="configuration-du-serveur-prometheus">Configuration du serveur Prometheus</h3>
<p>Tel que vous l’avez lancé dans le précédent paragraphe, Prometheus sera configuré par défaut afin de scruter son propre état. Si vous souhaitez gérer sa configuration, vous aurez besoin d’alimenter un fichier au format <a href="https://fr.wikipedia.org/wiki/YAML" title="Définition Wikipédia">YAML</a>.</p>
<p>Si ce fichier est disponible à l’emplacement <code>~/prometheus.yml</code>, vous devrez relancer votre conteneur Docker avec la commande suivante :<br><code>docker run -p 9090:9090 -v ~/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus</code></p>
<p>Pour un lancement classique, la commande sera la suivante :<br><code>./prometheus-2.0.0.linux-amd64/prometheus --config.file=~/prometheus.yml</code></p>
<h2 id="jobs-exporter">Jobs exporter</h2>
<p>Autre élément important de l’architecture : les sources de données à collecter.</p>
<p>Pour cela, Prometheus offre des <em>exporters</em> prêts à l’emploi. Parmi ceux‐ci, le <em>node exporter</em> est particulièrement intéressant. Ce dernier se charge d’exporter énormément de métriques système, que ça soit pour des machines physiques ou virtuelles. On y retrouve indifféremment :</p>
<ul>
<li>les informations sur l’activité processeur (au processeur près) ;</li>
<li>la consommation de la ressource mémoire ;</li>
<li>l’activité des disques (% d’attente, nombre d’entrées‐sorties par seconde, nombre de mégaoctets par seconde en lecture et écriture) ;</li>
<li>l’activité des interfaces réseau ;</li>
<li>enfin, sur les machines physiques, des indications comme par exemple la température des processeurs.</li>
</ul><p>En réalité, il y a tellement de métriques à disposition (comme par exemple l’état de l’entropie du système) qu’il serait difficile de tout détailler.</p>
<p>À noter qu’il existe également des <em>exporters</em> pour certains produits connus du marché, comme par exemple <strong>HAProxy</strong>, <strong>Apache</strong> ou encore <strong>MySQL</strong>.</p>
<p>L’installation d’un <em>node exporter</em> se réalise en deux phases :</p>
<ul>
<li>décompression des binaires sur la machine à superviser et lancement de l’agent ;</li>
<li>déclaration au niveau du serveur Prometheus de l’instance à scruter.</li>
</ul><h3 id="installation-dun-node-exporter">Installation d'un node exporter</h3>
<h3 id="installation-dun-nodeexporter">Installation d’un node exporter</h3>
<p>L’installation est assez classique. Il faut tout d’abord récupérer l’archive de l’<em>exporter</em> sur <a href="https://prometheus.io/download/">https://prometheus.io/download/</a> [<a href="https://github.com/prometheus/node_exporter/releases/download/v0.15.2/node_exporter-0.15.2.linux-amd64.tar.gz"><em>lien direct</em></a>].</p>
<p>Décompresser ensuite l’archive avec la commande suivante :<br><code>tar xfvz node_exporter-0.15.2.linux-amd64.tar.gz</code></p>
<p>Le node se lance ensuite de la manière suivante :<br><code>./node_exporter-0.15.2.linux-amd64/node_exporter</code></p>
<h3 id="configuration-de-prometheus">Configuration de Prometheus</h3>
<p>Une fois que le <em>node exporter</em> est lancé, il est maintenant temps de l’indiquer à Prometheus. Afin que cet ajout soit le plus souple possible, ajouter la section suivante dans le fichier <code>prometheus.yml</code> (au niveau du champ <code>scrape_configs</code>) :</p>
<pre><code class="yaml"><span class="l l-Scalar l-Scalar-Plain">scrape_configs</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">job_name</span><span class="p p-Indicator">:</span> <span class="s">'node'</span>
<span class="l l-Scalar l-Scalar-Plain">file_sd_configs</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">files</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">[</span> <span class="s">"/etc/prometheus/nodes/*.yml"</span> <span class="p p-Indicator">]</span>
<span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span></code></pre>
<p>Créez le répertoire jobs :<br><code>mkdir -p /etc/prometheus/nodes</code></p>
<p>Avec cette directive, Prometheus sera en mesure de scruter le contenu du répertoire <strong>/etc/prometheus/nodes</strong> et d'ajouter automatiquement à sa configuration tous les fichiers <strong>.yml</strong> qui y seront déposés. Dans le cas présent, ajoutez le fichier <strong>/etc/prometheus/nodes/localhost.yml</strong> avec le contenu suivant :</p>
<pre><code class="yaml"><span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">targets</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">[</span> <span class="s">"localhost:9100"</span> <span class="p p-Indicator">]</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="c1"># Vous pouvez ajouter ce que vous voulez pour taguer la machine</span>
<span class="l l-Scalar l-Scalar-Plain">host</span><span class="p p-Indicator">:</span> <span class="s">"localhost"</span></code></pre>
<p>Dès la création du fichier, Prometheus charge ce fichier et commence sa collecte.</p>
<h2 id="web-ui-découverte-de-grafana">Web UI : découverte de Grafana</h2>
<p>Par défaut, Prometheus offre à l’utilisateur une interface de restitution. Mais cette dernière est assez rudimentaire (elle est surtout là pour de la mise au point). Les auteurs conseillent de s’appuyer sur l’interface Grafana qui est bien plus avancée de ce point de vue.</p>
<h3 id="installation-de-grafana">Installation de Grafana</h3>
<p>Grafana est disponible au téléchargement à l’emplacement suivant : <a href="https://grafana.com/grafana/download">https://grafana.com/grafana/download</a>.</p>
<p>Une fois Grafana téléchargé, l’installation se fait avec <code>yum</code> ou <code>dpkg</code>.</p>
<p>Ci‐dessous l’instruction pour Debian :</p>
<pre><code class="bash">wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_4.6.3_amd64.deb
sudo dpkg -i grafana_4.6.3_amd64.deb</code></pre>
<p>Et la même chose pour Red Hat ou CentOS :</p>
<pre><code class="bash">wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana-4.6.3-1.x86_64.rpm
sudo yum localinstall grafana-4.6.3-1.x86_64.rpm</code></pre>
<p>Il est également possible de récupérer une archive TAR compressée avec GZIP seule. En effet, comme Prometheus, Grafana est écrit en Go et, par conséquence, n’a pas de dépendance au niveau système.</p>
<p>Une fois installé, il faut démarrer la console avec la commande suivante :<br><code>systemctl start grafana</code></p>
<p>L’utilisateur peut maintenant se connecter sur l’adresse URL de Grafana : <code>http://localhost:3000</code></p>
<p>Si vous souhaitez activer Grafana au démarrage, lancez la commande suivante :<br><code>systemctl enable grafana</code></p>
<h3 id="interfaçage-avec-prometheus">Interfaçage avec Prometheus</h3>
<p>Une fois sur l’interface de Grafana, authentifiez‐vous en tant qu’administrateur (compte <em>admin</em>, mot de passe <em>admin</em>).</p>
<p>Seconde étape : la configuration d’une source de données. Au niveau des champs, vous pourrez rentrer les valeurs suivantes :</p>
<ul>
<li>Name : nom de la connexion (ex : Prometheus) ;</li>
<li>Type : choisir Prometheus ;</li>
<li>URL : rentrer <code>http://localhost:9090</code> ;</li>
<li>Access : laisser la valeur <em>proxy</em>.</li>
</ul><p>Laissez les autres champs à la valeur par défaut et cliquez sur <em>Add</em>.</p>
<h3 id="ajout-dun-dashboard">Ajout d’un dashboard</h3>
<p>La source de données est maintenant configurée. En revanche, il n’y a aucun tableau de bord. La bonne nouvelle est que vous en avez de nombreux disponibles prêts à l’emploi à l’adresse suivante : <a href="https://grafana.com/dashboards">https://grafana.com/dashboards</a>.</p>
<p>Parmi ces tableaux de bords, <strong>Node Exporter Full</strong> permet de récupérer toutes les métriques remontées par les <em>nodes exporter</em> de Prometheus. Il est consultable à l’adresse suivante : <a href="https://grafana.com/dashboards/1860">https://grafana.com/dashboards/1860</a>.</p>
<p>L’installation est réalisée par l’écran d’importation de Grafana en saisissant l’identifiant du <em>dashboard</em> (ici 1860). En cas de problème d’ouverture de flux (avec un serveur mandataire), il est possible de télécharger le <em>dashboard</em> au format <a href="https://fr.wikipedia.org/wiki/JSON" title="Définition Wikipédia">JSON</a>, pour ensuite le téléverser sur via interface de Grafana.</p>
<p>Une fois le <em>dashboard</em> créé, vous devriez obtenir les graphiques suivants :<br><img src="//img.linuxfr.org/img/68747470733a2f2f67726166616e612e636f6d2f6170692f64617368626f617264732f313836302f696d616765732f313732372f696d616765/image" alt="Capture d’écran du dashboard" title="Source : https://grafana.com/api/dashboards/1860/images/1727/image"></p>
<h2 id="définition-dalertes">Définition d’alertes</h2>
<p>Tout est en place pour la collecte et la restitution des données. Il faut maintenant définir des alertes afin de les remonter auprès des différents opérateurs. Première chose, il faut modifier la configuration de Prometheus afin de lui faire charger des règles permettant de générer des alertes. Ci‐dessous la déclaration à rattacher au niveau du champ <code>global</code> :</p>
<pre><code class="yaml"><span class="c1"># Load rules once and periodically evaluate them according to the global 'evaluation_interval'.</span>
<span class="l l-Scalar l-Scalar-Plain">rule_files</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">/etc/prometheus/rules/node.rules.yml</span></code></pre>
<p>Créez également le fichier <code>/etc/prometheus/rules/node.rules.yml</code> en y mettant les éléments suivants :</p>
<ul>
<li>une variable <code>groups</code> avec une liste de règles ;</li>
<li>pour chaque règle les champs <code>name</code> et <code>rules</code> ;</li>
<li>pour chaque enregistrement de rules, la définition d’une alerte.</li>
</ul><p>Une alerte pourra faire appel à différents champs. Parmi ces derniers, vous pouvez retenir ceux‐ci :</p>
<ul>
<li>le champ <code>alert</code>, avec le nom de cette dernière ;</li>
<li>le champ <code>expr</code>, avec une requête permettant de déclencher l’alerte ;</li>
<li>le champ <code>for</code>, pour indiquer au bout de combien de temps vous considérez que l’alerte est caractérisée ;</li>
<li>enfin, les champs <code>labels</code> et <code>annotations</code> peuvent apporter des informations supplémentaires sur l’alerte (nom du système de fichiers, nom du serveur, petite phrase pour donner une procédure permettant de rétablir le service, etc.).</li>
</ul><p>Ci‐dessous quelques exemples d’alertes pour une surveillance des machines :</p>
<pre><code class="yaml"><span class="l l-Scalar l-Scalar-Plain">groups</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">name</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">Alerts nodes</span>
<span class="l l-Scalar l-Scalar-Plain">rules</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">alert</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">DiskWillFillIn4Hours</span>
<span class="l l-Scalar l-Scalar-Plain">expr</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">predict_linear(node_filesystem_free{job="node"}[1h], 4 * 3600) < 0</span>
<span class="l l-Scalar l-Scalar-Plain">for</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">5m</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">severity</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">critical</span>
<span class="l l-Scalar l-Scalar-Plain">annotations</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span> <span class="s">'{{</span><span class="nv"> </span><span class="s">$labels.mountpoint</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">almost</span><span class="nv"> </span><span class="s">full</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}:</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$value</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">humanize</span><span class="nv"> </span><span class="s">}}%'</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">alert</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">NoDiskSpace</span>
<span class="l l-Scalar l-Scalar-Plain">expr</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">node_filesystem_avail{fstype=~"(ext.|xfs)",job="node"} / node_filesystem_size{fstype=~"(ext.|xfs)",job="node"} * 100 <= 1</span>
<span class="l l-Scalar l-Scalar-Plain">for</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">15m</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">severity</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">critical</span>
<span class="l l-Scalar l-Scalar-Plain">annotations</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">description</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">There's only 1% disk space left on host {{ $labels.instance }}</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span> <span class="s">'No</span><span class="nv"> </span><span class="s">disk</span><span class="nv"> </span><span class="s">space</span><span class="nv"> </span><span class="s">left</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.mountpoint</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}:</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$value</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">humanize</span><span class="nv"> </span><span class="s">}}%'</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">alert</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">HighInodeUsage</span>
<span class="l l-Scalar l-Scalar-Plain">expr</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">node_filesystem_files_free{fstype=~"(ext.|xfs)",job="node"} / node_filesystem_files{fstype=~"(ext.|xfs)",job="node"} * 100 <= 20</span>
<span class="l l-Scalar l-Scalar-Plain">for</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">15m</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">severity</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">critical</span>
<span class="l l-Scalar l-Scalar-Plain">annotations</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">description</span><span class="p p-Indicator">:</span> <span class="s">'{{</span><span class="nv"> </span><span class="s">$labels.mountpoint</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">inodes</span><span class="nv"> </span><span class="s">are</span><span class="nv"> </span><span class="s">running</span><span class="nv"> </span><span class="s">low.</span><span class="nv"> </span><span class="s">Please</span><span class="nv"> </span><span class="s">consider</span><span class="nv"> </span><span class="s">removing</span><span class="nv"> </span><span class="s">file.'</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span> <span class="s">'Free</span><span class="nv"> </span><span class="s">inodes</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">mountpoint</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.mountpoint</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">at</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$value</span><span class="nv"> </span><span class="s">|</span><span class="nv"> </span><span class="s">printf</span><span class="nv"> </span><span class="s">"%.2f"</span><span class="nv"> </span><span class="s">}}%'</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">alert</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">ExtremelyHighCPU</span>
<span class="l l-Scalar l-Scalar-Plain">expr</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">instance:node_cpu_in_use:ratio > 0.95</span>
<span class="l l-Scalar l-Scalar-Plain">for</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">2h</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">severity</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">critical</span>
<span class="l l-Scalar l-Scalar-Plain">annotations</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">description</span><span class="p p-Indicator">:</span> <span class="s">'CPU</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">percent</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">extremely</span><span class="nv"> </span><span class="s">high</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">past</span><span class="nv"> </span><span class="s">2</span><span class="nv"> </span><span class="s">hours.'</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span> <span class="s">'CPU</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">percent</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">extremely</span><span class="nv"> </span><span class="s">high</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">past</span><span class="nv"> </span><span class="s">2</span><span class="nv"> </span><span class="s">hours.'</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">alert</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">HighCPU</span>
<span class="l l-Scalar l-Scalar-Plain">expr</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">instance:node_cpu_in_use:ratio > 0.8</span>
<span class="l l-Scalar l-Scalar-Plain">for</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">2h</span>
<span class="l l-Scalar l-Scalar-Plain">labels</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">severity</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">critical</span>
<span class="l l-Scalar l-Scalar-Plain">annotations</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">description</span><span class="p p-Indicator">:</span> <span class="s">'CPU</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">percent</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">extremely</span><span class="nv"> </span><span class="s">high</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">past</span><span class="nv"> </span><span class="s">2</span><span class="nv"> </span><span class="s">hours.'</span>
<span class="l l-Scalar l-Scalar-Plain">title</span><span class="p p-Indicator">:</span> <span class="s">'CPU</span><span class="nv"> </span><span class="s">use</span><span class="nv"> </span><span class="s">percent</span><span class="nv"> </span><span class="s">is</span><span class="nv"> </span><span class="s">high</span><span class="nv"> </span><span class="s">on</span><span class="nv"> </span><span class="s">{{</span><span class="nv"> </span><span class="s">$labels.instance</span><span class="nv"> </span><span class="s">}}</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">the</span><span class="nv"> </span><span class="s">past</span><span class="nv"> </span><span class="s">2</span><span class="nv"> </span><span class="s">hours.'</span></code></pre>
<p>En se rendant dans la console de Prometheus sur le lien <em>Alerts</em>, vous obtiendrez toutes les alertes définies et la liste des <em>exporters</em> en erreur.<br><img src="//img.linuxfr.org/img/68747470733a2f2f636f72656f732e636f6d2f73697465732f64656661756c742f66696c65732f696e6c696e652d696d616765732f70726f6d6574686575732d657463642d30332e706e67/prometheus-etcd-03.png" alt="Exemple d’alerte dans la console Prometheus" title="Source : https://coreos.com/sites/default/files/inline-images/prometheus-etcd-03.png"></p>
<h2 id="alertmanager">Alertmanager</h2>
<p>Ce processus aura en charge de restituer auprès des équipes en charge des serveurs l’arrivée de nouveaux événements.</p>
<h3 id="installation">Installation</h3>
<p>Tout comme pour la partie serveur de Prometheus, vous pouvez démarrer le gestionnaire d’alertes avec la commande :<br><code>docker run -p 9093:9093 prom/alertmanager</code></p>
<p>Pour les autres, vous allez devoir :</p>
<ul>
<li>
<p>récupérer l’archive d’alertmanager (actuellement en version 0.13.0) :</p>
<p><code>wget https://github.com/prometheus/alertmanager/releases/download/v0.13.0/alertmanager-0.13.0.linux-amd64.tar.gz</code></p>
</li>
<li>
<p>décompressez‐la avec la commande suivante :</p>
<p><code>tar xfvz alertmanager-0.13.0.linux-amd64.tar.gz</code></p>
</li>
<li>
<p>enfin, le lancement du gestionnaire d'alerte se fait avec les commandes suivantes :</p>
<p><code>cd ./alertmanager-0.13.0.linux-amd64 ./alertmanager --config.file=simple.yml</code></p>
</li>
</ul><p>Le fichier <code>simple.yml</code> est un exemple de configuration.</p>
<h3 id="configuration-du-gestionnaire-dalertes">Configuration du gestionnaire d’alertes</h3>
<p>Le gestionnaire d’alertes est très ouvert au niveau de ses capacités de communication. Vous pouvez envoyer des courriels ou des messages vers Slack pour notifier l’arrivée de nouvelles alertes.</p>
<p>Ci‐dessous un exemple de configuration mettant en place l’envoi des notifications vers Slack :</p>
<pre><code class="yaml"><span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span>
<span class="c1"># The root route on which each incoming alert enters.</span>
<span class="l l-Scalar l-Scalar-Plain">route</span><span class="p p-Indicator">:</span>
<span class="c1"># On envoie tout vers slack par défaut</span>
<span class="l l-Scalar l-Scalar-Plain">receiver</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">slack</span>
<span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span>
<span class="l l-Scalar l-Scalar-Plain">receivers</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">name</span><span class="p p-Indicator">:</span> <span class="s">'slack'</span>
<span class="l l-Scalar l-Scalar-Plain">slack_configs</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">api_url</span><span class="p p-Indicator">:</span> <span class="s">"https://hooks.slack.com/services/xxx/xxx/xxxxxx"</span>
<span class="l l-Scalar l-Scalar-Plain">channel</span><span class="p p-Indicator">:</span> <span class="s">'#prometheus'</span>
<span class="p p-Indicator">[</span><span class="nv">...</span><span class="p p-Indicator">]</span></code></pre>
<p>Dès que Prometheus envoie une alerte, cette dernière est poussée vers Slack sur le canal <code>#prometheus</code> afin d’être prise en compte par les différentes équipes.</p>
<h3 id="branchement-sur-prometheus">Branchement sur Prometheus</h3>
<p>Dernier point : brancher le serveur Prometheus sur le gestionnaire d’alertes avec la configuration suivante à ajouter dans le fichier <code>prometheus.yml</code> :</p>
<pre><code class="yaml"><span class="c1"># Alertmanager configuration</span>
<span class="l l-Scalar l-Scalar-Plain">alerting</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">alertmanagers</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">static_configs</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">targets</span><span class="p p-Indicator">:</span>
<span class="c1"># À adapter en fonction du serveur gestionnaire d’alertes</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">localhost:9093</span></code></pre>
<p>Un redémarrage du serveur sera nécessaire pour la prise en compte. Ceci fait, les alertes devraient commencer à arriver sur le canal de communication.</p>
<h2 id="pour-conclure">Pour conclure</h2>
<p>Le tour du propriétaire est maintenant terminé. À vous de jouer !</p></div><div><a href="https://linuxfr.org/news/decouverte-de-l-outil-de-supervision-prometheus.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/113419/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/decouverte-de-l-outil-de-supervision-prometheus#comments">ouvrir dans le navigateur</a>
</p>
yannigDavy DefaudBAudBenoît Sibaudpalm123NÿcoZeroHeureNicolas CasanovaC138dovikhttps://linuxfr.org/nodes/113419/comments.atomtag:linuxfr.org,2005:News/377972017-01-21T23:21:28+01:002017-02-03T12:57:13+01:00Les nouveautés de Glances 2.8 Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Au moment de la lecture de cette dépêche, Glances 2.8 sera disponible à l’installation depuis <a href="https://pypi.python.org/pypi/Glances">Pypi</a>. Nous allons donc faire le tour complet du propriétaire en mettant l’accent sur les nouveautés importantes de cette version.</p></div><ul><li>lien nᵒ 1 : <a title="https://nicolargo.github.io/glances/" hreflang="en" href="https://linuxfr.org/redirect/99145">Site officiel de Glances</a></li><li>lien nᵒ 2 : <a title="https://github.com/nicolargo/glances" hreflang="en" href="https://linuxfr.org/redirect/99146">GitHub Glances</a></li><li>lien nᵒ 3 : <a title="https://github.com/nicolargo/glances/wiki" hreflang="en" href="https://linuxfr.org/redirect/99147">Le Wiki officiel</a></li><li>lien nᵒ 4 : <a title="https://groups.google.com/forum/#!forum/glances-users" hreflang="en" href="https://linuxfr.org/redirect/99148">Le forum utilisateurs</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#aper%C3%A7u-g%C3%A9n%C3%A9ral-de-linterface">Aperçu général de l’interface</a></li>
<li><a href="#nouveau-greffon-pour-superviser-les-processeurs-graphiques-nvidia">Nouveau greffon pour superviser les processeurs graphiques NVIDIA</a></li>
<li><a href="#am%C3%A9lioration-du-greffon-dockers">Amélioration du greffon Dockers</a></li>
<li><a href="#le-greffon-r%C3%A9seau-permet-de-surveiller-la-qualit%C3%A9-du-signal-wifi">Le greffon réseau permet de surveiller la qualité du signal Wi‐Fi</a></li>
<li><a href="#de-nouveaux-modules-dexportation">De nouveaux modules d’exportation</a></li>
<li><a href="#optimisation-de-la-consommation-processeur-de-linterface-web">Optimisation de la consommation processeur de l’interface Web</a></li>
<li><a href="#et-son-lot-dam%C3%A9liorations-et-de-corrections-de-bogues">Et son lot d’améliorations et de corrections de bogues</a></li>
<li><a href="#appel-%C3%A0-contributeurs">Appel à contributeurs</a></li>
</ul><p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f6d61737465722f646f63732f5f7374617469632f676c616e6365732d726573706f6e736976652d77656264657369676e2e706e67/glances-responsive-webdesign.png" alt="Capture Glances" title="Source : https://raw.githubusercontent.com/nicolargo/glances/master/docs/_static/glances-responsive-webdesign.png"></p>
<h2 id="aperçu-général-de-linterface">Aperçu général de l’interface</h2>
<p>Pour ceux qui ne connaissent pas encore Glances, c’est un logiciel libre multi‐plate‐forme permettant de superviser son système d’exploitation ou un système distant à partir d’une interface en une seule vue — d’où son nom, <em>glance</em> signifiant coup d’œil en anglais. Cette interface est disponible en mode console/terminal ou via une interface Web ou mobile.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f76322e382f646f63732f5f7374617469632f676c616e6365732d73756d6d6172792e706e67/glances-summary.png" alt="Glances 2.8" title="Source : https://raw.githubusercontent.com/nicolargo/glances/v2.8/docs/_static/glances-summary.png"></p>
<p>Les développeurs ne sont pas oubliés, car ils disposent d’interfaces XML/RPC et HTTP/<a href="https://fr.wikipedia.org/wiki/RESTful" title="Définition Wikipédia">RESTful</a> pour récupérer les statistiques système dans d’autres applications.</p>
<p>Enfin, les administrateurs système pourront également exporter ces statistiques à long terme vers tout un tas de formats et de bases de données.</p>
<h2 id="nouveau-greffon-pour-superviser-les-processeurs-graphiques-nvidia">Nouveau greffon pour superviser les processeurs graphiques NVIDIA</h2>
<p>C’est une des plus anciennes demandes d’amélioration de Glances : la possibilité de surveiller les processeurs graphiques. Un nouveau greffon voit donc le jour dans cette version, mais avec certaines limitations. En effet, cette première version du greffon pour processeur graphique permet uniquement de surveiller la consommation processeur et mémoire des processeurs graphiques NVIDIA.</p>
<p>Pourquoi cela ? Parce qu’il n’y a, à ma connaissance, aucune bibliothèque permettant de récupérer de manière transparente les statistiques des processeurs graphiques NVIDIA, AMD et Intel. Un contributeur a donc décidé de prendre le taureau par les cornes en commençant par les processeurs graphiques NVIDIA qui disposaient d’une bibliothèque Python (<em>nvidia-ml-py</em>, à installer sur votre système pour bénéficier du greffon pour Glances).</p>
<ul>
<li><p>Vue en moyenne ou mono‐processeur graphique : <img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f76322e382f646f63732f5f7374617469632f6770752e706e67/gpu.png" alt="GPU" title="Source : https://raw.githubusercontent.com/nicolargo/glances/v2.8/docs/_static/gpu.png"></p></li>
<li><p>Vue multi‐processeur graphique : <img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f76322e382f646f63732f5f7374617469632f7065726770752e706e67/pergpu.png" alt="MEANGPU" title="Source : https://raw.githubusercontent.com/nicolargo/glances/v2.8/docs/_static/pergpu.png"></p></li>
</ul><p>Les prochaines versions de Glances amélioreront ce greffon avec la prise en charge d’autres marques de processeurs graphiques et des statistiques supplémentaires (comme les entrées‐sorties).</p>
<h2 id="amélioration-du-greffon-dockers">Amélioration du greffon Dockers</h2>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f76322e372f646f63732f5f7374617469632f646f636b65722e706e67/docker.png" alt="DOCKER" title="Source : https://raw.githubusercontent.com/nicolargo/glances/v2.7/docs/_static/docker.png"><br>
En plus de la prise en charge de la version 2.0 de l’API Docker, Glances 2.8 permet de fixer des seuils d’alerte de manière globale ou par conteneur. Ainsi, il est possible de superviser la consomation processeur d'un conteneur nommé <em>foo</em> en utilisant la syntaxe suivante dans le fichier de configuration de Glances :</p>
<pre><code>[docker]
# Thresthold for CPU (in %)
foo_cpu_careful=70
foo_cpu_warning=80
foo_cpu_critical=90
</code></pre>
<p>Il est également possible de déclencher une action si un seuil est dépassé :</p>
<pre><code>[docker]
foo_cpu_critical_action=echo {{Image}} {{Id}} {{cpu}} > /tmp/container_{{name}}.alert
</code></pre>
<p>Note : dans l’environnement de Glances, une action est une ligne de commande dans laquelle on peut utiliser certaines variables internes issues de l’API à travers les moustaches <code>{{}}</code>.</p>
<h2 id="le-greffon-réseau-permet-de-surveiller-la-qualité-du-signal-wifi">Le greffon réseau permet de surveiller la qualité du signal Wi‐Fi</h2>
<p>Si votre machine dispose d'une interface Wi‐Fi, ce nouveau greffon est fait pour vous. Il permet en effet de superviser la qualité des signaux Wi‐Fi.</p>
<p>Il s’intègre juste en dessous du greffon réseau :<br><img src="//img.linuxfr.org/img/68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f6e69636f6c6172676f2f676c616e6365732f76322e382f646f63732f5f7374617469632f776966692e706e67/wifi.png" alt="WIFI" title="Source : https://raw.githubusercontent.com/nicolargo/glances/v2.8/docs/_static/wifi.png"></p>
<p>En ce qui concerne le greffon réseau, il permet désormais de fixer des seuils manuellement (via le fichier de configuration) ou automatiquement (en fonction de la vitesse des interfaces réseau).</p>
<h2 id="de-nouveaux-modules-dexportation">De nouveaux modules d’exportation</h2>
<p>ZeroMQ et CouchDB viennent s’ajouter à la liste des cibles disponibles pour le module d’exportation des statistiques.</p>
<p>Pour cette version, cette liste est donc la suivante : CSV, InfluxDB, Cassandra, CouchDB, OpenTSDB, StatsD, ElasticSearch, RabbitMQ/ActiveMQ, ZeroMQ et Riemann.</p>
<h2 id="optimisation-de-la-consommation-processeur-de-linterface-web">Optimisation de la consommation processeur de l’interface Web</h2>
<p>Enfin, il est maintenant possible de définir le nombre maximum de processus à afficher dans l’interface Web. Cela réduit de manière importante la consommation processeur du navigateur faisant tourner l’interface de Glances.</p>
<p>Pour définir le nombre de processus (30 par défaut), il suffit de définir la section suivante dans le fichier de configuration :</p>
<pre><code>[outputs]
# Limit the number of processes to display in the WebUI
max_processes_display=30
</code></pre>
<p>Avec 30 processus, on réduit la consommation de 75 %.</p>
<h2 id="et-son-lot-daméliorations-et-de-corrections-de-bogues">Et son lot d’améliorations et de corrections de bogues</h2>
<blockquote>
<ul>
<li>
<em>Not compatible with the new Docker API 2.0 (Docker 1.13) (issue #1000)</em> ;</li>
<li>
<em>Highlight the top CPU and MEM process consumer (issue #878)</em> ;</li>
<li>
<em>Glances API returns the processes PPID (issue #926)</em> ;</li>
<li>
<em>Configure server cached time from the command line <code>--cached-time</code> (issue #901)</em> ;</li>
<li>
<em>Make the log logger configurable (issue #900)</em> ;</li>
<li>
<em>System uptime in export (issue #890)</em> ;</li>
<li>
<em>Refactor the <code>--disable-*</code> options (issue #948)</em> ;</li>
<li>
<em>PID column too small if <code>kernel.pid_max</code> is > 99999 (issue #959)</em> ;</li>
<li>
<em>Glances RAID plugin Traceback (issue #927)</em> ;</li>
<li>
<em>Default AMP crashes when <code>command</code> given (issue #933)</em> ;</li>
<li>
<em>Default AMP ignores <code>enable</code> setting (issue #932)</em> ;</li>
<li>
<em><code>/proc/interrupts</code> not found in an OpenVZ container (issue #947)</em>.</li>
</ul>
</blockquote>
<h2 id="appel-à-contributeurs">Appel à contributeurs</h2>
<p>Je tiens à remercier personnellement <a href="https://github.com/nicolargo/glances/graphs/contributors">tous les contributeurs</a>.</p>
<p>Nous recherchons des personnes motivées pour faire évoluer le projet : </p>
<ul>
<li>développeur Python confirmé ;</li>
<li>développeur JavaScript maîtrisant AngularJS pour l’interface Web ;</li>
<li>des testeurs, notamment dans les environnements Windows et Mac OS X.</li>
</ul></div><div><a href="https://linuxfr.org/news/les-nouveautes-de-glances-2-8.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/111091/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/les-nouveautes-de-glances-2-8#comments">ouvrir dans le navigateur</a>
</p>
nicolargoDavy DefaudXavier TeyssierNils RatusznikPierre JarillonBenoît Sibaudpalm123https://linuxfr.org/nodes/111091/comments.atomtag:linuxfr.org,2005:Post/374902016-11-06T17:44:35+01:002016-11-07T14:12:47+01:00Nagios 4.2.2 Sous Centos 7<p>Est ce centreon fonctionne avec centos 7 ?</p>
<p>Merci</p><div><a href="https://linuxfr.org/forums/linux-debutant/posts/nagios-4-2-2-sous-centos-7.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/110460/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/linux-debutant/posts/nagios-4-2-2-sous-centos-7#comments">ouvrir dans le navigateur</a>
</p>
femerillhttps://linuxfr.org/nodes/110460/comments.atomtag:linuxfr.org,2005:Diary/369172016-10-18T02:17:41+02:002016-10-18T02:17:41+02:00Zyeute: un outil minimaliste de monitoring… ou pasLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Salut les gens,</p>
<p>ma vie t’intéresse ? NAAAAANNNNNNN ! alors va zyeuter <a href="https://framagit.org/peetah/zyeute">ça</a> et bonne nuit.<br>
Sinon, en voici un morceau ! RHHHHOOOOOOO …</p>
<p>Au mois de mai dernier, j’ai eu une déconvenue avec l’outil de surveillance de mon fournisseur de serveurs claudes: alors que ma machine n’avait pas redémarré après un incident encore non élucidé à ce jour, cet outil n’a pas cru bon de m’en informer. Après quelques échanges de messages, le support technique m’indique que cet outil n’est pas fiable et que je ne devrais pas me reposer dessus. </p>
<p>Proposer un outil de surveillance et en avouer l’inefficacité… m’enfin !</p>
<p><strong>[ Alors tu vois qu’elle est chouette ma vie ! tu as bien fait de rester ! ]</strong></p>
<p>D’autre part, j’avais depuis plusieurs années un problème de branchement USB capricieux sur mon serveur auto-hébergé: un peu trop sensible aux vibrations de l’agitation citadine, le disque branché sur ce port USB se désactivait régulièrement, m’obligeant à démonter puis remonter régulièrement l’importun. Et pour réaliser cela, j’avais donné à manger à cron un script qui vérifiait l’état du fichier /dev/sda et s’occupait de remettre le tout d’aplomb en cas de disparition inopinée.</p>
<p><strong>[ C’est long hein ma vie ? Détends-toi les gens, on arrive au point qui captivera nécessairement ton attention… ]</strong></p>
<p>Bref, tout ça pour dire que j’avais besoin d’un outil qui irait à la fois vérifier si mon serveur claude était en ligne et si mon serveur auto-hébergé avait bien accès à son disque dur.</p>
<p>Penses-tu que je me serai renseigné pour savoir si cette perle existait déjà ?<br>
Que nenni ! Je suis un guerrier du bisou<sup id="fnref1"><a href="#fn1">1</a></sup> moi ! <br>
À besoin simple, solution simple: un script bash et hop, c’était plié, le tout placé en bonne position dans le crontab de mon serveur auto-hébergé !</p>
<p>Et puis je me suis dit que je pourrais ajouter à cet outil la possibilité de jeter un œil à la connectivité de mon serveur auto-hébergé depuis mon serveur claude… et puis pourquoi pas également zyeuter le bon fonctionnement de mes serveurs web claudes et auto-hébergé… et puis pourquoi pas du serveur XMPP, du serveur DAVCAL et tout et tout et tout !</p>
<p>Et pouf, du coup me voilà à transformer mon script tout petit tout simple en un outil beaucoup plus générique: le tout joli tout neuf et bien nommé Zyeute !</p>
<p>Zyeute exploite lâchement un fichier de configuration répertoriant les cibles à surveiller dans un contexte particulier, puis les donne sauvagement à manger à des outils de test indépendants de Zyeute:</p>
<ul>
<li>une IP ? allez hop un ping !</li>
<li>une connexion HTTPS ? allez hop une vérification de certificat via openssl !</li>
<li>un fichier qui a tendance à disparaître ? allez hop un [ -e monfichier ] !</li>
</ul><p>Seules contraintes pour ces outils de test:</p>
<ul>
<li>comprendre les arguments transmis par Zyeute</li>
<li>se terminer par un code de sortie de 0 en cas de succès ou de 1 en cas d’échec</li>
</ul><p>Pour plus de bonheur oculaire, un message d’information renseignant le sujet du succès ou de l’échec est tout de même conseillé, mais on sait aussi faire sans.</p>
<p>Et Zyeute dans tout ça ? Quoi c’est qu’il fait lui ?<br>
Par défaut, Zyeute se contente d’informer la majestueuse assemblée observante, par le biais de la sortie standard, d’une part lors de l’échec d’un test, et d’autre part lors du succès d’un test qui aurait précédemment échoué.<br>
Minimaliste on a dit !</p>
<p>Parce que Zyeute conserve un état des différents tests pour les différentes cibles dans leurs différents contextes, il peut être non seulement utilisé de manière ponctuelle, mais délivre tout son potentiel lors d’une automatisation via ton ordonnanceur de tâches préféré.</p>
<p>Ensuite, personnellement, je me plais à tuber cette information vers les outils de diffusion appropriés tels que messagerie électronique, messagerie instantanée et/ou SMS pour être certain de ne pas manquer la catastrophe annoncée d’un service inévitablement défaillant.</p>
<p><strong>[ Bah voilà tu sais tout les gens ! J’avais prévenu hein: y avait du level ! GG comme on dit chez les jeunes. ]</strong></p>
<p>Ah si ! Comme je m’étais préalablement fait la main avec <a href="https://framagit.org/peetah/DLFPlonk">DLFPLonk</a>, j’ai choisi de capitaliser sur cette expérience de <a href="https://framagit.org">FramaGit</a>, le <a href="https://gitlab.com">GitLab</a> de <a href="https://framasoft.org">FramaSoft</a>, pour y partager <a href="https://framagit.org/peetah/zyeute">Zyeute</a> sous licence <a href="https://unlicense.org">Unlicense</a>.</p>
<p>Outre la correction d’insectes, fruits ignobles de tes retours et remontées peut-être acides, nécessaire avant une version unité, cette version 0.9 ne doit son manque de dixième qu’à l’irrépressible nécessité de la dépouiller de sa dépendance actuelle au bash environnant: avoue, les gens, qu’un Zyeute qui tournerait sous un maximum de coquillages aurait autrement plus de chien !</p>
<p>Tiens d’ailleurs j’en profite pour t’avertir qu’en plus de bash, il te faudra sed, grep, find et <a href="https://github.com/stedolan/jq">jq</a> >= 1.5 pour utiliser mon, que dis-je, notre déjà indispensable Zyeute.<br>
Mais tout cela, et bien plus encore, tu le trouveras dans l’assemblage de mots qui se veut servir de documentation.<br>
Parce qu’il ne faut pas faire l'autruche: il va falloir la retravailler pour attirer le chaland.</p>
<p>Sur ce, bonne nuit les gens et n’oublie pas: <em>Zyeute veille pour toi</em>.</p>
<div class="footnotes">
<hr>
<ol>
<li id="fn1">
<p>KISS warrior <a href="#fnref1">↩</a></p>
</li>
</ol>
</div><div><a href="https://linuxfr.org/users/anonyme/journaux/zyeute-un-outil-minimaliste-de-monitoring-ou-pas.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/110302/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/anonyme/journaux/zyeute-un-outil-minimaliste-de-monitoring-ou-pas#comments">ouvrir dans le navigateur</a>
</p>
Anonymehttps://linuxfr.org/nodes/110302/comments.atomtag:linuxfr.org,2005:Diary/365132016-04-09T01:15:50+02:002016-04-09T01:15:50+02:00SNMP vs NRPELicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Et oui me direz-vous ! pourquoi ce titre aussi débile ?</p>
<p>SNMP est un protocole ad-hoc.</p>
<ul>
<li>standard, cross-plateforme (IETF inside)</li>
<li>implémenté, de base +extensible, par presque n’importe quel hôte…</li>
<li>en tant que protocole purement IP, pas forcément priorisé sur les flux TCP/IP ou UDP/IP en cas d’engorgement…</li>
</ul><p>NRPE est un protocole laxiste mais puissant.</p>
<ul>
<li><p>déjà il demande le lancement d’un service pas si « standard » que SNMP…, qui est implémenté Linux/Windows mais sur un router ou un switch tu vas pouvoir te brosser… alors que le router ou le switch (ou le frigo) en question parle déjà SNMP en fait…</p></li>
<li><p>son fichier de configuration inclue une directive expressément nommé <strong>dont_blame_nrpe</strong> dans le code, qu’à mon avis tous les décideurs avides de fonctionnalités, de modularité… font… le choix d’activer. C’est pourtant une porte ouverte à toute les tentatives d’abus… Alors qu’avec cette directive à "Off" l’exposition est incomensurablement moins étendue…</p></li>
<li><p>L’adoption très grande de ce protocole fait qu’on peut coder un « Check Nagios » absolument n’importe comment, tout le monde est d’accord sur des conventions de sortie standard et de code de retour…</p></li>
<li><p>NRPE implique des déploiements réguliers à chaque évolution (ajout, modification d’une commande…), évolutions spécialisées (windwos, linux, …). Là où, SNMP a le mérite d’être panOS…</p></li>
</ul><p>Pour ma part je pense que ces deux protocoles sont complémentaires. Ayant bien envie de connaître votre avis j’ai écrit ce journal dans ce but.</p><div><a href="https://linuxfr.org/users/m4rotte/journaux/snmp-vs-nrpe.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/108673/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/m4rotte/journaux/snmp-vs-nrpe#comments">ouvrir dans le navigateur</a>
</p>
Marotte ⛧https://linuxfr.org/nodes/108673/comments.atomtag:linuxfr.org,2005:News/371872016-03-26T15:12:54+01:002016-03-26T15:12:53+01:00Skydive, un nouvel outil d’analyse de votre réseauLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Skydive est un logiciel libre, sous licence Apache, permettant d’analyser les problèmes et de surveiller vos réseaux <a href="https://fr.wikipedia.org/wiki/Software-defined_networking">SDN</a>. <em>Software Defined Networking</em> est une architecture réseau abstraite permettant de gérer globalement ses ressources, elle est principalement utilisée dans les infrastructures de type Cloud, car elle offre une grande souplesse d’utilisation.</p></div><ul><li>lien nᵒ 1 : <a title="http://softwarefactory-project.io/r/#/q/project:skydive" hreflang="en" href="https://linuxfr.org/redirect/96762">Software Factory</a></li><li>lien nᵒ 2 : <a title="http://blogs.rdoproject.org/7874/skydive-a-real-time-network-analyzer" hreflang="en" href="https://linuxfr.org/redirect/96763">Blog post</a></li><li>lien nᵒ 3 : <a title="https://github.com/redhat-cip/skydive" hreflang="en" href="https://linuxfr.org/redirect/96764">Github</a></li><li>lien nᵒ 4 : <a title="https://github.com/redhat-cip/skydive/releases/download/v0.2.0/skydive" hreflang="wq" href="https://linuxfr.org/redirect/96771">Skydive release 0.2.0 (binaire, 20 Mo)</a></li></ul><div><h2 id="skydive">Skydive</h2>
<p>Une infrastructure SDN est complexe, mais trouver la source des problèmes l’est encore plus. Qui n’a pas eu de problème de paquets perdus pendant un déploiement ? Combien de flux simultanés la machine virtuelle du <em>tenant</em> (locataire) “Mr T” génère-t-elle ? Que s’est-il passé à 4h du matin ?</p>
<p>C’est pour répondre à ce genre de questions que le projet Skydive a été créé.</p>
<h2 id="topologie">Topologie</h2>
<p>Skydive permet de visualiser la topologie en temps réel et de faire la corrélation avec le trafic du réseau. L’architecture du projet Skydive contient des agents de collecte d’informations de topologie et de flux de votre réseau, ainsi qu’un agent de collecte et d’analyse permettant de faire la corrélation des différents points d’analyse de votre réseau physique ou virtuel. De plus, une interface web minimaliste est présente sur le port 8082 de l’agent d’analyse des données collectées, celle-ci vous permettra de visualiser la topologie et les flux de votre réseau.</p>
<h2 id="sondes">Sondes</h2>
<p>Skydive repose sur des sondes de collecte. À la fois pour la capture de la topologie et pour la capture des flux réseaux. Skydive embarque nativement les principales sondes permettant la collecte des informations des interfaces réseaux et d'une sonde sFlow pour la capture des flux. Bien qu'étant agnostique du SDN utilisé, il est possible d'enrichir les données collectées grâce à celles issues du contrôleur. Les connecteurs disponibles actuellement sont OpenStack et Docker.</p>
<h2 id="post-mortem">Post mortem</h2>
<p>Dans le cas d’utilisation de Skydive pour une analyse post mortem des problèmes rencontrés sur des applications/VM, Skydive enregistre ses données dans une base <a href="https://fr.wikipedia.org/wiki/Elasticsearch">Elasticsearch</a>.</p>
<h2 id="Écrit-en-go">Écrit en Go</h2>
<p>Skydive est écrit en Go, simple d’utilisation, et vous permettra de logger, comprendre, visualiser, dépanner votre réseau ou plus encore… Les git-review sont les bienvenus :)</p>
<h2 id="présence-à-lopenstack-summit">Présence à l'OpenStack Summit</h2>
<p>Nous serons présents à l'<a href="https://www.openstack.org/summit/austin-2016/summit-schedule/events/8540">OpenStack Summit</a> à Austin, Texas où aura lieu une présentation sur Skydive.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6c68332e676f6f676c6575736572636f6e74656e742e636f6d2f786b4437502d6e78586667796a31714d6769316665434353455574544441526d764870597043306d6766506a7a48625a51763971654c7a6833665a706e4c764e3137375f67526b686e6d6f593d77313030382d683735312d6e6f/xkD7P-nxXfgyj1qMgi1feCCSEUtTDARmvHpYpC0mgfPjzHbZQv9qeLzh3fZpnLvN177_gRkhnmoY=w1008-h751-no" alt="Impression d'écran de Skydive" title="Source : https://lh3.googleusercontent.com/xkD7P-nxXfgyj1qMgi1feCCSEUtTDARmvHpYpC0mgfPjzHbZQv9qeLzh3fZpnLvN177_gRkhnmoY=w1008-h751-no"><br><img src="//img.linuxfr.org/img/687474703a2f2f69312e77702e636f6d2f626c6f67732e72646f70726f6a6563742e6f72672f77702d636f6e74656e742f75706c6f6164732f323031362f30322f436170747572652d64752d323031362d30322d32332d3137313431312e706e673f773d31323233/Capture-du-2016-02-23-171411.png?w=1223" alt="Autre impression d'écran de Skydive" title="Source : http://i1.wp.com/blogs.rdoproject.org/wp-content/uploads/2016/02/Capture-du-2016-02-23-171411.png?w=1223"></p></div><div><a href="https://linuxfr.org/news/skydive-un-nouvel-outil-d-analyse-de-votre-reseau.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/108550/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/skydive-un-nouvel-outil-d-analyse-de-votre-reseau#comments">ouvrir dans le navigateur</a>
</p>
Nicolas PLANELpalm123Nils RatusznikXavier TeyssierNÿcoBenoît Sibaudhttps://linuxfr.org/nodes/108550/comments.atomtag:linuxfr.org,2005:Diary/363672016-02-09T11:44:30+01:002016-02-09T13:45:38+01:00License pour un système de journalisation/supervision de consommations énergétiques (pour une Ville)Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Bonjour chers lecteurs de linuxfr.org.<br>
J'aimerais solliciter votre aide concernant un choix de licence pour un projet du domaine publique.</p>
<p>Le projet :<br>
Créer un système de prise de mesures, d’agrégation, transmission et affichage de ces mesures et enfin analyse de ces mesures. Le but étant d'optimiser la consommation énergétique de la ville de Lorient (le projet émane du service environnement). Un petit truc en plus qui va vous intéresser, c'est que la personne en charge de cet appel d'offre (Pierre Crépeaux) veut utiliser un maximum de matériels ouverts et de logiciels open-source ou mieux : libres.</p>
<p>Mon approche :<br>
Utiliser de l'Arduino, des mini-pc sous Debian et un système de supervision (pour les systèmes informatiques). Pour information, je n'ai pas encore eu la validation sur le fait que mon entreprise soit retenue.</p>
<p>La question :<br>
Je vais créer des documents de projet (architecture, docs d'installation, procédures, etc), des bouts de code et des modèles de configuration. Bref, surtout du travail d'intégration. Un des objectifs pour moi (et également pour M. Crépeaux) est de partager le projet. Car de mon point de vue un système tel que demandé coûte bonbon quand il est mis en place par des sociétés dédiées. Et je considère que le projet doit pouvoir être copié/collé par d'autres villes qui n'ont pas un gros budget pour ça.</p>
<p>Bref, quelle licence choisir ? Les besoins :<br>
- garder le droit de paternité (c'est ma société qui l'a fait et ça doit être marqué et perdurer)<br>
- droits d'exploitation commerciale : libres<br>
- copyleft : oui (une modification sur les livrables doit être rendue publique)<br>
- attention aux interconnections via flux réseau ( GNU Affero règle ça ? )<br>
Je ne suis pas au point en ce qui concerne le droit des licences libres. Pouvez vous me conseiller SVP chers lecteurs ?</p>
<p>PS : pour info, le dossier de l'appel d'offre est ici : <a href="http://www.liberasys.com/wp-content/uploads/2016/02/DATALOGGING-BATIMENTS.zip">www.liberasys.com/wp-content/uploads/2016/02/DATALOGGING-BATIMENTS.zip</a> chose pas banale : voir le document "Annexe 1.doc" dans le dossier "DCE GENERAL" : "Annexe 1- Charte d’exigences pour un datalogging open source" ; ça va vous faire plaisir de voir ça.</p><div><a href="https://linuxfr.org/users/ghusson/journaux/license-pour-un-systeme-de-journalisation-supervision-de-consommations-energetiques-pour-une-ville.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/108145/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/ghusson/journaux/license-pour-un-systeme-de-journalisation-supervision-de-consommations-energetiques-pour-une-ville#comments">ouvrir dans le navigateur</a>
</p>
ghussonhttps://linuxfr.org/nodes/108145/comments.atomtag:linuxfr.org,2005:News/370852016-02-07T09:41:56+01:002016-02-07T09:41:56+01:00Présentation technique de CanopsisLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Supervision et visualisation des données : des domaines de l'informatique qui nous permettent de surveiller, analyser une infra, des données afin de comprendre et éventuellement prédire des dysfonctionnements.</p>
<p>De nombreux outils existent et excellent dans chacune de ces tâches. Les accorder ensemble afin d'unifier l'information permet ainsi de faciliter la prise de décision.</p>
<p>C'est ce que l'on appelle <strong>l'hypervision</strong>.</p>
<p>Canopsis se veut une solution d'hypervision (on évite l'appellation <em>hyperviseur</em> qui reste dans le langage courant spécifique à la virtualisation). Solution open-source sous licence AGPL3 développée par la société française <a href="http://capensis.fr">Capensis</a>, elle se veut simple d'utilisation, et suffisamment souple pour répondre à un maximum de besoin.</p></div><ul><li>lien nᵒ 1 : <a title="https://git.canopsis.net/explore" hreflang="fr" href="https://linuxfr.org/redirect/96352">Gitlab de Canopsis</a></li><li>lien nᵒ 2 : <a title="https://capensis.fr" hreflang="fr" href="https://linuxfr.org/redirect/96353">Capensis</a></li><li>lien nᵒ 3 : <a title="http://www-igm.univ-mlv.fr/~dr/XPOSE2010/Hypervision/Hyperviseur.html" hreflang="fr" href="https://linuxfr.org/redirect/96354">Présentation d'un hyperviseur</a></li><li>lien nᵒ 4 : <a title="http://www.informatique-securite.net/hypervision-supervision/" hreflang="fr" href="https://linuxfr.org/redirect/96355">Hypervision - Piloter votre supervision</a></li><li>lien nᵒ 5 : <a title="http://wiki.monitoring-fr.org/hypervision/start" hreflang="fr" href="https://linuxfr.org/redirect/96356">Hypervision sur monitoring-fr</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#la-probl%C3%A9matique">La problématique</a></li>
<li>
<a href="#objectif--la-solution">Objectif : la solution</a><ul>
<li><a href="#%C3%89tape-1--les-connecteurs">Étape 1 : les connecteurs</a></li>
<li><a href="#%C3%89tape-2--le-bus-de-donn%C3%A9es-et-les-moteurs">Étape 2 : le bus de données et les moteurs</a></li>
<li><a href="#%C3%89tape-3--les-sch%C3%A9mas">Étape 3 : les schémas</a></li>
<li>
<a href="#%C3%89tape-4--g%C3%A9rer-et-servir-la-donn%C3%A9e">Étape 4 : gérer et servir la donnée</a><ul>
<li><a href="#a-les-managers">A. Les managers</a></li>
<li><a href="#b-les-webservices">B. Les webservices</a></li>
</ul>
</li>
<li>
<a href="#%C3%89tape-5--lapplication-web">Étape 5 : l'application web</a><ul>
<li><a href="#a-les-briques">A. Les briques</a></li>
<li><a href="#b-les-composants">B. Les composants</a></li>
<li><a href="#c-les-renderers%C3%A9diteurs">C. Les renderers/éditeurs</a></li>
<li><a href="#d-les-widgets">D. Les widgets</a></li>
<li><a href="#e-les-mixins">E. Les mixins</a></li>
<li><a href="#f-les-vues">F. Les vues</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#le-bac-%C3%A0-%C3%A9v%C3%A9nements">Le bac à événements</a></li>
<li><a href="#s%C3%A9lecteur-et-widget-m%C3%A9t%C3%A9o--simplifier-la-supervision">Sélecteur et widget météo : simplifier la supervision</a></li>
<li><a href="#monitoring-et-s%C3%A9ries">Monitoring et séries</a></li>
<li><a href="#les-t%C3%A2ches-ordonnanc%C3%A9es-et-les-notifications">Les tâches ordonnancées et les notifications</a></li>
<li><a href="#conclusion">Conclusion</a></li>
</ul><h2 id="la-problématique">La problématique</h2>
<p>Dans une infra hétérogène, on dispose de nombreuses sources d'information :</p>
<ul>
<li>côté supervision, on peut avoir un mélange de :
<ul>
<li>Nagios/Icinga</li>
<li>Centreon</li>
<li>Shinken</li>
<li>HPOV</li>
<li>Zabbix</li>
<li>SNMP</li>
<li>…</li>
</ul>
</li>
<li>côté récolte de données, on peut avoir :
<ul>
<li>CollectD</li>
<li>Logstash</li>
<li>Munin</li>
<li>Telegraf (de la pile <a href="https://influxdata.com/">TICK</a>)</li>
<li>…</li>
</ul>
</li>
<li>ou encore :
<ul>
<li>des logs</li>
<li>des données stockées en base de données</li>
<li>un résultat de tests unitaires et fonctionnels (jMeter, Sikuli…)</li>
</ul>
</li>
</ul><p>La mise en place d'un accès à l'ensemble de ces informations peut être fastidieuse, et dans la plupart des cas, l'utilisateur (l'administrateur technique et/ou fonctionnel) devra accéder à plusieurs interfaces et maîtriser plusieurs outils.</p>
<p>Cela empêche d'avoir une vue d'ensemble cohérente et rend difficile l'anticipation ainsi que la prise de décision.</p>
<h2 id="objectif--la-solution">Objectif : la solution</h2>
<p>C'est là que Canopsis intervient.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e63616e6f707369732e636f6d2f77702d636f6e74656e742f7468656d65732f63616e6f707369732f696d616765732f736368656d612e706e67/schema.png" alt="Schéma fonctionnel" title="Source : http://www.canopsis.com/wp-content/themes/canopsis/images/schema.png"></p>
<h3 id="Étape-1--les-connecteurs">Étape 1 : les connecteurs</h3>
<p>Dans un premier temps, nous devons récupérer les informations produites par cet ensemble hétérogène.</p>
<p>Ainsi, pour chaque source de données, nous sommes en mesure de développer un <strong>connecteur</strong>, capable d'extraire les informations voulues, et de les transmettre à Canopsis sous la forme <strong>d'événements</strong> standardisés.</p>
<p>Un certain nombre de connecteurs sont déjà disponibles sur le <a href="https://git.canopsis.net/groups/canopsis-connectors">Gitlab</a>.</p>
<p>Le cas le plus simple est donc celui ci :</p>
<pre><code class="python"><span class="c">#!/usr/bin/env python</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">time</span>
<span class="c"># lib qui nous permet de nous connecter au bus de données (cf étape 2)</span>
<span class="kn">from</span> <span class="nn">kombu</span> <span class="kn">import</span> <span class="n">Connection</span>
<span class="c"># module qui sera utilisé pour envoyer les événements</span>
<span class="kn">from</span> <span class="nn">kombu.pools</span> <span class="kn">import</span> <span class="n">producers</span>
<span class="c"># construction de l'événement selon le standard Canopsis</span>
<span class="n">event</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"timestamp"</span><span class="p">:</span> <span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="p">()),</span>
<span class="c"># émetteur de l'événement</span>
<span class="s">"connector"</span><span class="p">:</span> <span class="s">"myconnector"</span><span class="p">,</span>
<span class="s">"connector_name"</span><span class="p">:</span> <span class="s">"myconnector-instance0"</span><span class="p">,</span>
<span class="c"># nature de l'événement</span>
<span class="s">"event_type"</span><span class="p">:</span> <span class="s">"check"</span><span class="p">,</span>
<span class="c"># source de l'événement</span>
<span class="s">"source_type"</span><span class="p">:</span> <span class="s">"resource"</span><span class="p">,</span>
<span class="s">"component"</span><span class="p">:</span> <span class="s">"<hostname>"</span><span class="p">,</span>
<span class="s">"resource"</span><span class="p">:</span> <span class="s">"<job's name>"</span><span class="p">,</span>
<span class="c"># données portées par l'événement</span>
<span class="s">"state"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="c"># 0 = INFO, 1 = MINOR, 2 = MAJOR, 3 = CRITICAL</span>
<span class="s">"output"</span><span class="p">:</span> <span class="s">"<message>"</span>
<span class="p">}</span>
<span class="c"># construction de la routing_key, qui sert à identifier l'événement et à le router</span>
<span class="n">routing_key</span> <span class="o">=</span> <span class="s">"{0}.{1}.{2}.{3}.{4}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">event</span><span class="p">[</span><span class="s">'connector'</span><span class="p">],</span>
<span class="n">event</span><span class="p">[</span><span class="s">'connector_name'</span><span class="p">],</span>
<span class="n">event</span><span class="p">[</span><span class="s">'event_type'</span><span class="p">],</span>
<span class="n">event</span><span class="p">[</span><span class="s">'source_type'</span><span class="p">],</span>
<span class="n">event</span><span class="p">[</span><span class="s">'component'</span><span class="p">]</span>
<span class="p">)</span>
<span class="k">if</span> <span class="n">event</span><span class="p">[</span><span class="s">'source_type'</span><span class="p">]</span> <span class="o">==</span> <span class="s">"resource"</span><span class="p">:</span>
<span class="n">routing_key</span> <span class="o">=</span> <span class="s">"{0}.{1}"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">routing_key</span><span class="p">,</span>
<span class="n">event</span><span class="p">[</span><span class="s">'resource'</span><span class="p">]</span>
<span class="p">)</span>
<span class="c"># Connexion</span>
<span class="n">uri</span> <span class="o">=</span> <span class="s">'amqp://cpsrabbit:canopsis@localhost:5672/canopsis'</span>
<span class="k">with</span> <span class="n">Connection</span><span class="p">(</span><span class="n">uri</span><span class="p">)</span> <span class="k">as</span> <span class="n">conn</span><span class="p">:</span>
<span class="c"># Création de l'émetteur</span>
<span class="k">with</span> <span class="n">producers</span><span class="p">[</span><span class="n">conn</span><span class="p">]</span><span class="o">.</span><span class="n">acquire</span><span class="p">(</span><span class="n">block</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="k">as</span> <span class="n">producer</span><span class="p">:</span>
<span class="c"># Publication</span>
<span class="n">producer</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
<span class="n">event</span><span class="p">,</span>
<span class="n">serializer</span><span class="o">=</span><span class="s">'json'</span><span class="p">,</span>
<span class="n">exchange</span><span class="o">=</span><span class="s">'canopsis.events'</span><span class="p">,</span>
<span class="n">routing_key</span><span class="o">=</span><span class="n">routing_key</span>
<span class="p">)</span></code></pre>
<p>Bien évidemment, du moment qu'un connecteur envoie ses événements, il peut être développé dans n'importe quel langage, c'est le cas du connecteur Nagios qui se présente comme un Nagios Event Broker, et est donc développé en C.</p>
<h3 id="Étape-2--le-bus-de-données-et-les-moteurs">Étape 2 : le bus de données et les moteurs</h3>
<p>Les événements produits par les connecteurs sont transmis au bus de données de Canopsis, basé sur <a href="https://www.rabbitmq.com/">RabbitMQ</a>.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f69676d2e756e69762d6d6c762e66722f7e64722f58504f5345323031312f7261626269746d712f6c6f61645f62616c616e63696e672e706e67/load_balancing.png" alt="Schema RabbitMQ" title="Source : http://igm.univ-mlv.fr/~dr/XPOSE2011/rabbitmq/load_balancing.png"></p>
<p>Source : <a href="http://igm.univ-mlv.fr/%7Edr/XPOSE2011/rabbitmq/usages.html">http://igm.univ-mlv.fr/~dr/XPOSE2011/rabbitmq/usages.html</a></p>
<p>Ces événements vont être consommés par des <em>daemons</em> que nous appelons <strong>moteurs</strong>.</p>
<p>Leur but est simple :</p>
<ul>
<li>traiter la donnée</li>
<li>enregistrer les informations pertinentes en base de données</li>
<li>transmettre, si nécessaire, l'événement à un ou plusieurs autres moteurs</li>
</ul><p>Nous avons, par exemple :</p>
<ul>
<li>le moteur <code>event_filter</code> qui se charge de filtrer/modifier les événements entrants</li>
<li>le moteur <code>context</code> qui se charge d'enregistrer les informations sur l'entité cible de l'événement (connecteur source, composant/ressource qui a produit l'événement…)</li>
<li>le moteur <code>perfdata</code> qui s'occupe d'historiser les données de performance (comme remontées par Nagios ou CollectD)</li>
<li>…</li>
</ul><p>Comme pour les <em>connecteurs</em>, les <em>moteurs</em> peuvent être développés dans n'importe quel langage, bien que pour le moment nous les avons tous faits en Python.</p>
<p>Étant un <em>daemon</em>, un <em>moteur</em> dispose de 2 fonctions :</p>
<ul>
<li>une pour consommer les événements (dans un <em>thread</em> à part)</li>
<li>une pour exécuter une tâche régulièrement (recharger la configuration, envoyer des stats…)</li>
</ul><p>Ainsi que la configuration suivante :</p>
<pre><code class="ini"><span class="k">[engine:myengine]</span>
<span class="c1"># chemin Python de la méthode de consommation</span>
<span class="na">event_processing</span><span class="o">=</span><span class="s">canopsis.myfeature.process.event_processing</span>
<span class="c1"># chemin Python de la méthode exécutée régulièrement</span>
<span class="na">beat_processing</span><span class="o">=</span><span class="s">canopsis.myfeature.process.beat_processing</span>
<span class="c1"># nom de l'exchange AMQP sur lequel écouter (par défaut: amq.direct)</span>
<span class="na">exchange_name</span><span class="o">=</span><span class="s">canopsis.event</span>
<span class="c1"># RK à consommer</span>
<span class="na">routing_keys</span><span class="o">=</span><span class="s">nagios.#,shinken.#</span>
<span class="c1"># intervalle entre 2 exécutions du beat_processing (en secondes)</span>
<span class="na">beat_interval</span><span class="o">=</span><span class="s">60</span>
<span class="c1"># liste des moteurs sur lesquels retransmettre l'événement reçu, possiblement modifié (par défaut: aucun)</span>
<span class="na">next</span><span class="o">=</span><span class="s">myengine2,myengine3</span></code></pre>
<p>Et donc l'implémentation se résume à :</p>
<pre><code class="python"><span class="k">def</span> <span class="nf">event_processing</span><span class="p">(</span><span class="n">engine</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="o">**</span><span class="n">_</span><span class="p">):</span>
<span class="c"># traiter l'événement</span>
<span class="k">return</span> <span class="n">event</span>
<span class="k">def</span> <span class="nf">beat_processing</span><span class="p">(</span><span class="n">engine</span><span class="p">,</span> <span class="o">**</span><span class="n">_</span><span class="p">):</span>
<span class="c"># faire des choses</span></code></pre>
<h3 id="Étape-3--les-schémas">Étape 3 : les schémas</h3>
<p>Toutes les données qui véhiculent dans le bus et qui sont sauvegardées en base sont munies de schémas les décrivant.</p>
<p>Ces schémas servent à plusieurs choses :</p>
<ul>
<li>valider que la donnée est bien formatée</li>
<li>décrire comment la donnée sera représentée</li>
<li>décrire comment la donnée sera éditée</li>
</ul><p>Ces deux derniers points permettent de générer une partie du code de l'UI (cf étape 5).</p>
<p>À terme, ils serviront également à :</p>
<ul>
<li>décrire comment la donnée sera utilisée</li>
<li>décrire comment la donnée pourra être transformée</li>
</ul><p>Ce qui permettra de générer une partie du code backend (cf étape 4).</p>
<p>Le formalisme qui permet d'écrire un schéma est actuellement inspiré du standard <a href="http://json-schema.org/">JSON Schema</a> :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"MyData"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Schéma décrivant la donnée, comment l'afficher et l'éditer"</span>
<span class="c1">// description de la donnée</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"object"</span><span class="p">,</span>
<span class="s2">"properties"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"color"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"string"</span><span class="p">,</span>
<span class="s2">"required"</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="cm">/* comment la donnée sera affichée/éditée</span>
<span class="cm"> * le rôle 'color' :</span>
<span class="cm"> * - affichera un carré de couleur lorsqu'on l'affichera</span>
<span class="cm"> * - affichera un colorpicker lorsqu'on l'éditera</span>
<span class="cm"> */</span>
<span class="s2">"role"</span><span class="o">:</span> <span class="s2">"color"</span><span class="p">,</span>
<span class="c1">// les champs suivants servent pour le formulaire</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"Couleur de la donnée"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Tooltip d'aide"</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">// les champs suivants aident à générer le formulaire d'édition</span>
<span class="s2">"categories"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"General"</span><span class="p">,</span>
<span class="s2">"keys"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"color"</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span></code></pre>
<p>L'<code>id</code> d'un schéma est construit de la manière suivante :</p>
<ul>
<li><code>mydata</code></li>
<li>
<code>mydata.mydata2</code> : ici <code>mydata2</code> hérite de <code>mydata</code>
</li>
</ul><p>On obtient donc en base de données :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"_id"</span><span class="o">:</span> <span class="s2">"<id du schema>"</span><span class="p">,</span>
<span class="s2">"schema"</span><span class="o">:</span> <span class="c1">// le schéma à proprement parler</span>
<span class="p">}</span></code></pre>
<h3 id="Étape-4--gérer-et-servir-la-donnée">Étape 4 : gérer et servir la donnée</h3>
<p>Maintenant que nous avons la structure pour récupérer la donnée, et que nous sommes en mesure de la schématiser, il faut mettre en place les mécanismes permettant d'interagir avec et de la servir à l'UI.</p>
<h4 id="a-les-managers">A. Les managers</h4>
<p>La gestion de la donnée est prise en charge par ce que l'on appelle les <strong>managers</strong>. Pour bien comprendre son rôle, il faut plonger un peu dans le code.</p>
<p>Un <strong>configurable</strong> est un objet Python dont les propriétés sont définies par son fichier de configuration :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">canopsis.configuration.configurable</span> <span class="kn">import</span> <span class="n">Configurable</span>
<span class="kn">from</span> <span class="nn">canopsis.configuration.configurable.decorator</span> <span class="kn">import</span> <span class="n">conf_paths</span>
<span class="kn">from</span> <span class="nn">canopsis.configuration.configurable.decorator</span> <span class="kn">import</span> <span class="n">add_category</span>
<span class="kn">from</span> <span class="nn">canopsis.configuration.model</span> <span class="kn">import</span> <span class="n">Parameter</span>
<span class="n">CONF_PATH</span> <span class="o">=</span> <span class="s">'myfeature/manager.conf'</span> <span class="c"># {sys.prefix}/etc/{CONF_PATH}</span>
<span class="n">CATEGORY</span> <span class="o">=</span> <span class="s">'MYFEATURE'</span>
<span class="c"># Définition du contenu de la catégorie</span>
<span class="n">CONTENT</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">Parameter</span><span class="p">(</span><span class="s">'foo'</span><span class="p">),</span>
<span class="n">Parameter</span><span class="p">(</span><span class="s">'bar'</span><span class="p">,</span> <span class="n">parser</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
<span class="p">]</span>
<span class="c"># ajoute un fichier de configuration à lire par le configurable</span>
<span class="nd">@conf_paths</span><span class="p">(</span><span class="n">CONF_PATH</span><span class="p">)</span>
<span class="c"># permet de spécifier la catégorie de configuration depuis laquelle on peut lire les paramètres</span>
<span class="nd">@add_category</span><span class="p">(</span><span class="n">CATEGORY</span><span class="p">,</span> <span class="n">content</span><span class="o">=</span><span class="n">CONTENT</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">MyFeatureManager</span><span class="p">(</span><span class="n">Configurable</span><span class="p">):</span>
<span class="k">pass</span></code></pre>
<p>Ainsi, avec le fichier de configuration suivant :</p>
<pre><code class="ini"><span class="k">[MYFEATURE]</span>
<span class="na">foo</span><span class="o">=</span><span class="s">bar</span>
<span class="na">bar</span><span class="o">=</span><span class="s">42</span></code></pre>
<p>Ou :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"MYFEATURE"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"foo"</span><span class="o">:</span> <span class="s2">"bar"</span><span class="p">,</span>
<span class="s2">"bar"</span><span class="o">:</span> <span class="mi">42</span>
<span class="p">}</span>
<span class="p">}</span></code></pre>
<p>En effet, le configurable va tester différents drivers, actuellement on dispose de INI et JSON mais il est envisageable d'avoir un driver MongoDB ou autre</p>
<p>Lorsque l'on instanciera la classe, on obtiendra :</p>
<pre><code class="python"><span class="n">obj</span> <span class="o">=</span> <span class="n">MyFeatureManager</span><span class="p">()</span>
<span class="k">assert</span> <span class="n">obj</span><span class="o">.</span><span class="n">foo</span> <span class="o">==</span> <span class="s">"bar"</span>
<span class="k">assert</span> <span class="n">obj</span><span class="o">.</span><span class="n">bar</span> <span class="o">==</span> <span class="mi">42</span></code></pre>
<p>Et à partir de cette classe <code>Configurable</code> on va définir l'arbre d'héritage suivant :</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6c75742e696d2f684147434b6b50544c6e2f496a4e43675541764369486f7233696c/IjNCgUAvCiHor3il" alt="Diagramme Configurable" title="Source : https://lut.im/hAGCKkPTLn/IjNCgUAvCiHor3il"></p>
<p>Un <code>ConfigurableRegistry</code> permet de spécifier, dans un paramètre de configuration, un autre <code>Configurable</code> à instancier :</p>
<pre><code class="ini"><span class="na">otherconfigurable_value</span> <span class="o">=</span> <span class="s">canopsis.myotherfeature.manager.MyOtherFeatureManager</span></code></pre>
<p>Et on y accèdera, dans l'instance, de la manière suivante :</p>
<pre><code class="python"><span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="p">[</span><span class="s">'otherconfigurable'</span><span class="p">],</span> <span class="n">MyOtherFeatureManager</span><span class="p">)</span></code></pre>
<p>Le <code>MiddlewareRegistry</code> fait de même pour les <code>Middleware</code> (qui identifient un <strong>protocole</strong> ainsi qu'un <strong>type de données</strong>) :</p>
<pre><code class="ini"><span class="na">mymiddleware_uri</span> <span class="o">=</span> <span class="s">protocol-datatype-datascope://</span></code></pre>
<p>De même que pour le <code>ConfigurableRegistry</code>, on y accède de la manière suivante :</p>
<pre><code class="python"><span class="k">assert</span> <span class="bp">self</span><span class="p">[</span><span class="s">'mymiddleware'</span><span class="p">]</span><span class="o">.</span><span class="n">connected</span><span class="p">()</span></code></pre>
<p>En général, un <em>manager</em> sera un <code>MiddlewareRegistry</code>, ce qui permettra de changer de techno utilisée, sans modifier le code :</p>
<pre><code class="ini"><span class="k">[MYFEATURE]</span>
<span class="na">mystorage_uri</span> <span class="o">=</span> <span class="s">mongodb-timed-mydata://</span>
<span class="c1"># mystorage_uri = influxdb-timed-mydata://</span>
<span class="na">mymanager_value</span> <span class="o">=</span> <span class="s">canopsis.myotherfeature.manager.MyOtherFeatureManager</span>
<span class="c1"># mymanager_value = canopsis.myotherfeature.manager2.MyOtherFeatureManager2</span></code></pre>
<p>Et ce manager sera utilisé par le <strong>moteur</strong> et le <strong>webservice</strong>.</p>
<p>En reprenant l'exemple du moteur :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">canopsis.common.utils</span> <span class="kn">import</span> <span class="n">singleton_per_scope</span>
<span class="kn">from</span> <span class="nn">canopsis.myfeature.manager</span> <span class="kn">import</span> <span class="n">MyFeatureManager</span>
<span class="k">def</span> <span class="nf">event_processing</span><span class="p">(</span><span class="n">engine</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="n">manager</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">_</span><span class="p">):</span>
<span class="k">if</span> <span class="n">manager</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="c"># instancie la classe une seule fois par module</span>
<span class="n">manager</span> <span class="o">=</span> <span class="n">singleton_per_scope</span><span class="p">(</span><span class="n">MyFeatureManager</span><span class="p">)</span>
<span class="c"># faire des choses avec l'événement et le manager</span>
<span class="k">return</span> <span class="n">event</span>
<span class="k">def</span> <span class="nf">beat_processing</span><span class="p">(</span><span class="n">engine</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="n">manager</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">_</span><span class="p">):</span>
<span class="k">if</span> <span class="n">manager</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">manager</span> <span class="o">=</span> <span class="n">singleton_per_scope</span><span class="p">(</span><span class="n">MyFeatureManager</span><span class="p">)</span>
<span class="c"># faire des choses avec le manager</span></code></pre>
<h4 id="b-les-webservices">B. Les webservices</h4>
<p>Afin de servir la donnée à l'UI, on dispose d'une application WSGI découpée en modules, que l'on appelle <strong>webservice</strong>.</p>
<p>Ces derniers se trouvent dans le paquet Python <code>canopsis.webcore.services</code>.</p>
<p>Et grâce au code suivant (à placer dans le <code>__init__.py</code>), on peut avoir plusieurs paquets Python fournissant du code à cet emplacement :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">pkgutil</span> <span class="kn">import</span> <span class="n">extend_path</span>
<span class="n">__path__</span> <span class="o">=</span> <span class="n">extend_path</span><span class="p">(</span><span class="n">__path__</span><span class="p">,</span> <span class="n">__name__</span><span class="p">)</span></code></pre>
<p>Bref, un <em>webservice</em> s'écrit très simplement :</p>
<pre><code class="python"><span class="c"># couche d'abstraction qui nous permettra de passer de Bottle à Flask</span>
<span class="kn">from</span> <span class="nn">canopsis.common.ws</span> <span class="kn">import</span> <span class="n">route</span>
<span class="kn">from</span> <span class="nn">canopsis.common.utils</span> <span class="kn">import</span> <span class="n">singleton_per_scope</span>
<span class="kn">from</span> <span class="nn">canopsis.myfeature.manager</span> <span class="kn">import</span> <span class="n">MyFeatureManager</span>
<span class="c"># Sera appelé par l'application WSGI pour charger les routes HTTP</span>
<span class="k">def</span> <span class="nf">exports</span><span class="p">(</span><span class="n">ws</span><span class="p">):</span>
<span class="c"># ici `ws` désigne donc le webserver</span>
<span class="n">manager</span> <span class="o">=</span> <span class="n">singleton_per_scope</span><span class="p">(</span><span class="n">MyFeatureManager</span><span class="p">)</span>
<span class="c"># ici on créé la route /foo qui accepte la méthode GET</span>
<span class="nd">@route</span><span class="p">(</span><span class="n">ws</span><span class="o">.</span><span class="n">application</span><span class="o">.</span><span class="n">get</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">foo</span><span class="p">():</span>
<span class="k">return</span> <span class="n">manager</span><span class="o">.</span><span class="n">foo</span>
<span class="c"># l'API retournera :</span>
<span class="c"># {</span>
<span class="c"># "total": 1,</span>
<span class="c"># "data": ["bar"],</span>
<span class="c"># "success": true</span>
<span class="c"># }</span>
<span class="c"># cette fois ci, on créé la route /bar/:baz</span>
<span class="nd">@route</span><span class="p">(</span><span class="n">ws</span><span class="o">.</span><span class="n">application</span><span class="o">.</span><span class="n">get</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="n">baz</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">manager</span><span class="o">.</span><span class="n">bar</span> <span class="o">==</span> <span class="n">baz</span><span class="p">)</span></code></pre>
<h3 id="Étape-5--lapplication-web">Étape 5 : l'application web</h3>
<p>Côté <em>backend</em>, on dispose désormais du nécessaire pour fournir à l'UI tout ce dont elle a besoin.<br>
Ainsi, nous avons également travaillé la modularité de cette UI, basée sur <a href="http://emberjs.com">Ember</a>, au maximum.</p>
<h4 id="a-les-briques">A. Les briques</h4>
<p>Afin de répondre à cette problématique de modularité, nous avons mis en place un système de briques, permettant de sélectionner les fonctionnalités effectivement chargées.</p>
<p>Concrètement, on peut voir une <strong>brique</strong> comme étant un <em>addon</em> apportant plusieurs fonctionnalités telles que :</p>
<ul>
<li>nouveaux éléments graphiques (<em>composants</em>)</li>
<li>nouveaux outils de rendus (<em>widgets</em>, <em>renderers</em>)</li>
<li>nouveaux outils d'éditions (<em>éditors</em>)</li>
<li>…</li>
</ul><p>Pour construire une brique, il suffit de créer un paquet <a href="https://www.npmjs.com/">NPM</a> avec le <code>package.json</code> suivant :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"name"</span><span class="o">:</span> <span class="s2">"<nom de la brique>"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"<description de la brique>"</span><span class="p">,</span>
<span class="s2">"version"</span><span class="o">:</span> <span class="s2">"0.1.0"</span><span class="p">,</span>
<span class="c1">// il s'agit du fichier principal de la brique, il pointera vers la version de dev ou minifiée</span>
<span class="s2">"main"</span><span class="o">:</span> <span class="s2">"init.js"</span><span class="p">,</span>
<span class="s2">"scripts"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"test"</span><span class="o">:</span> <span class="s2">"echo \"Error: no test specified\" && exit 1"</span><span class="p">,</span>
<span class="s2">"compile"</span><span class="o">:</span> <span class="s2">"rm -Rf tmp/build && broccoli build tmp/build && cp tmp/build . -RT"</span><span class="p">,</span>
<span class="s2">"lint"</span><span class="o">:</span> <span class="s2">"eslint src"</span><span class="p">,</span>
<span class="s2">"doc"</span><span class="o">:</span> <span class="s2">"./node_modules/canopsis-ui-toolbelt/scripts/buildDoc"</span><span class="p">,</span>
<span class="s2">"minify"</span><span class="o">:</span> <span class="s2">"node node_modules/canopsis-ui-toolbelt/scripts/minify.js"</span>
<span class="p">},</span>
<span class="s2">"repository"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"git"</span><span class="p">,</span>
<span class="s2">"url"</span><span class="o">:</span> <span class="s2">"<url du dépôt>"</span>
<span class="p">},</span>
<span class="s2">"author"</span><span class="o">:</span> <span class="s2">"<auteur>"</span><span class="p">,</span>
<span class="s2">"license"</span><span class="o">:</span> <span class="s2">"AGPL-3.0"</span><span class="p">,</span>
<span class="s2">"devDependencies"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"broccoli"</span><span class="o">:</span> <span class="s2">"^0.16.9"</span><span class="p">,</span>
<span class="s2">"broccoli-funnel"</span><span class="o">:</span> <span class="s2">"^1.0.1"</span><span class="p">,</span>
<span class="s2">"broccoli-merge-trees"</span><span class="o">:</span> <span class="s2">"^1.0.0"</span><span class="p">,</span>
<span class="s2">"broccoli-sourcemap-concat"</span><span class="o">:</span> <span class="s2">"^1.1.6"</span><span class="p">,</span>
<span class="s2">"broccoli-template"</span><span class="o">:</span> <span class="s2">"^0.1.1"</span><span class="p">,</span>
<span class="s2">"broccoli-uglify-js"</span><span class="o">:</span> <span class="s2">"^0.1.3"</span><span class="p">,</span>
<span class="c1">// outil de gestion des briques Canopsis</span>
<span class="s2">"canopsis-ui-toolbelt"</span><span class="o">:</span> <span class="s2">"https://git.canopsis.net/canopsis/canopsis-ui-toolbelt/repository/archive.tar.gz?ref=<branche git de canopsis-ui-toolbelt>"</span><span class="p">,</span>
<span class="s2">"jsdoc"</span><span class="o">:</span> <span class="s2">"^3.3.0"</span><span class="p">,</span>
<span class="s2">"pre-commit"</span><span class="o">:</span> <span class="s2">"^1.1.1"</span>
<span class="p">},</span>
<span class="s2">"pre-commit"</span><span class="o">:</span> <span class="p">[</span>
<span class="s2">"lint"</span><span class="p">,</span>
<span class="s2">"doc"</span>
<span class="p">]</span>
<span class="p">}</span></code></pre>
<p>Puis, dans un dossier <code>src</code> on placera le code source de la brique :</p>
<ul>
<li><code>components/mycomponent/component.js</code></li>
<li><code>components/mycomponent/template.hbs</code></li>
<li><code>renderers/renderer-myrole.hbs</code></li>
<li><code>editors/editor-myrole.hbs</code></li>
<li><code>widgets/mywidget/controller.js</code></li>
<li><code>widgets/mywidget/mywidget.hbs</code></li>
<li><code>mixins/mymixin.js</code></li>
</ul><p>L'outil <code>canopsis-ui-toolbelt</code> se charge de :</p>
<ul>
<li>récupérer récursivement tout le code JS dans le dossier <code>src</code>
</li>
<li>référencer le code JS dans le fichier <code>init.js</code> qui représente la brique</li>
<li>récupérer récursivement tout les templates (<code>*.hbs</code>) dans le dossier <code>src</code>
</li>
<li>référencer les templates également dans le fichier <code>init.js</code>
</li>
<li>référencer les templates dans <code>Ember.TEMPLATES</code> :
<ul>
<li>pour un composant, il est requis d'avoir le dossier <code>components/<mycomponent></code>, afin que le template soit reconnu comme étant un template de composant</li>
<li>pour le reste, le nom du template dans <em>Ember</em> sera le nom du fichier sans extension</li>
</ul>
</li>
</ul><p><em>NB: Le découpage n'est donc obligatoire que pour les composants, le reste peut être mis en vrac dans <code>src</code>.</em></p>
<p>Une fois que l'on a créé tout cela (ou récupéré le dépôt Git), on peut finaliser la brique :</p>
<pre><code>$ npm install
$ npm run compile
</code></pre>
<p>Chaque fichier source contiendra au moins un <strong>Ember Initializer</strong> :</p>
<pre><code class="javascript"><span class="nx">Ember</span><span class="p">.</span><span class="nx">Application</span><span class="p">.</span><span class="nx">initializer</span><span class="p">({</span>
<span class="nx">name</span><span class="o">:</span> <span class="s1">'MyModule'</span><span class="p">,</span>
<span class="nx">after</span><span class="o">:</span> <span class="p">[</span><span class="s1">'Dependency1'</span><span class="p">,</span> <span class="s1">'Dependency2'</span><span class="p">],</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">container</span><span class="p">,</span> <span class="nx">application</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">Dependency1</span> <span class="o">=</span> <span class="nx">container</span><span class="p">.</span><span class="nx">lookupFactory</span><span class="p">(</span><span class="s1">'deptype:dependency1'</span><span class="p">),</span>
<span class="nx">Dependency2</span> <span class="o">=</span> <span class="nx">container</span><span class="p">.</span><span class="nx">lookupFactory</span><span class="p">(</span><span class="s1">'deptype:dependency2'</span><span class="p">);</span>
<span class="c1">// do stuff</span>
<span class="nx">application</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">'modtype:mymodule'</span><span class="p">,</span> <span class="cm">/* stuff */</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span></code></pre>
<p>Cela permet ainsi de s'assurer du bon chargement de chaque module.</p>
<p>Au final, pour installer une brique, il suffit de :</p>
<ul>
<li>cloner le dépôt finalisé dans : <code>/opt/canopsis/var/www/canopsis</code>
</li>
<li>lancer la commande <code>webmodulemanager enable mybrick</code> afin de l'activer au chargement de l'UI</li>
</ul><p>L'ensemble des briques existantes (hormis celle par défaut livrées avec Canopsis) sont disponible <a href="https://git.canopsis.net/groups/canopsis-ui-bricks">ici</a>.</p>
<h4 id="b-les-composants">B. Les composants</h4>
<p>Le composant, l'élément le plus basique de l'UI, sera utilisé par tout les autres éléments.<br>
Il s'agit simplement d'un composant <em>Ember</em> avec un template à fournir.</p>
<p>On définira notre composant dans <code>src/components/mycomponent/component.js</code> :</p>
<pre><code class="javascript"><span class="nx">Ember</span><span class="p">.</span><span class="nx">Application</span><span class="p">.</span><span class="nx">initializer</span><span class="p">({</span>
<span class="nx">name</span><span class="o">:</span> <span class="s1">'MyComponent'</span><span class="p">,</span>
<span class="nx">after</span><span class="o">:</span> <span class="p">[],</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">container</span><span class="p">,</span> <span class="nx">application</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">MyComponent</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Component</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
<span class="nx">init</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_super</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
<span class="c1">// faire des choses</span>
<span class="p">},</span>
<span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// on implémente les actions, déclenchable depuis le template</span>
<span class="nx">foo</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="s1">'bar'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">application</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">'component:component-mycomponent'</span><span class="p">,</span> <span class="nx">MyComponent</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span></code></pre>
<p>Et le template dans <code>src/components/mycomponent/template.hbs</code> :</p>
<pre><code class="html"><span class="nt"><h1></span>My awesome component<span class="nt"></h1></span>
<span class="nt"><a</span> <span class="err">{{</span><span class="na">action</span> <span class="na">foo</span><span class="err">}}</span><span class="nt">></span>Launch action<span class="nt"></a></span></code></pre>
<h4 id="c-les-rendererséditeurs">C. Les renderers/éditeurs</h4>
<p>Une fois nos composants définis, on est en mesure de les utiliser dans des <strong>renderers</strong> ou des <strong>éditeurs</strong>.</p>
<p>Le but de ces éléments est simple :</p>
<ul>
<li>lorsqu'on demande l'affichage d'une donnée avec le composant <code>renderer</code> :
<ul>
<li>le champ <code>role</code> du schéma JSON est également lu</li>
<li>si un <em>renderer</em> du même nom est trouvé, il est utilisé dans le template</li>
<li>sinon, on affiche la donnée telle quelle</li>
</ul>
</li>
<li>lorsqu'un formulaire d'édition est généré à partir du schéma JSON, en utilisant le composant <code>editor</code> :
<ul>
<li>le champ <code>role</code> est lu</li>
<li>si un éditeur du même nom est trouvé, il est utilisé dans le formulaire</li>
<li>sinon, on utilise l'éditeur par défaut</li>
</ul>
</li>
</ul><p>Les <em>renderers</em>/<em>éditeurs</em> ne sont donc que de simple templates <a href="https://github.com/tildeio/htmlbars">HTMLBars</a>.</p>
<p>On aura le <em>renderer</em> dans <code>src/renderers/renderer-myrole.hbs</code> :</p>
<pre><code class="html"><span class="nt"><p></span>My rendered data: {{value}}<span class="nt"></p></span>
{{component-mycomponent}}</code></pre>
<p>Et l'<em>éditeur</em> dans <code>src/editors/editor-myrole.hbs</code> :</p>
<pre><code class="html"><span class="nt"><p></span>My data is being edited :<span class="nt"></p></span>
{{input type="password" value=attr.value}}
{{component-mycomponent}}</code></pre>
<h4 id="d-les-widgets">D. Les widgets</h4>
<p>Enfin, on aura les <strong>widgets</strong>, qui seront en mesure d'utiliser <em>composants</em> et<br><em>renderers</em> afin d'implémenter des outils de visualisation de données plus complexes.</p>
<p>Un <em>widget</em> est un <strong>MVC</strong> complet :</p>
<ul>
<li>on implémente un contrôleur</li>
<li>on implémente des <em>mixins</em> qui viendront s'appliquer à la vue</li>
<li>on écrit un template</li>
</ul><p>Ce qui donne :</p>
<pre><code class="javascript"><span class="nx">Ember</span><span class="p">.</span><span class="nx">Application</span><span class="p">.</span><span class="nx">initializer</span><span class="p">({</span>
<span class="nx">name</span><span class="o">:</span> <span class="s1">'MyWidget'</span><span class="p">,</span>
<span class="nx">after</span><span class="o">:</span> <span class="p">[</span><span class="s1">'WidgetFactory'</span><span class="p">],</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">container</span><span class="p">,</span> <span class="nx">application</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">WidgetFactory</span> <span class="o">=</span> <span class="nx">container</span><span class="p">.</span><span class="nx">lookupFactory</span><span class="p">(</span><span class="s1">'factory:widget'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">widgetOptions</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">MyWidgetViewMixin</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">Mixin</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="nx">didInsertElement</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_super</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
<span class="c1">// faire des choses</span>
<span class="p">},</span>
<span class="nx">willDestroyElement</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_super</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
<span class="c1">// faire des choses</span>
<span class="p">},</span>
<span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// actions de la vue</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="kd">var</span> <span class="nx">widget</span> <span class="o">=</span> <span class="nx">WidgetFactory</span><span class="p">(</span><span class="s1">'mywidget'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">viewMixins</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">MyWidgetViewMixin</span>
<span class="p">],</span>
<span class="nx">actions</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// actions du contrôleur</span>
<span class="p">},</span>
<span class="nx">init</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// faire des choses</span>
<span class="p">},</span>
<span class="nx">findItems</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// méthode appelée lors de la récupération des données pour le template</span>
<span class="p">}</span>
<span class="p">},</span> <span class="nx">widgetOptions</span><span class="p">);</span>
<span class="nx">application</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">'widget:mywidget'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span></code></pre>
<p>Ensuite, il est nécessaire de créer un schéma <code>widget.mywidget.json</code> qui sera utilisé pour configurer le widget lors de son ajout dans une vue :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"MyWidget"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Schéma de configuration de MyWidget"</span><span class="p">,</span>
<span class="s2">"metadata"</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// icône dans le formulaire d'ajout de widget</span>
<span class="s2">"icon"</span><span class="o">:</span> <span class="s2">"fa fa-cog"</span>
<span class="p">},</span>
<span class="s2">"categories"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"General"</span><span class="p">,</span>
<span class="s2">"keys"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"foo"</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"object"</span><span class="p">,</span>
<span class="s2">"properties"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"foo"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"Foo"</span><span class="p">,</span> <span class="c1">// nom du champ dans le formulaire</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Foo field"</span><span class="p">,</span> <span class="c1">// tooltip dans le formulaire</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"string"</span><span class="p">,</span>
<span class="s2">"role"</span><span class="o">:</span> <span class="s2">"myrole"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre>
<h4 id="e-les-mixins">E. Les mixins</h4>
<p>Lorsque l'on a des fonctionnalités communes à plusieurs widgets (comme le <code>PeriodicRefresh</code> qui actualise le widget régulièrement), il convient de factoriser le code en un <strong>mixin</strong>.</p>
<p>Ce dernier pourra être ajouté et configuré au <em>widget</em> via l'UI, et ensuite appliquer la-dite configuration au contrôleur du widget :</p>
<pre><code class="javascript"><span class="nx">Ember</span><span class="p">.</span><span class="nx">Application</span><span class="p">.</span><span class="nx">initializer</span><span class="p">({</span>
<span class="nx">name</span><span class="o">:</span><span class="s1">'MyMixin'</span><span class="p">,</span>
<span class="nx">after</span><span class="o">:</span> <span class="p">[</span><span class="s1">'MixinFactory'</span><span class="p">],</span>
<span class="nx">initialize</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">container</span><span class="p">,</span> <span class="nx">application</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">Mixin</span> <span class="o">=</span> <span class="nx">container</span><span class="p">.</span><span class="nx">lookupFactory</span><span class="p">(</span><span class="s1">'factory:mixin'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">get</span> <span class="o">=</span> <span class="nx">Ember</span><span class="p">.</span><span class="nx">get</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">MyMixin</span> <span class="o">=</span> <span class="nx">Mixin</span><span class="p">(</span><span class="s1">'mymixin'</span><span class="p">,</span> <span class="p">{</span>
<span class="nx">mixinsOptionsReady</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_super</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">mixinOptions</span> <span class="o">=</span> <span class="nx">get</span><span class="p">(</span><span class="s1">'mixinOptions.mymixin'</span><span class="p">);</span>
<span class="c1">// faire des choses</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">application</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">'mixin:mymixin'</span><span class="p">,</span> <span class="nx">MyMixin</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span></code></pre>
<p>Et il ne manque plus que le schéma <code>mixin.mymixin.json</code> décrivant la configuration du <em>mixin</em> :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"MyMixin"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Schéma de configuration de MyMixin"</span><span class="p">,</span>
<span class="s2">"metadata"</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// description affiché dans l'UI</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Add stuff to widget"</span>
<span class="p">},</span>
<span class="s2">"categories"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"General"</span><span class="p">,</span>
<span class="s2">"keys"</span><span class="o">:</span> <span class="p">[</span><span class="s2">"bar"</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"object"</span><span class="p">,</span>
<span class="s2">"properties"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"bar"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"Bar"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"Bar field"</span><span class="p">,</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"string"</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre>
<h4 id="f-les-vues">F. Les vues</h4>
<p>Tout les outils sont désormais à notre disposition pour construire nos <em>dashboards</em>.</p>
<p>Donc si on résume :</p>
<ul>
<li>une <strong>vue</strong> est composée de <em>widgets</em>
</li>
<li>un <em>widget</em> est composé de <em>composants</em> et de <em>mixins</em>
</li>
</ul><p>L'UI fournit les outils qui permettent de construire ces vues, le résultat final est un document JSON stocké en base :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s2">"_id"</span><span class="o">:</span> <span class="s2">"id de ma vue"</span><span class="p">,</span>
<span class="s2">"description"</span><span class="o">:</span> <span class="s2">"description de ma vue"</span>
<span class="s2">"crecord_name"</span><span class="o">:</span> <span class="s2">"nom de ma vue"</span><span class="p">,</span>
<span class="s2">"crecord_type"</span><span class="o">:</span> <span class="s2">"view"</span><span class="p">,</span>
<span class="s2">"author"</span><span class="o">:</span> <span class="s2">"<user qui a créé la vue>"</span><span class="p">,</span>
<span class="s2">"enable"</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="s2">"internal"</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="s2">"tags"</span><span class="o">:</span> <span class="p">[],</span>
<span class="c1">// le widget initial de la vue</span>
<span class="s2">"containerwidget"</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// identifiant du widget</span>
<span class="s2">"xtype"</span><span class="o">:</span> <span class="s2">"widgetcontainer"</span><span class="p">,</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"container title vbox"</span><span class="p">,</span>
<span class="c1">// le widget "widgetcontainer" s'attend à avoir un champ "items"</span>
<span class="s2">"items"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="c1">// le widget "widgetwrapper" sert à inclure des widgets dans un container pour les placer correctement</span>
<span class="s2">"xtype"</span><span class="o">:</span> <span class="s2">"widgetwrapper"</span><span class="p">,</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"wrapper"</span><span class="p">,</span>
<span class="c1">// le widget encapsulé :</span>
<span class="s2">"widget"</span><span class="o">:</span> <span class="p">{</span>
<span class="s2">"xtype"</span><span class="o">:</span> <span class="s2">"mywidget"</span><span class="p">,</span>
<span class="s2">"title"</span><span class="o">:</span> <span class="s2">"My awesome widget"</span><span class="p">,</span>
<span class="c1">// configuration spécifique au widget</span>
<span class="s2">"foo"</span><span class="o">:</span> <span class="s2">"bar"</span><span class="p">,</span>
<span class="c1">// mixins appliqués via l'UI :</span>
<span class="s2">"mixins"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"name"</span><span class="o">:</span> <span class="s2">"periodicrefresh"</span><span class="p">,</span>
<span class="c1">// paramètres du mixin</span>
<span class="s2">"refreshInterval"</span><span class="o">:</span> <span class="mi">60</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="s2">"name"</span><span class="o">:</span> <span class="s2">"mymixin"</span><span class="p">,</span>
<span class="c1">// paramètres du mixin</span>
<span class="s2">"bar"</span><span class="o">:</span> <span class="s2">"baz"</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="c1">// le container de base de la vue à un widget de layout par défaut</span>
<span class="s2">"mixins"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"name"</span><span class="o">:</span> <span class="s2">"lightlayout"</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span></code></pre>
<p>La totalité de l'UI est générée à partir de ces vues JSON, et est donc complètement personnalisable.</p>
<h2 id="le-bac-à-événements">Le bac à événements</h2>
<p>Parmi les vues par défaut qui sont livrées avec Canopsis, on trouve le <strong>Bac à événements</strong>.</p>
<p>Cette vue fournit un <em>dashboard</em> de supervision commun, unifiant ainsi la totalité des superviseurs remontant des informations à Canopsis.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6c75742e696d2f4e4f39435252754476492f325757494b674355726b364574593175/2WWIKgCUrk6EtY1u" alt="screenshot du bac à événements" title="Source : https://lut.im/NO9CRRuDvI/2WWIKgCUrk6EtY1u"></p>
<p>Depuis ce bac, on voit apparaître les différentes alarmes avec comme informations :</p>
<ul>
<li>leurs sources d'émission (le connecteur)</li>
<li>leurs sources cible (composant/ressource, qui dans la plupart des cas correspond au couple <em>host</em>/<em>service</em>)</li>
<li>le dernier message associé à un <em>check</em> (Nagios, Shinken, Centreon, …)</li>
<li>le statut de l'alarme associé au <em>check</em> :
<ul>
<li>
<strong>Off</strong> : aucune alarme n'est présente</li>
<li>
<strong>On Going</strong> : un problème a été remonté et n'est toujours pas résolu</li>
<li>
<strong>Stealthy</strong> : une alarme a été remontée et est immédiatement repassée OK (durée paramétrable)</li>
<li>
<strong>Flapping</strong> : il y a eu X changements d'état en 1h sur l'alarme (durée et fréquence paramétrable)</li>
<li>
<strong>Cancelled</strong> : l'alarme a été annulée par un utilisateur (pour éviter les faux-positifs)</li>
</ul>
</li>
<li>l'état du <em>check</em> :
<ul>
<li>
<strong>INFO</strong> : tout va bien</li>
<li>
<strong>MINOR</strong> : équivalent au <em>Warning</em> de Nagios</li>
<li>
<strong>MAJOR</strong> : équivalent au <em>Critical</em> de Nagios</li>
<li>
<strong>CRITICAL</strong> : les <em>Unknown</em> de Nagios sont remontés en tant que tel, mais cela ne se limite pas à cette notion</li>
<li>
<strong>UNKNOWN</strong> : état non pris en charge à l'heure actuelle, c'est tout ce qui est supérieur à <em>CRITICAL</em> (<code>3</code>)</li>
</ul>
</li>
<li>la présence d'un acquittement et/ou d'un ticket :
<ul>
<li>les connecteurs pour Nagios, Shinken, etc… peuvent remonter les acquittements posés</li>
<li>depuis Canopsis, on peut en poser manuellement</li>
</ul>
</li>
<li>la date du dernier changement d'état</li>
</ul><p>Sur chaque alarme, on peut réaliser différentes actions :</p>
<ul>
<li>l'acquittement (permet de déverrouiller les autres actions), cela émettra le même événement qui serait remonté par un superviseur, soit un événement de type <code>ack</code>
</li>
<li>une suppression de l'acquittement, cela émettra un événement de type <code>ackremove</code>
</li>
<li>une annulation de l'alarme, cela émettra un événement de type <code>cancel</code>
</li>
<li>une fois l'alarme annulée, on peut annuler cette action, cela émettra un événement de type <code>uncancel</code>
</li>
<li>une déclaration de ticket :
<ul>
<li>cela émettra un événement de type <code>declareticket</code>
</li>
<li>cet événement pourra être capturé par le moteur <code>event_filter</code> pour déclencher un job (voir plus bas) qui communiquera le ticket à un outil tiers (par exemple <a href="http://www.combodo.com/itop">iTop</a>)</li>
</ul>
</li>
<li>une association de ticket existant :
<ul>
<li>cela émettra un événement de type <code>assocticket</code>
</li>
<li>on peut imaginer que le job qui communique la déclaration du ticket à l'outil tiers récupère le numéro du ticket nouvellement créé, et l'associe automatiquement</li>
</ul>
</li>
<li>une requalification de l'événement :
<ul>
<li>cela changera l'état du <em>check</em> manuellement, et ce dernier gardera cet état jusqu'à la résolution de l'alarme</li>
<li>cela émettra un événement de type <code>check</code>, comme le superviseur</li>
<li>la seule différence est la présence d'un champ <code>keep_state</code> qui vaut <code>true</code> dans l'événement</li>
</ul>
</li>
</ul><p>Toutes ces actions permettent ainsi d'unifier une supervision hétérogène, et l'administrateur (technique) ne devra utiliser/maîtriser qu'un seul outil.</p>
<h2 id="sélecteur-et-widget-météo--simplifier-la-supervision">Sélecteur et widget météo : simplifier la supervision</h2>
<p>Lorsque l'on supervise une grosse infrastructure, les informations remontées via les <em>checks</em> deviennent tout de suite beaucoup plus conséquentes. C'est pourquoi nous avons mis en place la possibilité d'agréger ces <em>checks</em> afin d'avoir une visibilité plus simple sur l'infra.</p>
<p>Cette agrégation se fait à l'aide des <strong>sélecteurs</strong> :</p>
<ul>
<li>on créé un filtre d'événements</li>
<li>on applique un algorithme à l'état de chaque <em>check</em> qui matche le filtre (actuellement seul l'algo <strong>Worst State</strong> est disponible)</li>
<li>on produit un événement de type <code>selector</code> qui contient :
<ul>
<li>l'état agrégé</li>
<li>le champ <code>output</code> qui est le rendu du template spécifié dans la configuration du sélecteur</li>
</ul>
</li>
<li>si le sélecteur est configuré pour, on déclenche le calcul des <strong>SLA</strong> :
<ul>
<li>sur une période de temps (spécifiée dans la configuration du sélecteur)</li>
<li>on calcule le pourcentage de temps passé sur chaque état possible</li>
<li>on produit une <em>métrique</em> pour chacune de ces métriques, ainsi qu'un événement de type <code>sla</code>
</li>
<li>l'état remonté par l'événement correspond aux seuils de SLA configurés dans le sélecteur</li>
</ul>
</li>
</ul><p>Le résultat est finalement affichable avec un widget <strong>weather</strong> :</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6c75742e696d2f72466a387241725044672f383866507a4643305931354b35423030/88fPzFC0Y15K5B00" alt="screenshot widget weather" title="Source : https://lut.im/rFj8rArPDg/88fPzFC0Y15K5B00"></p>
<p><em>NB: Le sélecteur peut afficher également des checks unitairement</em></p>
<p>On peut ainsi noter les couleurs suivantes :</p>
<ul>
<li>
<em>vert</em> : l'état du sélecteur est <code>INFO</code>
</li>
<li>
<em>jaune</em> : l'état du sélecteur est <code>MINOR</code>
</li>
<li>
<em>orange</em> : l'état du sélecteur est <code>MAJOR</code>
</li>
<li>
<em>rouge</em> : l'état du sélecteur est <code>CRITICAL</code>
</li>
<li>
<em>violet</em> : toutes les alarmes du sélecteur ont été acquittée</li>
<li>la couleur du widget est celle du pire état des sélecteurs positionnés dans celui ci</li>
</ul><p>Un clic sur le sélecteur dans le widget nous redirigera sur le <em>Bac à événements</em>, filtré avec le filtre du sélecteur.</p>
<h2 id="monitoring-et-séries">Monitoring et séries</h2>
<p>Chaque connecteur, moteur, et sélecteur produisent des données de performances :</p>
<ul>
<li>temps d'exécution d'un <em>check</em>
</li>
<li>usage CPU/RAM/Disque</li>
<li>temps moyen passé sur un événement</li>
<li>nombre moyen d'événements par seconde</li>
<li>donnée de SLA</li>
<li>…</li>
</ul><p>Tout cela est remonté dans Canopsis dans un événement via le champ <code>perf_data_array</code> :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="c1">// info de l'événement classique</span>
<span class="s2">"perf_data_array"</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="s2">"metric"</span><span class="o">:</span> <span class="s2">"nom_de_ma_metrique"</span><span class="p">,</span>
<span class="s2">"value"</span><span class="o">:</span> <span class="mf">42.1337</span><span class="p">,</span>
<span class="s2">"type"</span><span class="o">:</span> <span class="s2">"GAUGE"</span><span class="p">,</span> <span class="c1">// GAUGE, COUNTER, ABSOLUTE ou DERIVE</span>
<span class="c1">// champs optionnels</span>
<span class="s2">"unit"</span><span class="o">:</span> <span class="s2">"..."</span><span class="p">,</span>
<span class="s2">"min"</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="s2">"max"</span><span class="o">:</span> <span class="mf">1337.42</span><span class="p">,</span>
<span class="s2">"warn"</span><span class="o">:</span> <span class="mi">1000</span><span class="p">,</span>
<span class="s2">"crit"</span><span class="o">:</span> <span class="mi">1300</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span></code></pre>
<p>Ces données vont être historisée dans Canopsis. On peut donc noter 4 types de métriques :</p>
<ul>
<li>
<code>GAUGE</code> : on historise la valeur telle quelle</li>
<li>
<code>COUNTER</code> : lorsque l'on récupère la valeur, on fait l'addition des valeurs historisées</li>
<li>
<code>ABSOLUTE</code> : on historise la valeur absolue</li>
<li>
<code>DERIVE</code> : il s'agit de la valeur dérivée par rapport au temps</li>
</ul><p>Une métrique est ensuite identifiée par :</p>
<ul>
<li>le composant de l'événement</li>
<li>la ressource de l'événement</li>
<li>le nom de la métrique dans le tableau de <em>perfdata</em>
</li>
</ul><p>Le tout peut être affiché dans un chart :</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f6c75742e696d2f7435554f6566485170612f385a48595364427878624f444f4a5377/8ZHYSdBxxbODOJSw" alt="screenshot de timechart" title="Source : https://lut.im/t5UOefHQpa/8ZHYSdBxxbODOJSw"></p>
<p>On est ainsi en mesure de sélectionner un ensemble de métrique avec un filtre basé sur des expressions régulières :</p>
<ul>
<li><code>co:.*\.myhost re:cpu-.* me:system me:user me:wait</code></li>
</ul><p>Qui se traduit en filtre MongoDB :</p>
<pre><code class="javascript"><span class="p">{</span>
<span class="s1">'$and'</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span><span class="s1">'component'</span><span class="o">:</span> <span class="p">{</span><span class="s1">'$regex'</span><span class="o">:</span> <span class="s1">'.*\.myhost'</span><span class="p">}},</span>
<span class="p">{</span><span class="s1">'resource'</span><span class="o">:</span> <span class="p">{</span><span class="s1">'$regex'</span><span class="o">:</span> <span class="s1">'cpu.*'</span><span class="p">}},</span>
<span class="p">{</span>
<span class="s1">'$or'</span><span class="o">:</span> <span class="p">[</span>
<span class="p">{</span><span class="s1">'name'</span><span class="o">:</span> <span class="p">{</span><span class="s1">'$regex'</span><span class="o">:</span> <span class="s1">'system'</span><span class="p">}},</span>
<span class="p">{</span><span class="s1">'name'</span><span class="o">:</span> <span class="p">{</span><span class="s1">'$regex'</span><span class="o">:</span> <span class="s1">'user'</span><span class="p">}},</span>
<span class="p">{</span><span class="s1">'name'</span><span class="o">:</span> <span class="p">{</span><span class="s1">'$regex'</span><span class="o">:</span> <span class="s1">'wait'</span><span class="p">}}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span></code></pre>
<p>Une fois les identifiants de métriques récupérés, on peut aller demander les points stockés en base, dans une fenêtre de temps bien définie.</p>
<p>Une <strong>série</strong> est donc munie :</p>
<ul>
<li>d'un filtre de métrique</li>
<li>d'une période d'agrégation avec un opérateur d'agrégation (le manager de <em>perfdata</em> nous retournera les données agrégées)</li>
<li>d'une période de consolidation</li>
<li>d'une formule de consolidation</li>
</ul><p>Ici la partie consolidation sert à consolider les différents points agrégés en un seul, afin de produire une nouvelle métrique.</p>
<p>La formule se construit de la manière suivante :</p>
<ul>
<li>on a des opérateurs qui prennent en paramètre un filtre de métrique qui sera appliqué sur l'ensemble de métriques déjà sélectionnées</li>
<li>ces opérateurs retournent un point consolidé</li>
<li>on peut les utiliser dans une expression mathématique classique</li>
</ul><p>Par exemple, <code>SUM("me:.*") / COUNT("me:.*")</code>, permet de réaliser une moyenne.</p>
<h2 id="les-tâches-ordonnancées-et-les-notifications">Les tâches ordonnancées et les notifications</h2>
<p>Parmi les moteurs de Canopsis, certains sont dédiés à une fonction précise : exécuter une tâche.</p>
<p>Il y a donc un moteur <strong>scheduler</strong> qui, régulièrement, va chercher à exécuter des jobs configurés selon une <a href="http://www.kanzaki.com/docs/ical/rrule.html">règle de récurrence</a>.<br>
En fonction du type de job, ce dernier sera redirigé au moteur correspondant, que l'on appellera un <strong>taskhandler</strong>.</p>
<p>Cela permet de construire un équivalent de <code>crontab</code> au sein de Canopsis.</p>
<p>Ces <em>taskhandlers</em> ne servent pas uniquement à l'exécution de tâches ordonnancées, ils peuvent être utilisés en tant que notification :</p>
<ul>
<li>une règle du moteur <em>event_filter</em> peut déclencher l'exécution d'un job si l'événement reçu matche le filtre de la règle</li>
<li>par exemple, à la réception d'un événement <code>declareticket</code>, on peut lancer l'exécution d'un job réalisant une requête d'insertion de ticket à un outil tiers</li>
</ul><h2 id="conclusion">Conclusion</h2>
<p>Grâce à tout ces éléments, Canopsis est en mesure de répondre à de nombreux besoins, allant de la supervision simple, à l'analyse poussée de données afin de générer des rapports sur une infrastructure (ou autre).</p>
<p>Notre objectif premier est la modularité du projet, afin de pouvoir fournir une solution sur mesure et de ne pas transformer l'outil en énorme usine à gaz. Pour résumer, on a répondu à cette problématique avec :</p>
<ul>
<li>le découpage du <em>backend</em> en projets Python embarquant : un <em>manager</em>, éventuellement un moteur et un <em>webservice</em>
</li>
<li>le découpage du <em>frontend</em> en briques embarquant : des composants, des <em>renderers</em>, des <em>éditeurs</em>, des <em>mixins</em>, des <em>widgets</em>
</li>
<li>la schématisation des données et à l'avenir des actions possibles sur cette dernière (transformation, schématisation de l'API des <em>managers</em>, …)</li>
<li>le développement d'API générique permettant le changement de technologies sans modification du code</li>
</ul><p>Beaucoup de choses ont été faites, et beaucoup de travail reste à faire, notamment :</p>
<ul>
<li>la finalisation des rôles <strong>Ansible</strong>
</li>
<li>l'intégration d'une notion de graphe pour les entités qui sont le centre de toutes les données stockées par Canopsis, afin de rendre le système complètement réflexif</li>
<li>une séparation totale du <em>backend</em> et du <em>frontend</em>, permettant d'utiliser l'un sans l'autre</li>
<li>génération de code à partir des schémas</li>
<li>…</li>
</ul><p>Bref, Canopsis est en constante évolution, et touche à de nombreuses problématiques toutes plus intéressantes les unes que les autres.</p></div><div><a href="https://linuxfr.org/news/presentation-technique-de-canopsis.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/108104/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/presentation-technique-de-canopsis#comments">ouvrir dans le navigateur</a>
</p>
David DelassusBenoît SibaudNÿcopalm123claudexbubar🦥https://linuxfr.org/nodes/108104/comments.atomtag:linuxfr.org,2005:News/367632015-10-13T11:58:03+02:002015-10-13T11:58:03+02:00EyesOfNetwork 4.2 est sortiLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Pour ceux qui ne connaîtraient pas encore EyesOfNetwork (« EON »), il s'agit d'une solution de supervision Open Source réunissant de manière pragmatique les processus <a href="https://fr.wikipedia.org/wiki/Information_Technology_Infrastructure_Library">ITIL</a>. Elle est basée sur plusieurs produits libres tels que Nagios, Nagvis, GLPI…</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7777772e657965736f666e6574776f726b2e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031352f30392f455945535f434d4a4e312e706e67/EYES_CMJN1.png" alt="EON, EyesOfNetwork" title="Source : https://www.eyesofnetwork.com/wp-content/uploads/2015/09/EYES_CMJN1.png"></p>
<p>EON est accessible via une interface web permettant à chaque acteur d'un Système d’Information de disposer des informations pertinentes pour son métier ; elle comprend une interface graphique de définition des processus métiers et des modules de génération de rapports de statistiques sur les incidents et de génération de graphiques de performances.</p>
<p>La version 4.2 renforce encore ce positionnement en offrant un nouveau module de simulation utilisateur. Ce module permet de définir, sur un poste de travail, des scénarios applicatifs, de les jouer à place de l'utilisateur afin d'obtenir une disponibilité encore plus précise des applications métiers, et donner au DSI une vision encore plus fine de son Système d'Information.</p></div><ul><li>lien nᵒ 1 : <a title="https://www.eyesofnetwork.com/?lang=fr" hreflang="fr" href="https://linuxfr.org/redirect/95213">Site web</a></li><li>lien nᵒ 2 : <a title="https://forum.eyesofnetwork.com/" hreflang="fr" href="https://linuxfr.org/redirect/95214">Forum</a></li><li>lien nᵒ 3 : <a title="https://www.eyesofnetwork.com/?page_id=48&lang=fr" hreflang="fr" href="https://linuxfr.org/redirect/95215">Téléchargement</a></li></ul><div><h2 id="extrait-des-notes-de-publication-de-la-version-42">Extrait des notes de publication de la version 4.2</h2>
<h3 id="nouveautés">Nouveautés</h3>
<ul>
<li>Eon4apps 2.0</li>
<li>Recherche Eonweb basée sur thruk (tous les objets & multi backend livestatus )</li>
<li>Dépôts yum locaux pré configurés (base, updates & extras)</li>
<li>Mysqli dans eonweb</li>
<li>…</li>
</ul><h3 id="mises-à-jour">Mises à jour</h3>
<ul>
<li>Nagios-plugins 2.1.1</li>
<li>Nagvis 1.8.5</li>
<li>Thruk 1.88-4</li>
<li>…</li>
</ul><h3 id="greffons">Greffons</h3>
<ul>
<li>Check_mssql_health</li>
<li>Check_mysql_health</li>
<li>Check_emc_clariion</li>
<li>Check_ilo_health</li>
<li>Check_oracle_health</li>
<li>Check_vmware_esx</li>
<li>Windows : check_backupexec.vbs, tina_catalog_status.bat …</li>
<li>…</li>
</ul><h3 id="correctifs">Correctifs</h3>
<ul>
<li>Check_snmp_storage.pl >2T</li>
<li>Check_snmp_uptime.pl non basé exclusivement sur le service SNMP</li>
<li>Eonweb meta IE10</li>
<li>Lilac xml importer avec dépendances de contacts/contactgroup</li>
<li>…</li>
</ul></div><div><a href="https://linuxfr.org/news/eyesofnetwork-4-2-est-sorti.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/106983/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/eyesofnetwork-4-2-est-sorti#comments">ouvrir dans le navigateur</a>
</p>
texeireBenoît SibaudclaudexNÿcoNils Ratusznikpalm123https://linuxfr.org/nodes/106983/comments.atomtag:linuxfr.org,2005:Post/357302015-08-21T10:47:43+02:002015-08-22T11:46:47+02:00[Zabbix]: problème de performance serveur<p>Bonjour,<br>
je sais qu'il y'a quelques gros fans zabbix qui trainent ici, je poste donc dans l'espoir que quelqu'un puisse m'orienter sur ma configuration.</p>
<p>Le contexte: 1 VM Ubuntu server 12.04 4 VCPU, 12GB ram, 80GB disk zabbix 2.2.8 + Mysql sur un autre serveur<br>
Concernant zabbix:</p>
<pre><code>*Number of hosts: 5472
*Number of items: 320402
*Number of triggers: 238018
*Number of users: 29
*Requiered server performance: 1228.98
</code></pre>
<p>Au niveau de la configuration du <strong>/etc/zabbix/zabbix_server.conf</strong> voici ce qui diffère de la configuration par défaut:</p>
<pre><code class="ini"><span class="na">NodeID</span><span class="o">=</span><span class="s">1</span>
<span class="na">LogFile</span><span class="o">=</span><span class="s">/var/log/zabbix/zabbix_server.log</span>
<span class="na">LogFileSize</span><span class="o">=</span><span class="s">0</span>
<span class="na">DebugLevel</span><span class="o">=</span><span class="s">3</span>
<span class="na">PidFile</span><span class="o">=</span><span class="s">/var/run/zabbix/zabbix_server.pid</span>
<span class="na">DBHost</span><span class="o">=</span><span class="s">zabbix-db-1</span>
<span class="na">DBName</span><span class="o">=</span><span class="s">zabbix</span>
<span class="na">DBUser</span><span class="o">=</span><span class="s">zabbix</span>
<span class="na">DBPassword</span><span class="o">=</span><span class="s">'password'</span>
<span class="na">DBSocket</span><span class="o">=</span><span class="s">/var/run/mysqld/mysqld.sock</span>
<span class="na">StartTrappers</span><span class="o">=</span><span class="s">50</span>
<span class="na">StartPingers</span><span class="o">=</span><span class="s">50</span>
<span class="na">HousekeepingFrequency</span><span class="o">=</span><span class="s">4</span>
<span class="na">CacheSize</span><span class="o">=</span><span class="s">256M</span>
<span class="na">TrendCacheSize</span><span class="o">=</span><span class="s">512M</span>
<span class="na">ValueCacheSize</span><span class="o">=</span><span class="s">512M</span>
<span class="na">AlertScriptsPath</span><span class="o">=</span><span class="s">/usr/lib/zabbix/alertscripts</span>
<span class="na">ExternalScripts</span><span class="o">=</span><span class="s">/usr/lib/zabbix/externalscripts</span>
<span class="na">FpingLocation</span><span class="o">=</span><span class="s">/usr/bin/fping</span>
<span class="na">Fping6Location</span><span class="o">=</span><span class="s">/usr/bin/fping6</span>
<span class="na">LogSlowQueries</span><span class="o">=</span><span class="s">10000</span></code></pre>
<p>La supervision est passive, ce sont les agents de mes nodes qui renvoient leur valeurs (d'où le nombre de trapper)</p>
<p>En surveillant les graphs de performance du serveur, je me rends compte que toutes les heures j'ai le zabbix busy history syncer processes qui montent à 100% pendant quelques minutes, pendant cette période le serveur n'arrive plus à tracer les autres graphes de supervision du serveur zabbix.</p>
<p>Dans les logs du serveur je vois que ces pics correspondent à l'insertion de valeurs dans la table history_uint du style:</p>
<p><code>**slow query: 11.011690 sec, "insert into history_uint (blablabla)**</code></p>
<p>ou des queries en erreurs du style:</p>
<p><code>** [Z3005] query failed: [1205] Lock wait timeout exceeded; try restarting transaction [update ids set nextid=nextid+1 where nodeid=1 and table_name='items' and field_name='itemid']**</code></p>
<p>Avez vous une piste à me conseiller concernant ce qui peut être fait (conf zabbix ou mysql)?</p><div><a href="https://linuxfr.org/forums/linux-general/posts/zabbix-probleme-de-performance-serveur.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/106572/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/linux-general/posts/zabbix-probleme-de-performance-serveur#comments">ouvrir dans le navigateur</a>
</p>
jean_clumehttps://linuxfr.org/nodes/106572/comments.atom