Ember 1.2 / 1.3 : logs, plugins et une plateforme qui grandit avec vous
Publié le 28 avril 2026
Il y a quelques semaines, nous avons sorti Ember 1.1 et transformé un simple moniteur Caddy en quelque chose qui ressemblait davantage à un panneau de contrôle : un onglet Config, une vue Certificates, des graphiques waterfall, le support des sockets Unix. Les retours ont été excellents : issues, PRs, utilisateurs demandant « juste ce petit truc en plus ». Nous avons récemment dépassé les 150 téléchargements par jour, l'annonce sur Reddit a rencontré un beau succès et YoanDev a publié une vidéo YouTube pour montrer les capacités de l'app. Nous avons récolté plus de 300 étoiles sur GitHub. Merci à toutes les personnes qui soutiennent Ember !
Deux versions plus tard, Ember 1.2 et 1.3 répondent à ces demandes.

1.2, c'était voir plus de ce que Caddy fait déjà : des logs en direct diffusés jusque dans la TUI, un onglet Upstreams pour les reverse proxies, et des self-metrics pour que vous puissiez surveiller le moniteur. 1.3, c'est vous permettre d'étendre Ember vous-même : un système de plugins à la compilation, une séparation Runtime / Access dans le visualiseur de logs, et une image Docker officielle sur Docker Hub.
Cet article passe en revue les points forts des deux versions.
Logs en direct, directement dans la TUI
Avant 1.2, suivre les logs de Caddy voulait dire tail -f dans un autre terminal, ou rediriger un flux JSON à travers jq. Ember était très bon pour vous montrer ce qui se passait (RPS, latences, erreurs), mais pas pourquoi. Les logs étaient ailleurs.
Ember 1.2 introduit le streaming de logs en direct. Au démarrage, Ember ouvre un listener TCP en loopback, enregistre deux sinks dans Caddy via l'API admin, active la journalisation des accès sur tout serveur qui n'avait pas déjà un bloc logs, et commence à parser les entrées à la volée. Aucune modification du Caddyfile. Aucune manipulation JSON. Quand vous quittez, tout ce qu'Ember a touché est désenregistré et la configuration revient exactement là où elle était.

La table suit les entrées en direct par défaut, les codes de statut sont colorés, et / ouvre un filtre insensible à la casse qui se compose avec ce que vous êtes en train de regarder. Le défilement gèle automatiquement le buffer pour qu'une ligne en cours de lecture ne glisse pas sous vos yeux ; une pastille PAUSED indique combien de nouvelles lignes sont en attente en arrière-plan. Appuyez sur f pour reprendre.
Si Caddy n'est pas joignable au démarrage d'Ember, le listener reste ouvert et un watchdog réessaie toutes les 30 secondes jusqu'à ce que les sinks soient enregistrés. Le même watchdog gère caddy reload : les sinks sont ré-enregistrés automatiquement, donc le streaming reprend sans que vous ayez à faire quoi que ce soit. Sur un Caddy distant ou dans Docker, passez --log-listen <addr> (ou définissez EMBER_LOG_LISTEN) pour que Caddy ait une adresse joignable à laquelle pousser.
Runtime et Access, côte à côte
Faire passer chaque ligne dans une seule table fonctionne, jusqu'à ce que votre trafic d'accès noie la poignée d'événements runtime qui comptent vraiment : un handshake TLS raté, une erreur de module, un appel à l'API admin. Ember 1.3 les sépare proprement.
L'onglet Logs dispose maintenant d'un sidepanel à gauche avec deux portées : Runtime (démarrage, rechargements, TLS, API admin, logs des plugins) et Access (requêtes HTTP). Les deux flux vivent dans des ring buffers en mémoire séparés, 10 000 entrées chacun, pour qu'un serveur web chargé ne puisse pas évincer de rares erreurs runtime. Sous Access, Ember liste les hôtes qu'il a effectivement vus dans le trafic récent ; en sélectionner un restreint la table à cet hôte et supprime la colonne Host pour laisser plus de place aux URI.

La vue Runtime a son propre jeu de colonnes : Time, Level, Logger, Message. La sévérité est colorée (rouge pour ERROR/FATAL, orange pour WARN), mais comme Ember doit rester utilisable sous NO_COLOR, la sévérité a aussi un préfixe textuel : ! pour ERROR, * pour WARN, pour que le signal survive même sans couleur.
Depuis l'onglet Caddy, appuyez sur l sur n'importe quel hôte pour sauter directement à l'onglet Logs pré-filtré sur les accès de cet hôte. Ce trajet « j'ai vu un 500 dans la table, montre-moi la ligne de log » tient maintenant en une seule touche.
L'onglet Upstreams
Ember montrait déjà le trafic par hôte. Ce qu'il ne montrait pas, c'était l'autre côté du reverse proxy : les upstreams eux-mêmes. 1.2 ajoute un onglet Upstreams dédié qui apparaît automatiquement dès que Caddy expose caddy_reverse_proxy_upstreams_healthy, ce qui arrive dès qu'au moins un handler reverse_proxy est configuré.

Les health checks et les politiques de load balancing sont extraits de la configuration Caddy en direct, pas devinés. Un suffixe ! sur le statut signifie que l'état vient de basculer depuis le dernier poll, donc un backend instable ressort visuellement sans que vous ayez à fixer la table. Triez avec s/S, filtrez avec /, rafraîchissez les colonnes issues de la config avec r.
Surveiller le surveillant : les self-metrics d'Ember
Si Ember est intégré à votre stack d'observabilité, il faut qu'il vous prévienne quand lui est en difficulté. 1.2 ajoute des self-metrics Ember qui apparaissent sur /metrics dès que --expose est défini, à côté des métriques Caddy et FrankenPHP que vous scrapez déjà :
ember_build_info: constante à1, avec les labelsversionetgoversion.ember_scrape_total/ember_scrape_errors_total: compteurs par étape de sous-fetch (threads,metrics,process).ember_scrape_duration_seconds: latence du dernier scrape par étape.ember_last_successful_scrape_timestamp_seconds: date du dernier succès pour chaque étape.
Ce qui veut dire que vous pouvez enfin alerter sur ce qui compte :
rate(ember_scrape_errors_total[5m]) > 0
time() - ember_last_successful_scrape_timestamp_seconds{stage="metrics"} > 60
ember_scrape_duration_seconds{stage="metrics"} > 1Ember n'est plus une boîte noire dans votre Prometheus.
Un système de plugins pour vos propres modules Caddy
L'écosystème Caddy est énorme : rate limiters, WAFs, caches, modules d'auth, middlewares personnalisés. Ember ne peut pas avoir un onglet pour chacun d'eux. Alors 1.3 vous confie ce travail, de la façon la plus agréable possible.
Ember 1.3 embarque un système de plugins à la compilation. Les plugins suivent exactement le même modèle que les modules Caddy : blank imports plus enregistrement dans init(). Vous les déposez dans un petit main.go qui appelle ember.Run(), go build, et vous obtenez un binaire Ember personnalisé avec les onglets en plus, les métriques Prometheus en plus, ou les deux.
package main
import (
"fmt"
"os"
"github.com/alexandre-daubois/ember"
_ "github.com/example/ember-ratelimit"
_ "github.com/example/ember-cache"
)
func main() {
if err := ember.Run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}Un plugin implémente une surface minimale : Name, Provision, Fetch, puis choisit ce qu'il veut faire des données : afficher un onglet TUI (Update, View, HandleKey), écrire des métriques Prometheus (WriteMetrics), ou les deux. La configuration vient de l'environnement : EMBER_PLUGIN_RATELIMIT_MAX_RPS=1000 atterrit dans PluginConfig.Options["max_rps"]. Ember enveloppe chaque appel avec une récupération de panic, donc un plugin cassé affiche « plugin error: ... » dans son onglet au lieu d'entraîner toute la TUI avec lui.
Les plugins export-only, Fetcher + Exporter, sans Renderer, collectent des données et les ajoutent à /metrics sans toucher à l'interface. Parfait pour alimenter un tableau Grafana sans encombrer le terminal.
L'API des plugins est étiquetée experimental volontairement : les interfaces peuvent encore bouger à mesure que nous apprenons ce que les gens construisent réellement avec. Si une interface vous paraît maladroite ou n'expose pas quelque chose dont vous avez besoin, ouvrez une issue : l'API grandira pour correspondre aux cas d'usage réels.
Ember sur Docker Hub
Jusqu'à la 1.2, l'image conteneur ne vivait que sur ghcr.io. Beaucoup d'utilisateurs ont demandé un miroir sur Docker Hub, donc 1.3 publie les deux :
alexandredaubois/emberghcr.io/alexandre-daubois/ember
Même image, même contenu, choisissez le registre préféré de votre plateforme. L'image est toujours construite FROM scratch (binaire statique et certificats CA, pas d'OS, pas de shell) et toujours avec --daemon --expose :9191 par défaut, donc vous pouvez la déposer comme sidecar sans rien surcharger :
docker run --rm --network host alexandredaubois/emberAu-delà des fonctionnalités phares
Beaucoup de changements plus discrets ont atterri à travers 1.2 et 1.3 :
- Raccourci
ipour le flag interval :ember -i 2sau lieu deember --interval 2s. - Fil d'Ariane dans le panneau de détail d'hôte : vous savez toujours quel hôte vous inspectez.
- Style des onglets rafraîchi et meilleure gestion des hauteurs de table de manière générale.
- Détection plus fine du reset du compteur de workers FrankenPHP, indépendante des resets propres à Caddy.
- Correction d'une race sur le fetcher HTTP pendant un rechargement TLS (
SIGHUP) : plus de petits trous dans le scrape à la rotation des certificats. - Validation au démarrage : les valeurs
--metrics-prefixinvalides, ou un--timeoutplus court que--interval, sont maintenant rejetés au démarrage plutôt que de produire des scrapes cassés. - Correction des percentiles : nous ne renvoyons plus les comptes cumulés de l'histogramme en guise de percentiles quand il n'y a pas encore de snapshot de référence.
- P90 dans la sortie JSON streaming et dans le chemin de repli du tracker.
- Onglet FrankenPHP toujours en deuxième position quand il est détecté, pour que votre carte mentale de la barre d'onglets reste stable.
Un mot sur la [BC BREAK] en 1.2
Un nettoyage de métriques mérite d'être mentionné. Ember 1.2 arrête de dupliquer une poignée de métriques Caddy que Caddy expose déjà sur son propre endpoint /metrics. Si vous scrapiez les deux, vous aviez des doublons ; si vous ne scrapiez qu'Ember, vous lisiez peut-être des valeurs reformées par Ember au lieu des valeurs canoniques de Caddy. 1.2 traite Caddy comme la source de vérité pour tout ce que Caddy expose déjà, et le /metrics d'Ember n'ajoute plus désormais que de la valeur par-dessus. Si vous dépendiez d'une copie côté Ember de l'une de ces métriques, pointez votre dashboard directement sur l'endpoint Caddy.
Profitez de Ember 1.3 aujourd'hui !
Homebrew:
brew upgrade emberAvec go install:
go install github.com/alexandre-daubois/ember/cmd/ember@latestOne-liner:
curl -fsSL https://raw.githubusercontent.com/alexandre-daubois/ember/main/install.sh | shEt bien sûr Docker:
docker pull alexandredaubois/ember
# or
docker pull ghcr.io/alexandre-daubois/emberLe code source est sur github.com/alexandre-daubois/ember. Issues, PRs et idées de plugins sont tous les bienvenus : l'API de plugins de la 1.3 en particulier évoluera en fonction de ce que vous essayerez d'en faire !



