Files
SentinelMesh/doc_brainstorming/deep-research-report(4).md
T
2026-05-19 06:39:32 +02:00

22 KiB
Raw Blame History

Dossier technique pour le deuxième widget Glance de monitoring dagents Rust

Conclusion opérationnelle

Oui, ton deuxième widget est réalisable, et il est même cohérent avec larchitecture de Glance à condition de le traiter comme une application externe intégrée dans Glance, pas comme un widget natif compilé “dans” Glance en Rust. Le dépôt principal de Glance est un projet Go avec un go.mod, et sa mécanique de widgets personnalisés repose aujourdhui sur quatre portes dentrée documentées par le projet lui-même : iframe, html, extension et custom-api. Glance précise aussi que les pages ne se mettent pas à jour automatiquement en arrière-plan et quun rechargement de page est normalement nécessaire pour récupérer les nouvelles données. Pour ton besoin — tuiles live, popup latéral, auto-découverte, installation dagent, mise à jour, métriques à fréquences différentes et états de veille/arrêt/actif — loption la plus robuste est donc : backend Rust + petite UI web servie par ce backend + intégration dans Glance via iframe. citeturn36view0turn33view1turn35view0turn34view0

Il y a aussi une nuance importante de vocabulaire : le projet étudié ici est Glance, pas Glances. La documentation de Glance dit dailleurs explicitement que le widget server-stats est encore “under development”, quil peut sappuyer sur le Glance Agent pour des serveurs distants, et que le support dautres providers “such as Glances” viendra plus tard. Autrement dit, ton besoin avancé dépasse clairement ce que le widget natif server-stats couvre aujourdhui. citeturn3view0

Mon verdict est donc simple : oui pour Rust, mais en service externe consommé par Glance, pas comme module interne du binaire Go de Glance. Si tu veux un rendu vraiment vivant et administrable, je te recommande de bâtir un petit produit séparé, par exemple fleet-collector et fleet-agent, puis de lafficher dans une page Glance dédiée. Cette approche servira dailleurs très bien ton premier widget IP réseau et ton deuxième widget agents avec un même modèle dinventaire. citeturn33view1turn34view0turn31view0turn35view0

Ce que Glance permet réellement pour ce besoin

Glance organise linterface autour de pages et de colonnes. Une page peut jouer le rôle de “tab” au sens fonctionnel, avec un layout wide et des colonnes full ou small. Si tu veux réserver un onglet complet à ton monitoring, Glance le permet nativement côté configuration, sans toucher au code source du projet. citeturn3view0

Pour ton cas, les trois mécanismes utiles sont les suivants. Dabord, custom-api sait appeler une API JSON avec GET, POST, PUT, PATCH, DELETE, gérer des headers, un body, des subrequests, puis rendre le résultat avec un template basé sur Go html/template et gjson. Cest puissant pour des widgets “server-rendered” relativement riches, mais la doc de Glance dit aussi explicitement que ce mode demande des notions de programmation, HTML, CSS et templates Go. Ensuite, extension est un protocole HTTP simple où un service externe renvoie du HTML et quelques headers spécifiques ; Glance documente néanmoins que cette API est work in progress, que le cache par défaut dune extension est de 30 minutes, quil est configurable, et que le seul type de contenu supporté actuellement est html. Enfin, iframe embarque simplement une application externe à partir dune URL et dune hauteur donnée. Pour un écran de supervision avec popups, tuiles dynamiques, tri intelligent, interaction fine et mises à jour live, iframe est de loin la meilleure option. citeturn35view0turn31view0turn34view0turn33view1

La principale raison est le modèle dactualisation de Glance. Le README officiel dit que les widgets ne font pas de requêtes périodiques en arrière-plan et que les données sont récupérées au chargement puis mises en cache ; il faut normalement recharger la page pour voir les changements. Il existe bien une pull request ouverte ajoutant des “live-events” avec polling serveur toutes les 15 secondes et SSE pour monitor et custom-api, mais elle est encore ouverte au 19 mai 2026 et nappartient donc pas au comportement stable documenté du main actuel. Ton besoin de CPU/RAM à 1 seconde ne doit pas dépendre dune PR non mergée. citeturn33view1turn33view0

Glance reste toutefois très bon comme conteneur, car tu peux lui faire servir des assets via assets-path, injecter du HTML dans le <head> avec document.head, ajouter un custom-css-file, et cibler les widgets par widget-type-* ou css-class. Autrement dit, même si le vrai widget vit dans un service Rust séparé, tu peux le “fondre” visuellement dans lunivers Glance. citeturn32view0turn32view1turn32view2turn32view3

Un squelette de configuration Glance pour ce deuxième widget ressemblerait à ceci :

pages:
  - name: Infrastructure
    width: wide
    columns:
      - size: full
        widgets:
          - type: iframe
            title: Fleet Monitor
            source: https://dash.example.net/widgets/agents
            height: 820
            css-class: fleet-monitor

Si tu veux garder un mode “dégradé” purement Glance, tu peux aussi fournir un petit widget custom-api qui naffiche quun résumé global : nombre dagents, nombre offline, charge CPU moyenne, machines en alerte, lien dinstallation et lien “ouvrir la vue détaillée”. Mais la vue principale riche doit rester dans liframe. citeturn35view0turn34view0turn32view3

Architecture recommandée pour le widget agents

Je te recommande une architecture en trois briques. Première brique : un fleet-agent Rust installé sur chaque VM ou machine physique. Deuxième brique : un fleet-collector Rust central qui reçoit les enregistrements, stocke linventaire, expose une API et un flux temps réel. Troisième brique : une UI web légère, servie par le collector, affichée dans Glance via iframe. Cette séparation colle au modèle de Glance, contourne proprement labsence dauto-refresh généralisé, et te laisse toute latitude pour le placement intelligent des tuiles, les popups, les liens personnalisés et les workflows dinstallation/mise à jour. citeturn33view1turn34view0turn35view0turn31view0

[ VM / Bare metal ]
    └─ fleet-agent (Rust)
       ├─ collecte CPU / RAM / disque / process
       ├─ inventaire matériel
       ├─ écoute veille / reboot / shutdown
       └─ push JSON vers collector

[ Serveur central ]
    └─ fleet-collector (Rust)
       ├─ API denregistrement des agents
       ├─ stockage inventaire + séries courtes
       ├─ stream SSE / WebSocket pour lUI
       ├─ génération commandes install / update
       └─ UI web du widget

[ Glance ]
    └─ page "Infrastructure"
       └─ widget iframe -> UI du collector

Je te conseille un modèle push depuis les agents vers le collector, parce que ton cahier des charges inclut des événements qui se prêtent mal à un modèle purement pull : arrêt propre, passage en veille, reprise, changement d’état, heartbeat, auto-enregistrement au boot, et publication de métriques avec des fréquences hétérogènes. Comme Glance nest pas un moteur de polling continu des widgets, et comme server-stats est encore explicitement en développement, vouloir faire ça directement “dans Glance” te mettrait rapidement à contre-courant du produit. citeturn33view1turn3view0

La bonne granularité, à mon sens, est la suivante. Inventaire statique au démarrage puis deux fois par jour : hostname, OS, carte mère, modèle, vendor, serial, interfaces réseau, icône, emplacement, groupe, parent, liens. Métriques rapides toutes les 1 à 5 secondes : CPU, RAM, état de disponibilité, éventuellement charge GPU si la machine en a une. Métriques lentes toutes les 30 minutes : capacité disque, occupation des volumes, état SMART synthétique. Événements à la volée : démarrage, arrêt, veille, reprise, changement dIP, agent obsolète, échec dun module. Cette séparation colle bien aux capacités des APIs système disponibles et évite de transmettre trop de bruit. citeturn22view0turn24search7turn8search0turn8search4turn12search0turn11search0turn10search0turn30search6

Pour le volet secondaire de tes tuiles, je te conseille de ne pas tout remonter à 1 seconde. Les données de popup — SMBIOS/DMI, services, icône, emplacement, relations de parenté, liste des top processus, état détaillé des disques — peuvent être stockées côté collector et réactualisées plus lentement, voire à la demande. Les docs de sysinfo montrent explicitement que le CPU sappuie sur des différences temporelles, quil faut garder une même instance System, et quil vaut mieux utiliser des refresh ciblés pour les performances. Cette philosophie va exactement dans le sens de ton besoin “fréquences différentes selon les familles de données”. citeturn22view0turn26view0

Stack Rust recommandée

Pour le runtime et lAPI réseau, la combinaison la plus naturelle est Tokio + Axum. Tokio est le runtime asynchrone standard de fait pour les applications réseau Rust ; sa primitive interval est adaptée à des boucles planifiées de collecte. Axum est conçu pour fonctionner avec Tokio et Hyper, sait gérer des APIs HTTP, les WebSockets, et fournit nativement des réponses SSE. Pour ton widget, SSE suffit souvent très bien : le collector pousse les changements de tuiles, et lUI met à jour la grille sans refresh. citeturn16search22turn20search2turn20search5turn16search2turn20search0turn20search4

Pour la collecte système générale, je recommande sysinfo comme base. La doc officielle montre que la crate couvre processus, mémoire, CPU, disques, réseaux, températures de composants, et quelle dispose de RefreshKind, ProcessRefreshKind, DiskRefreshKind, ainsi que dun MINIMUM_CPU_UPDATE_INTERVAL. Elle expose aussi des informations de carte mère, par exemple nom, vendor, version, numéro de série et asset tag via Motherboard. Pour les top processus, elle fournit notamment cpu_usage(), memory(), status(), parent(), exe() et cmd(). Cest une excellente base pour un agent Rust Linux-first. citeturn22view0turn25view0turn25view1turn26view0turn26view1

Pour le matériel et les identifiants, tu as deux étages. Dabord sysinfo, qui sait remonter une partie de linventaire matériel. Ensuite, pour les informations plus complètes ou plus “admin” — SMBIOS/DMI, châssis, BIOS, vendor, références — tu peux compléter avec dmidecode ou directement les fichiers sysfs. La doc de dmidecode rappelle toutefois que ces informations viennent du firmware SMBIOS/DMI et peuvent être rapides et sûres à lire mais parfois peu fiables, car elles dépendent de ce que le firmware expose. Cest important pour ton design : il faut afficher ces champs comme de linventaire déclaratif, pas comme une vérité absolue. citeturn25view0turn9search12turn9search6

Pour les disques, je te conseille de séparer “occupation des volumes” et “santé physique”. Loccupation se fait très bien avec sysinfo::Disks. La santé disque et les attributs SMART doivent venir de smartctl, car la documentation officielle indique que smartctl contrôle et surveille le système SMART des disques ATA/SATA, SCSI/SAS et SSD, et son code source expose un mode --json/-j pour une sortie JSON ou YAML. Cest le meilleur compromis Rust aujourdhui : exécuter smartctl, parser le JSON, et normaliser un petit résumé par disque pour ton popup ou tes alertes. citeturn24search7turn8search0turn8search4

Pour les GPU, je te recommande un design par provider optionnel. Côté NVIDIA, la référence est clairement NVML ; NVIDIA documente NVML comme une API C de monitoring et management des GPU, thread-safe, et base de nvidia-smi. En Rust, nvml-wrapper permet dy accéder proprement. Côté AMD, la doc ROCm indique que AMD SMI est linterface unifiée vers laquelle AMD pousse désormais les usages de monitoring/management GPU et quelle est la successeure de ROCm SMI. Traduction pratique : phase 1 NVIDIA si tu veux aller vite, phase 2 AMD SMI si ton parc le justifie. citeturn10search0turn10search1turn6search4turn30search1turn30search6

Pour la base de données centrale, tu as deux bons choix. Si ton parc reste modeste et si tu veux un déploiement très simple, SQLite en WAL est parfaitement défendable avec un collector unique et un modèle “une écriture logique à la fois”. La doc SQLite rappelle comment activer WAL et souligne que ce mode permet, en règle générale, que les écrivains ne bloquent pas les lecteurs et inversement, tout en expliquant le rôle des checkpoints. En revanche, la doc SQLite signale aussi un bug rare WAL-reset corrigé en 3.51.3 le 13 mars 2026, ainsi que dans certains backports. Donc si tu pars sur SQLite/WAL, veille à utiliser une version corrigée. Si tu veux monter en charge, multi-utilisateur, ou faire de la rétention longue avec analytics, PostgreSQL devient plus confortable. Côté Rust, SQLx est adapté aux deux mondes : crate async, support Tokio, support SQLite/PostgreSQL, requêtes vérifiables à la compilation. citeturn27view0turn19search0turn19search1

Pour les mises à jour de lagent, deux options sont sérieuses. Soit tu fais du self-update in-place avec une crate dédiée ; la doc de self_update précise quelle sait mettre à jour des exécutables Rust en place à partir de plusieurs backends de distribution. Soit, ce que je préfère dans ton contexte, tu gardes un installeur shell et des binaires versionnés, ce qui te donne un chemin dupgrade plus transparent, plus compatible avec systemd et plus facile à signer/vérifier. Pour la signature, Minisign est une option légère et robuste, officiellement documentée comme un outil simple de signature/vérification basé sur Ed25519. citeturn16search1turn17search0

Déploiement, découverte et mises à jour

Pour la distribution des artefacts, Gitea est suffisant. La documentation officielle du Generic Package Registry explique quil peut publier des fichiers génériques comme des binaires de release, via PUT, et les télécharger via GET sur des URLs versionnées. Gitea documente aussi lauthentification API par Basic auth, query token, ou surtout Authorization: token .... Concrètement, tu peux stocker dans Gitea : le binaire par plateforme, le fichier .minisig, un manifest.json, et le install.sh. citeturn28view0turn28view2

Dans ce modèle, ton widget central peut générer la commande dinstallation exactement dans lesprit que tu veux, par exemple :

curl -fsSL https://git.example.net/api/packages/infra/generic/fleet-agent/1.2.0/install.sh \
  | bash -s -- \
    --collector https://collector.example.net \
    --token AGENT_REG_TOKEN \
    --group vm \
    --icon server \
    --link https://proxmox.example.net

Je te conseille toutefois que ce script ne télécharge pas directement un binaire non vérifié : il doit récupérer le manifest, télécharger lartefact pour lOS/arch courants, vérifier la signature Minisign, installer le binaire, créer lunité systemd et démarrer le service. Cest plus sûr que le simple curl | bash aveugle, tout en restant simple à opérer. citeturn28view0turn17search0

Pour lauto-découverte, je te recommande de faire de la self-registration dabord, et du mDNS/DNS-SD seulement en option locale. Les RFC IETF disent clairement que mDNS fonctionne sur le local link en absence de DNS conventionnel, et que DNS-SD sert à découvrir les instances dun service à partir de son type. Cela veut dire que mDNS est pratique sur un LAN plat, mais pas un mécanisme principal pour des segments séparés, des VLANs ou des routes plus complexes. En outre, les travaux IETF sur la privacy de DNS-SD rappellent que la découverte de services divulgue typiquement des noms dhôtes et des paramètres réseau. En pratique : annonce mDNS facultative pour le confort local, enregistrement explicite au collector pour le vrai fonctionnement. citeturn14search3turn14search1turn14search7

Pour la détection des états système, le plus propre est de mélanger hooks systemd et écoute D-Bus. La documentation systemd indique que ExecStop= et ExecStopPost= sexécutent lors dune opération darrêt/restart du service, ce qui te donne un bon point de sortie “propre” pour publier un dernier événement. En parallèle, linterface org.freedesktop.login1 documente les signaux PrepareForShutdown() et PrepareForSleep() envoyés juste avant et juste après extinction/suspend, avec un booléen indiquant lentrée ou la sortie de l’état. Cest exactement ce quil te faut pour les états “veille”, “arrêt”, “actif”. citeturn11search0turn12search0

Enfin, pour la mise à jour par mini-modules, le collector peut exposer une notion de “catalogue de modules” par agent : par exemple smart, gpu-nvidia, gpu-amd, services-extra, netinfo-advanced. Le widget na pas besoin dexécuter lui-même le code distant ; il peut afficher la commande exacte à lancer, ou bien lagent peut poller un manifest signé et proposer/appliquer lupdate localement selon une politique. Cette seconde approche est plus sûre et plus industrialisable si tu comptes dépasser quelques machines. citeturn28view0turn16search1turn17search0

Plan de réalisation recommandé

Je te recommande un MVP Linux-first en trois étapes. Étape une : collector Rust + UI iframe + agent Rust qui remonte en push lenregistrement, le heartbeat, CPU, RAM, volumes, état de base, et un top 5 processus rafraîchi toutes les 10 à 15 secondes. Tu obtiens déjà les tuiles, l’état online/offline, les popups secondaires et la génération de commandes dinstallation. Cette première étape sappuie presque entièrement sur tokio, axum, sysinfo, systemd et la mécanique Glance iframe. citeturn20search2turn16search2turn22view0turn26view0turn34view0

Étape deux : enrichissement matériel. Tu ajoutes DMI/SMBIOS, cartes réseau, disques SMART, capteurs/temperatures disponibles, et éventuellement données GPU NVIDIA. Cette couche est surtout utile pour ton volet latéral “hardware, icon, services, lien, emplacement, parent”. Cest aussi l’étape où tu peux stabiliser ton modèle dinventaire pour quil serve en commun ton premier widget “cartographie IP réseau” et ton deuxième widget “agents”. citeturn25view0turn9search12turn8search0turn10search0

Étape trois : exploitation avancée. Tu ajoutes auto-discovery optionnelle, agent modules, politiques dupdate, AMD SMI si nécessaire, et éventuellement une petite vue Glance custom-api de synthèse pour les KPIs globaux. À ce stade, Glance reste le portail, mais la logique métier vit clairement dans ton service Rust, ce qui est précisément ce que larchitecture de Glance favorise déjà avec iframe, extension et custom-api. citeturn35view0turn31view0turn34view0

Limites et points ouverts

La principale limite technique est que ton besoin est beaucoup plus proche dun mini-produit de fleet monitoring que dun simple widget statique. Ce nest pas un défaut de Glance ; cest juste que Glance documente aujourdhui un modèle de données principalement fetch-on-load + cache, avec des extensions HTML et des custom APIs orientées rendu, et non un framework de widgets riches temps réel comparable à une SPA supervisée par un bus d’événements. Lexistence dune PR SSE non mergée va dans ce sens : le besoin de live updates existe, mais il nest pas encore un socle stable du projet. citeturn33view1turn33view0turn31view0turn35view0

Le deuxième point ouvert est le périmètre OS. La stack que je te propose est excellente pour un parc Linux / VMs / bare metal sous systemd, parce quelle repose sur smartctl, login1/systemd, SMBIOS/DMI, NVML/AMD SMI et sysinfo. Si tu veux couvrir sérieusement Windows, BSD ou macOS avec le même niveau de détails matériels et d’événements système, il faudra des providers spécifiques ou un niveau de service un peu moins riche. sysinfo est multi-OS, mais tout ce qui touche au shutdown propre, à SMART, à SMBIOS détaillé et à la télémétrie GPU dépend fortement de lOS et du vendor. citeturn22view0turn9search12turn8search0turn12search0turn10search0turn30search6

Le troisième point ouvert est la taille de parc visée. Si tu parles de quelques dizaines de machines, SQLite en WAL avec un collector unique, un cache mémoire court et des agrégats récents est probablement suffisant. Si tu parles de centaines de nœuds, dhistoriques longs ou de multiples utilisateurs simultanés du dashboard, je partirais plus vite sur PostgreSQL et un découplage plus net entre ingestion temps réel et UI. Et si tu restes sur SQLite, je te recommande explicitement de vérifier la version déployée au regard des correctifs WAL mentionnés par la documentation SQLite de mars 2026. citeturn27view0turn19search1

En synthèse finale : oui, tu peux ajouter ce widget avec du Rust ; non, je ne te recommande pas de vouloir lajouter “dans Glance” comme widget natif Rust ; oui, je te recommande fortement un service Rust externe affiché par iframe dans une page Glance, avec un agent Rust en push, un collector temps réel, un stockage léger, une distribution via Gitea, et une vérification de signature des binaires. Cest larchitecture la plus propre, la plus maintenable, et la plus fidèle à la manière dont Glance expose aujourdhui ses points dextension. citeturn36view0turn35view0turn34view0turn31view0turn33view1