From fd1c0a2698c77eec59156bb47a5ef049f7de1535 Mon Sep 17 00:00:00 2001 From: Cedric Date: Fri, 2 Oct 2026 11:29:21 +0200 Subject: [PATCH] README in French README.fr.md is a full French translation of README.md (same sections, code blocks and commands unchanged, same image and links). Each README starts with a link to the other language. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.fr.md | 320 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 322 insertions(+) create mode 100644 README.fr.md diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..066cd45 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,320 @@ +[English](README.md) | Français + +# Logstream + +Un collecteur syslog simple : il reçoit les logs en UDP/TCP sur le port 514, les stocke dans +[VictoriaLogs](https://docs.victoriametrics.com/victorialogs/) et sert une interface web +soignée (thème clair/sombre, recherche instantanée, direct, tags de couleur, interface en +anglais et en français). + +``` +devices ──514 udp/tcp──▶ logstream (Go) ──HTTP batches──▶ VictoriaLogs + ▲ └── SSE (live) ──▶ browser + └──── API / UI ◀─────────┘ +``` + +## Architecture + +![Schéma logique de Logstream](docs/architecture.png) + +- **Ingestion** : les messages syslog (UDP/TCP) et les logs des conteneurs Docker passent tous + par `sink()` (résolution DNS inverse des hôtes donnés par leur IP), puis par la file du + `Store`, qui les envoie par lots à VictoriaLogs. +- **Direct** : `sink()` publie aussi chaque message dans le `Hub`, qui le diffuse aux + navigateurs en SSE. +- **Recherche** : l'API HTTP traduit les filtres de l'interface en requêtes LogsQL envoyées à + VictoriaLogs. +- **Frise** : `/api/histogram` (`histogram.go`) compte les logs par intervalle et par sévérité, + alignés sur l'heure locale ; les bornes du zoom (`from`/`to`) s'appliquent aussi à la liste + et à l'export. +- **État** : les tags et les réglages des sources sont dans `/data` (volume `logstream-data`) ; + les logs eux-mêmes dans le volume `vlogs-data`. + +La source modifiable du schéma est +[`docs/architecture.excalidraw`](docs/architecture.excalidraw) +(à ouvrir sur [excalidraw.com](https://excalidraw.com)). + +## Démarrage + +```bash +cp .env.example .env # optional +docker compose up -d --build +./tools/send-test-logs.sh # sends 100 test messages +``` + +Ouvrez ensuite . + +## Envoyer des logs + +- **rsyslog** (Linux) : ajoutez `*.* @SERVER_IP:514` (UDP) ou `*.* @@SERVER_IP:514` (TCP) + dans `/etc/rsyslog.d/90-logstream.conf`, puis lancez `systemctl restart rsyslog`. +- **Équipements réseau, NAS, pare-feu** : indiquez l'IP du serveur et le port 514 dans leurs + réglages « syslog distant » (remote syslog). +- **Test manuel** : `logger -n 127.0.0.1 -P 514 -d "hello error"` (util-linux) ou + `echo "<14>test ok" | nc -u -w1 127.0.0.1 514`. + +**Paramètres > Sources > Syslog** active ou désactive la réception syslog et choisit les +protocoles (UDP, TCP) sans redémarrage ; le choix est enregistré dans `/data/syslog.json`. Cet +onglet affiche aussi l'état d'écoute (et l'erreur si le port est déjà utilisé). Le port +lui-même est publié par docker-compose : modifiez `SYSLOG_PORT` dans `.env`, puis lancez +`docker compose up -d`. + +Formats pris en charge : RFC 3164 (BSD) et RFC 5424. En TCP, les deux découpages sont acceptés : +« un message par ligne » et « octet counting » (RFC 6587). + +## Recherche + +**Mode simple** (par défaut) : chaque mot est cherché comme sous-chaîne, sans tenir compte de +la casse, dans le message, l'hôte et l'application. Les mots sont combinés avec ET. + +| Saisie | Signification | +|---|---| +| `error disk` | contient « error » **et** « disk » | +| `"disk full"` | contient la phrase exacte | +| `error -timeout` | contient « error » mais pas « timeout » | + +**Mode LogsQL** (bouton `Simple` / `LogsQL`) : le langage de requête complet de VictoriaLogs, +par exemple `error AND host:web-01`, `app:~"ssh|nginx"` ou `* | stats by (host) count()`. +Le direct est désactivé dans ce mode. + +Chaque ligne affiche, de gauche à droite : l'**heure de réception** (horloge du serveur), +l'horodatage trouvé dans le message lui-même (`msg_time`), la sévérité, l'hôte, l'application +et le message. Un clic sur un hôte ou une application filtre dessus. + +Les logs sont indexés, recherchés et triés par **heure de réception** : les équipements dont +l'horloge est fausse (par exemple des points d'accès dont le NTP échoue) apparaissent quand même +dans la bonne plage de temps. Les logs stockés par les versions antérieures à ce changement sont +indexés par l'horodatage de leur message ; purgez-les depuis les Paramètres pour repartir sur +une base propre. + +Les badges de sévérité `err`/`crit` et `warning` reprennent les couleurs des tags `error` et +`warning`. + +Raccourcis : `/` place le curseur dans la recherche, `Esc` la vide. Un clic sur une ligne +affiche tous ses champs. + +Les en-têtes de colonnes restent visibles pendant le défilement. Faites glisser le bord d'un +en-tête (réception, heure message, sévérité, hôte, app) pour redimensionner la colonne, et +double-cliquez dessus pour revenir à la largeur automatique ; le message occupe l'espace +restant. Les largeurs sont mémorisées par le navigateur (**Paramètres > Interface > +Réinitialiser les colonnes** les rétablit toutes). Sur téléphone, la liste garde sa +présentation sur deux lignes, sans colonnes. + +## Frise + +La frise au-dessus de la liste montre le volume de logs par intervalle, compté selon l'**heure +de réception** sur l'horloge du serveur (elle correspond donc aux heures affichées dans les +lignes). + +- Au survol d'un intervalle : ses bornes, son total et le détail par sévérité. +- Un clic sur une barre zoome sur cet intervalle ; un glisser sur plusieurs barres zoome sur la + sélection. La plage de temps affiche alors la période zoomée (« × Annuler le zoom » ou le + choix d'une autre plage en sort) ; la liste, les compteurs et l'export CSV suivent le zoom, + et le direct se met en pause. +- En direct, le dernier intervalle grandit à l'arrivée des messages, et la frise se recharge à + chaque nouvel intervalle. Rien n'est rafraîchi tant que l'onglet du navigateur est masqué ; + la frise se met à jour dès qu'il redevient visible. + +**Paramètres > Interface > Frise** (mémorisé par navigateur) : échelle (linéaire, √ par défaut, +log), hauteur (S/M/L : 40/80/120 px), couleur (empilement par sévérité, intensité comparée à +la médiane de la fenêtre : calme, rafale au-delà de 3×, anomalie au-delà de 10×, ou aucune), +barres ou aire, division (automatique, environ 100 intervalles, ou fixe : 1 s, 10 s, 1 min, +5 min, 1 h, 1 jour) et rafraîchissement (désactivé, 5 s, 15 s, 30 s, 1 min, ou à chaque nouvel +intervalle). Une division fixe qui dépasserait 300 intervalles sur la plage est élargie +(signalé par « élargi »). Les intervalles sont alignés sur l'heure locale du fuseau horaire +choisi dans les Paramètres (les jours commencent à minuit, heure locale). + +API : `curl 'localhost:8080/api/histogram?range=24h&step=auto&tz=Europe/Paris'` renvoie +`step` (ms), `start` (ms), `count`, `now` (horloge du serveur) et les `buckets` non vides +(`i` = numéro d'intervalle, `n` = total, `sev` = nombre par sévérité). Toutes les routes de +logs acceptent aussi `from` / `to` (millisecondes Unix) à la place de `range`. + +## Logs des conteneurs Docker + +Logstream collecte aussi les logs des conteneurs Docker qui tournent sur la machine où il est +installé (`DOCKER_LOGS=on`, le défaut dans `docker-compose.yml`). Ils sont recherchés, filtrés, +colorés et exportés comme les messages syslog : + +- **host** est le nom de l'hôte Docker, **app** le service compose (ou le nom du conteneur), et + chaque log porte aussi `container`, `container_id`, `image`, `compose_project`, + `compose_service` et `stream` (stdout/stderr), visibles dans le détail de la ligne. +- Le filtre **Source** n'affiche que les logs syslog ou que les logs Docker ; les lignes Docker + ont un petit cube devant le nom de l'application, de la couleur de son projet compose. +- La sévérité vient de la ligne elle-même quand l'application l'écrit : JSON + (`"level":"error"`), logfmt (`level=warn`), `[ERROR]`, ou un niveau en majuscules au début de + la ligne (`ERROR`, `WARN`…). Sinon, elle vaut `info`. Les codes de couleur du terminal sont + supprimés. +- **Paramètres > Sources** affiche une étiquette par conteneur (`project/service`) dans un seul + champ : les conteneurs suivis en couleur, puis les non suivis en gris ; un clic bascule une + étiquette. La couleur identifie le projet compose, et les noms d'applications Docker de la + liste utilisent la même couleur. Les conteneurs arrêtés sont masqués par défaut (« Afficher + les conteneurs arrêtés » les montre, en pointillés, et ils restent modifiables). Une zone de + filtre et « Tout activer » / « Tout désactiver » (appliqués aux étiquettes affichées) aident + quand les conteneurs sont nombreux. Les nouveaux conteneurs sont suivis automatiquement, sauf + si cette option est désactivée. Les choix sont enregistrés par service compose (ou nom de + conteneur) dans `/data/docker.json` : ils survivent aux recréations. +- Logstream mémorise la position lue dans chaque conteneur (`/data/docker-state.json`) : après + un redémarrage, il reprend sans perdre ni dupliquer de lignes. Un conteneur vu pour la + première fois est lu à partir de `DOCKER_BACKFILL` en arrière (1 heure par défaut). +- Logstream lui-même et le proxy ci-dessous ne sont jamais collectés ; ajoutez l'étiquette + `logstream.exclude=true` à tout autre conteneur pour l'exclure définitivement. + +**Sécurité** : l'accès au socket Docker équivaut à un accès root sur la machine. Logstream passe +donc par [docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy), qui ne laisse +passer que la liste des conteneurs, la lecture des logs, les événements et les informations du +moteur (`GET` uniquement). + +## Export CSV + +Le bouton **Exporter** (à côté du nombre de logs) télécharge tous les logs stockés qui +correspondent aux filtres en cours (recherche, plage de temps, sévérité, hôte, application), +du plus récent au plus ancien, jusqu'à `EXPORT_MAX` lignes (100 000 par défaut), et pas +seulement les lignes à l'écran. Deux variantes : + +- **CSV** : séparateur virgule, UTF-8. +- **CSV pour Excel** : séparateur point-virgule avec un BOM UTF-8, pour qu'Excel en français + l'ouvre directement avec les accents. Les cellules qui commencent par `=`, `+`, `-` ou `@` + sont préfixées par `'` pour qu'un message de log forgé ne puisse pas s'exécuter comme une + formule. + +Colonnes : `received`, `message_time` (toutes deux au format `YYYY-MM-DD HH:MM:SS.mmm` dans le +fuseau horaire choisi dans les Paramètres), `severity`, `facility`, `host`, `host_ip`, `app`, +`pid`, `source_ip`, `proto`, `message`. En mode LogsQL, seule la partie filtre est prise en +charge (pas de `| pipes`). + +En ligne de commande : `curl -o logs.csv 'localhost:8080/api/export.csv?q=error&range=24h&tz=Europe/Paris'`. + +## Paramètres + +L'icône en forme d'engrenage ouvre les paramètres, organisés en onglets. Tout, sauf les tags de +couleur, est mémorisé par navigateur. + +- **Localisation** + - *Langue* : anglais ou français. + - *Date et heure* : fuseau horaire (celui du navigateur, UTC ou environ 80 fuseaux courants) + et format d'affichage de l'heure de réception : `DD/MM/YYYY HH:MM:SS` (par défaut, + l'affichage français habituel), avec millisecondes, `YYYY-MM-DD`, horloge sur 12 heures, + ISO 8601 ou epoch Unix. Le fuseau horaire s'applique à toutes les dates affichées. +- **Filtres** : tags de couleur. Chaque tag a un mot-clé, une couleur de fond (le texte passe + automatiquement en noir ou en blanc pour rester lisible) et des options : mot entier, respect + de la casse, expression régulière, actif. Les tags sont stockés sur le serveur dans + `/data/tags.json` (volume `logstream-data`) : ils sont donc partagés par tous les navigateurs. + Tags par défaut (pastel) : `warning` (orange), `error` (rouge), `ok` (vert). Les tags par + défaut qui utilisent encore les couleurs des versions précédentes passent automatiquement aux + couleurs pastel. +- **Interface** + - *Thème* : Système (suit la préférence de l'ordinateur ou du téléphone), Clair ou Sombre. Le + bouton soleil/lune de l'en-tête bascule entre clair et sombre. + - *Affichage des logs* : taille du texte (très petite, petite, moyenne, grande) et police : + la police monospace du système, ou l'une des 12 polices libres conçues pour le texte dense + (JetBrains Mono, Fira Code, Source Code Pro, IBM Plex Mono, Cascadia Code, Roboto Mono, + Ubuntu Mono, Inconsolata, Red Hat Mono, Noto Sans Mono, Victor Mono, DM Mono). Elles sont + chargées par le navigateur depuis [Bunny Fonts](https://fonts.bunny.net), un service + européen de polices respectueux de la vie privée ; sans accès à internet, la police du + système est utilisée. Les ligatures sont désactivées pour que `->` ou `!=` s'affichent tels + quels. +- **Données** : « Supprimer tous les logs » efface définitivement tous les logs stockés (il faut + taper `PURGE` pour confirmer). Les tags et les paramètres sont conservés. VictoriaLogs doit + être lancé avec `-delete.enable` (déjà présent dans `docker-compose.yml`) ; mettez + `ALLOW_PURGE=false` pour désactiver la fonction. Toute personne qui peut ouvrir l'interface + peut purger : définissez `AUTH_USER` / `AUTH_PASS` si l'interface est accessible à d'autres. + +## Noms d'hôtes (DNS inverse) + +Quand un équipement envoie son adresse IP comme nom d'hôte (ou pas de nom d'hôte du tout), +Logstream cherche son nom DNS (enregistrement PTR) et stocke le nom dans `host` et l'IP dans +`host_ip`. Les résultats sont mis en cache (1 heure, 10 minutes quand il n'y a pas de nom). Les +logs stockés auparavant avec une IP sont résolus à l'affichage, et le filtre d'hôte affiche +`name (IP)`. + +Le conteneur utilise le DNS de Docker, qui relaie vers les résolveurs de l'hôte. Si vos noms +locaux ne sont connus que de votre routeur ou d'un DNS local (Pi-hole, AdGuard, Unbound…), +définissez `DNS_SERVER=192.168.1.1` (son adresse). Mettez `RDNS=off` pour désactiver les +résolutions. +- **Tags de couleur** : chaque tag a un mot-clé, une couleur de fond (le texte passe + automatiquement en noir ou en blanc pour rester lisible) et des options : mot entier, respect + de la casse, expression régulière, actif. Les tags sont stockés dans `/data/tags.json` + (volume `logstream-data`). Tags par défaut (pastel) : `warning` (orange), `error` (rouge), + `ok` (vert). Les tags par défaut qui utilisent encore les couleurs des versions précédentes + passent automatiquement aux couleurs pastel. + +## Configuration + +| Variable | Défaut | Rôle | +|---|---|---| +| `SYSLOG_PORT` | `514` | port syslog publié sur l'hôte | +| `HTTP_PORT` | `8080` | port de l'interface web | +| `RETENTION` | `30d` | durée de conservation des logs dans VictoriaLogs | +| `AUTH_USER` / `AUTH_PASS` | vide | authentification HTTP Basic pour l'interface | +| `RDNS` | `on` | résoudre les hôtes donnés par leur IP en noms DNS | +| `DNS_SERVER` | vide | serveur DNS pour les résolutions inverses (`ip` ou `ip:port`) | +| `ALLOW_PURGE` | `true` | autoriser « Supprimer tous les logs » dans les Paramètres | +| `EXPORT_MAX` | `100000` | nombre maximal de lignes dans un export CSV | +| `DOCKER_LOGS` | `on` dans compose | collecter les logs des conteneurs Docker locaux | +| `DOCKER_HOST` | `tcp://docker-proxy:2375` dans compose | adresse de l'API Docker (`unix:///var/run/docker.sock` hors compose) | +| `DOCKER_BACKFILL` | `1h` | historique lu pour un conteneur vu pour la première fois | +| `TZ` | `Europe/Paris` | fuseau horaire des horodatages RFC 3164 (qui n'en portent pas) | +| `BATCH_SIZE`, `FLUSH_MS`, `QUEUE_SIZE` | `1000`, `1000`, `100000` | réglage de l'ingestion | + +## Débogage + +- `docker compose logs -f logstream` : erreurs de réception et erreurs d'envoi vers + VictoriaLogs. +- La barre du bas affiche les compteurs reçus / stockés / perdus et la dernière erreur de + stockage. +- : l'interface de VictoriaLogs, pour essayer des requêtes + LogsQL. +- API : + ```bash + curl 'localhost:8080/api/logs?q=error&range=1h&limit=5' # the response includes the generated LogsQL query + curl localhost:8080/api/stats + curl localhost:8080/api/tags + ``` +- Lancement hors Docker (Go 1.22+) : `VLOGS_URL=http://localhost:9428 DATA_DIR=./data SYSLOG_ADDR=:5514 go run .` + +## Mise à jour + +Toutes les versions d'images sont épinglées : un `docker compose pull` ou une reconstruction ne +change jamais un composant à votre insu. + +| Emplacement | Image | Version | +|---|---|---| +| `docker-compose.yml` | `victoriametrics/victoria-logs` | `v1.52.0` | +| `docker-compose.yml` | `tecnativa/docker-socket-proxy` | `v0.5.0` | +| `Dockerfile` (build) | `golang` | `1.27.1-alpine3.24` | +| `Dockerfile` (exécution) | `alpine` | `3.24.2` | + +Pour mettre à jour l'une d'elles : + +1. Lisez les notes de version : [VictoriaLogs](https://docs.victoriametrics.com/victorialogs/changelog/), + [docker-socket-proxy](https://github.com/Tecnativa/docker-socket-proxy/releases), + [Go](https://go.dev/doc/devel/release), [Alpine](https://alpinelinux.org/releases/). + VictoriaLogs conserve son format de stockage entre versions mineures ; lisez le changelog + avant un changement de version majeure. +2. Modifiez la version dans le fichier indiqué ci-dessus, puis lancez `docker compose up -d --build`. +3. Vérifiez la barre du bas (reçus / stockés / perdus) et **Paramètres > Sources**. Pour revenir + en arrière, remettez la version précédente et lancez la même commande. + +## Organisation du code + +| Fichier | Contenu | +|---|---| +| `main.go` | configuration, démarrage, authentification | +| `syslog.go` | écoute UDP/TCP et analyse RFC 3164 / 5424 | +| `store.go` | insertions par lots dans VictoriaLogs et requêtes LogsQL | +| `query.go` | traduit les filtres de l'interface en LogsQL ; filtre du direct | +| `histogram.go` | frise : division, alignement des intervalles, `/api/histogram` | +| `hub.go` | envoie les nouveaux messages aux navigateurs (SSE) | +| `rdns.go` | résolutions DNS inverses avec cache | +| `export.go` | export CSV en flux | +| `docker.go` | logs des conteneurs Docker (API, lecteurs, positions, détection du niveau) | +| `syslogserver.go` | écoutes syslog ouvertes et fermées depuis Paramètres > Sources | +| `tags.go` | stockage des tags de couleur | +| `api.go` | routes HTTP `/api/*` | +| `web/` | interface (HTML, CSS, JavaScript simple, sans étape de build), embarquée dans le binaire ; les traductions sont dans `web/app.js` (`I18N`) | + +## Remarque + +Avec Docker Desktop (macOS/Windows), l'IP source vue par le conteneur pour les paquets UDP est +la passerelle Docker. Le champ `host` vient toujours de l'en-tête syslog, qui porte normalement +le vrai nom de l'émetteur. diff --git a/README.md b/README.md index 5d9f81e..53396a1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +English | [Français](README.fr.md) + # Logstream A simple syslog sink: receives logs over UDP/TCP on port 514, stores them in