Logstash pour les devs - 04 - Inputs stdin et file : lire des donnees locales

Les deux premiers input plugins : stdin pour tester et file pour lire des fichiers de logs. Sincedb, start_position et file rotation.

  1. 01 Logstash pour les devs - 00 - Pourquoi Logstash existe encore en 2026
  2. 02 Logstash pour les devs - 01 - L'Elastic Stack de A a Z
  3. 03 Logstash pour les devs - 02 - Installer Logstash avec Docker en 5 minutes
  4. 04 Logstash pour les devs - 03 - Anatomie d'un pipeline Logstash
  5. 05 Logstash pour les devs - 04 - Inputs stdin et file : lire des donnees locales
  6. 06 Logstash pour les devs - 05 - Input Beats : recevoir des logs de Filebeat
  7. 07 Logstash pour les devs - 06 - Inputs HTTP, TCP et UDP : recevoir des donnees réseau
  8. 08 Logstash pour les devs - 07 - Inputs Kafka et JDBC : sources avancees
  9. 09 Logstash pour les devs - 08 - Les codecs : decoder et encoder les donnees
  10. 10 Logstash pour les devs - 09 - Le filtre Grok : parser n'importe quel log
  11. 11 Logstash pour les devs - 10 - Le filtre Dissect : parser sans regex
  12. 12 Logstash pour les devs - 11 - Le filtre Mutate : transformer les champs
  13. 13 Logstash pour les devs - 12 - Filtres Date et GeoIP : temps et geolocalisation
  14. 14 Logstash pour les devs - 13 - Filtres KV, JSON et XML : parser les formats structures
  15. 15 Logstash pour les devs - 14 - Le filtre Ruby : quand les autres ne suffisent pas
  16. 16 Logstash pour les devs - 15 - Filtres Aggregate et Metrics : correler les événements
  17. 17 Logstash pour les devs - 16 - Conditionnels et contrôle de flux
  18. 18 Logstash pour les devs - 17 - Output Elasticsearch : envoyer les donnees
  19. 19 Logstash pour les devs - 18 - Outputs file, stdout et les autres
  20. 20 Logstash pour les devs - 19 - Gerer le multiline : stack traces et logs multi-lignes
  21. 21 Logstash pour les devs - 20 - Pipelines multiples et pipeline-to-pipeline
  22. 22 Logstash pour les devs - 21 - Performance et tuning Logstash
  23. 23 Logstash pour les devs - 22 - Monitoring Logstash : metriques et alertes
  24. 24 Logstash pour les devs - 23 - Dead Letter Queue : ne plus perdre d'événements
  25. 25 Logstash pour les devs - 24 - Sécurité Logstash : SSL, auth et secrets
  26. 26 Logstash pour les devs - 25 - Debugger un pipeline Logstash
  27. 27 Logstash pour les devs - 26 - Tester ses pipelines avant la prod
  28. 28 Logstash pour les devs - 27 - Cas pratique : centraliser des logs applicatifs
  29. 29 Logstash pour les devs - 28 - Cas pratique : ETL avec Logstash et PostgreSQL
  30. 30 Logstash pour les devs - 29 - Cas pratique : enrichir des donnees en temps réel
  31. 31 Logstash pour les devs - 30 - Logstash en production : architecture et bonnes pratiques
  32. 32 Logstash pour les devs - 31 - Glossaire Logstash de A a Z

04 - Inputs stdin et file : lire des donnees locales

Ce que tu vas apprendre

  • Comment stdin fonctionne et quand l'utiliser
  • Le plugin file en détail : path, globs, start_position
  • Le mecanisme sincedb (comment Logstash se souvient de ce qu'il a deja lu)
  • La gestion de la rotation des fichiers de log
  • Les pièges classiques du file input

Prerequisites

  • Le lab Docker qui tourne (voir article 02)
  • Avoir compris l'anatomie d'un pipeline (voir article 03)

stdin : le plugin de dev

J'utilise stdin pour une seule chose : tester un filtre rapidement. Tu veux vérifier si ton pattern Grok fonctionne ? Tu colles ta ligne de log dans stdin et tu regardes le résultat dans stdout. Pas de fichier, pas de configuration, pas d'attente.

Configuration minimale

input {
  stdin {
    codec => plain
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

Le codec plain est le défaut. Chaque ligne tapee dans le terminal devient un événement avec le texte dans le champ message.

stdin avec un codec JSON

Si ton application écrit des logs en JSON (et elle devrait), tu peux demander a stdin de parser le JSON directement :

input {
  stdin {
    codec => json
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

Si tu colles {"level":"ERROR","service":"api","msg":"timeout"}, Logstash créé un événement avec trois champs directement accessibles : level, service, msg. Pas besoin de filtre JSON.

Les limites de stdin

stdin bloque le terminal. Tu ne peux pas l'utiliser dans un conteneur Docker en mode detache (-d). Et il ne fonctionne que pour un seul flux de donnees. En production, tu ne l'utiliseras jamais. C'est un outil de debug.

Pour le lab Docker, si tu veux tester avec stdin, lance Logstash en mode interactif :

bashdocker compose run --rm -it logstash \
  bin/logstash -e 'input { stdin {} } output { stdout { codec => rubydebug } }'

Ca lance une instance temporaire. Tape du texte, regarde le résultat, quitte avec Ctrl+C.

file : le plugin le plus utilise en local

Le plugin file lit des fichiers. Ca parait simple, mais il y a un mecanisme interne qui surprend la première fois : sincedb.

Configuration de base

input {
  file {
    path => "/data/app.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}

output {
  stdout {
    codec => rubydebug
  }
}

Mets ce pipeline dans logstash/pipeline/main.conf et créé un fichier data/app.log avec quelques lignes :

2026-03-31 14:00:01 INFO  User 42 logged in
2026-03-31 14:00:02 ERROR Database connection timeout
2026-03-31 14:00:03 WARN  Slow query: 2340ms

Logstash va lire le fichier et créer un événement par ligne.

start_position : beginning vs end

Ce paramètre ne s'applique que la première fois que Logstash voit un fichier. Deux options :

  • beginning : lit le fichier depuis le début
  • end : ne lit que les nouvelles lignes ajoutees apres le démarrage (défaut)

Le défaut est end. Ca surprend tout le monde. Tu créés un fichier, tu demarres Logstash, et rien ne se passe. Le fichier existait deja, Logstash commence a la fin et attend de nouvelles lignes.

Pour du dev et du test, utilise toujours start_position => "beginning".

sincedb : la mémoire de Logstash

sincedb est le mecanisme qui permet a Logstash de se souvenir de sa position dans un fichier. C'est un petit fichier texte qui stocke, pour chaque fichier surveille, l'inode et le nombre d'octets deja lus.

# Contenu typique d'un fichier sincedb
1234567 0 54321 98765

Chaque ligne represente un fichier : inode, device majeur, device mineur, position en octets.

Pourquoi c'est important ? Parce que si Logstash redemarrage, il reprend là où il s'etait arrêté. Pas de doublon, pas de perte. C'est le meme principe que les offsets Kafka.

Le problème en dev : si tu modifies ton fichier de test et que tu veux le relire, Logstash refuse. sincedb lui dit "j'ai deja lu ce fichier jusqu'a l'octet 156". Pour contourner :

# Option 1 : envoyer sincedb dans /dev/null (oublie tout a chaque redemarrage)
sincedb_path => "/dev/null"

# Option 2 : supprimer le fichier sincedb manuellement
# Il est dans /usr/share/logstash/data/plugins/inputs/file/ par defaut

En production, ne touche jamais a sincedb. C'est ce qui garantit la fiabilité du file input. En dev, sincedb_path => "/dev/null" est ton ami.

Surveiller un dossier entier

Tu peux utiliser des globs dans le path :

input {
  file {
    path => "/data/logs/*.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}

Logstash surveille tous les fichiers .log dans /data/logs/. Si un nouveau fichier apparaît, il le détecté et commence a le lire.

Globs supportes :

Pattern Signification
* N'importe quel nom de fichier
** N'importe quel sous-dossier (recursif)
? Un seul caractère
[abc] Un caractère parmi a, b, c
# Tous les logs dans tous les sous-dossiers
path => "/data/logs/**/*.log"

# Les logs qui commencent par "app"
path => "/data/logs/app*.log"

# Plusieurs patterns
path => ["/data/logs/app.log", "/data/logs/error.log"]

Exclure des fichiers

input {
  file {
    path => "/data/logs/*.log"
    exclude => ["debug.log", "*.gz"]
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}

exclude prend un tableau de globs. Ici, on ignore les fichiers de debug et les archives gzippees.

La rotation des fichiers

Les fichiers de log tournent. Logrotate, par exemple, renomme app.log en app.log.1 et créé un nouveau app.log. Ou alors il compresse en app.log.gz.

Logstash gere ca grace au tracking par inode. Il suit l'inode du fichier, pas son nom. Quand app.log est renomme en app.log.1, Logstash continue de lire app.log.1 jusqu'a la fin (meme inode), puis détecté le nouveau app.log (nouvel inode) et commence a le lire.

# Avant rotation
app.log (inode 12345, position 5000)  <-- Logstash lit ici

# Apres rotation
app.log.1 (inode 12345, position 5000)  <-- Logstash finit de lire
app.log   (inode 67890, position 0)     <-- Logstash commence ici

Paramètres lies a la rotation

input {
  file {
    path => "/data/logs/app.log"
    start_position => "beginning"

    # Combien de temps garder un fichier ouvert apres la derniere lecture
    close_older => "1 hour"

    # Combien de temps ignorer un fichier inactif
    ignore_older => "24 hours"

    # Frequence de verification des nouveaux fichiers
    stat_interval => "1 second"

    # Frequence de verification des fichiers connus
    discover_interval => 15
  }
}
  • close_older : ferme le file handle apres 1 heure d'inactivite. Important sur les systèmes avec beaucoup de fichiers pour éviter d'epuiser les file descriptors.
  • ignore_older : ne lit pas les fichiers qui n'ont pas ete modifies depuis 24 heures. Evite de relire de vieux logs au démarrage.
  • stat_interval : a quelle fréquence Logstash vérifié si les fichiers connus ont grandi.
  • discover_interval : a quelle fréquence Logstash cherche de nouveaux fichiers dans le glob.

Cas pratique : lire plusieurs types de logs

Imaginons que tu as deux types de logs dans des dossiers différents :

data/
├── app/
│   ├── api.log
│   └── worker.log
└── nginx/
    └── access.log

Tu peux utiliser deux inputs file et ajouter un champ type pour les distinguer dans les filtres :

input {
  file {
    path => "/data/app/*.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
    type => "app"
    add_field => { "source_dir" => "app" }
  }

  file {
    path => "/data/nginx/*.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
    type => "nginx"
    add_field => { "source_dir" => "nginx" }
  }
}

filter {
  if [type] == "nginx" {
    grok {
      match => { "message" => "%{COMBINEDAPACHELOG}" }
    }
  }

  if [type] == "app" {
    grok {
      match => { "message" => "%{TIMESTAMP_ISO8601:ts} %{LOGLEVEL:level} %{GREEDYDATA:msg}" }
    }
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "logs-%{type}-%{+YYYY.MM.dd}"
  }
}

Le champ type est un paramètre commun a tous les inputs. Il permet de router les événements dans les filtres avec des conditionnels. Les logs Nginx vont dans logs-nginx-2026.03.31, les logs app dans logs-app-2026.03.31.

Surveiller un fichier en temps réel

Pour simuler une application qui écrit des logs en continu, ouvre un deuxieme terminal et ajoute des lignes :

bash# Terminal 1 : Logstash tourne avec le pipeline file

# Terminal 2 : ajouter des lignes au fichier
docker exec -it logstash bash -c 'echo "2026-03-31 15:00:00 INFO New line added" >> /data/app.log'

Ou depuis l'hote, si le dossier data/ est monte :

bashecho "2026-03-31 15:00:00 INFO New line added" >> data/app/api.log

Logstash détecté la nouvelle ligne et la traite. Le delai depend de stat_interval (1 seconde par défaut).

Les paramètres communs a tous les inputs

Chaque input plugin accepte des paramètres génériques. On les a deja vus pour certains :

Paramètre Description Exemple
type Ajoute un champ type a chaque événement type => "nginx"
tags Ajoute des tags a chaque événement tags => ["web", "prod"]
add_field Ajoute des champs custom add_field => { "env" => "staging" }
codec Change le codec d'entree codec => json

Ces paramètres fonctionnent sur tous les inputs : file, beats, http, kafka, jdbc. On les retrouvera dans les prochains articles.

Quand utiliser file vs Filebeat

Le plugin file de Logstash et Filebeat font la meme chose : lire des fichiers de log. Mais ils n'ont pas le meme usage.

file input (Logstash) Filebeat
RAM ~1 Go (c'est Logstash entier) ~15 Mo
Use case Dev, tests, machine unique Production, multi-serveurs
Backpressure Queue interne Buffer disque + retry
Installation Rien (dans Logstash) Agent a installer sur chaque serveur

En production, tu mets Filebeat sur chaque serveur et tu centralises vers Logstash. Tu n'installes pas Logstash sur chaque serveur, c'est du gaspillage de RAM.

Le file input est utile pour le dev local, les tests, et les cas ou tu as un seul serveur avec Logstash deja installe. Sur paltemps.fr, le file input sert surtout dans les scripts de reprocessing : relire un fichier de log archive pour le re-parser avec de nouvelles regles.

Résumé

  • stdin est un outil de debug : rapide, interactif, inutile en production
  • Le file input lit des fichiers et suit sa position avec sincedb
  • start_position => "beginning" relit le fichier depuis le début (sinon, seules les nouvelles lignes sont lues)
  • sincedb_path => "/dev/null" oublie la position a chaque redemarrage (utile en dev)
  • La rotation des fichiers est geree automatiquement via le tracking par inode
  • Le champ type permet de distinguer les sources dans les filtres
  • En production, préféré Filebeat au file input pour la collecte

Precedent : 03 - Anatomie d'un pipeline | Suivant : 05 - Input Beats

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.