Analyser les journaux web et applicatifs à grande échelle
Extrayez les codes d’état, les temps de réponse et les champs client des journaux d’accès avec grep, cut et awk.
Analyser les journaux web et applicatifs à grande échelle est une leçon DevOps Bootcamp gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DevOps Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DevOps Bootcamp comprend 4 leçons au total.
Qu’est-ce qu’un journal d’accès web ?
Chaque serveur HTTP — Apache, Nginx, Caddy — écrit une ligne dans un journal d’accès pour chaque requête. Comprendre la structure de ces lignes constitue la base de tout travail d’analyse des journaux.
Une ligne typique au format de journal combiné (CLF) ressemble à ceci :
- Adresse IP du client — l’auteur de la requête
- Horodatage — le moment où elle s’est produite
- Ligne de requête — méthode, chemin, protocole
- Code d’état — réponse HTTP (200, 404, 500…)
- Octets envoyés — taille du corps de la réponse
- Référent — page d’origine
- Agent utilisateur — chaîne identifiant le navigateur ou le robot
Exemple de ligne provenant de /var/log/nginx/access.log :
192.168.1.10 - alice [11/Jun/2026:14:32:01 +0000] "GET /api/orders HTTP/1.1" 200 1482 "-" "curl/7.88.1"
À grande échelle, ces fichiers atteignent des millions de lignes par jour. L’objectif de cette leçon est d’en extraire, filtrer et agréger efficacement les champs à l’aide des outils BASH standard.
Échantillonner un journal en direct avec tail et grep
Avant d’écrire une chaîne de traitement, examinez le journal pour comprendre sa structure. tail vous permet de suivre un flux en direct ; grep le réduit immédiatement aux lignes pertinentes.
Schémas courants :
tail -n 1000 access.log— les 1000 dernières lignestail -f access.log— suivre en temps réeltail -f access.log | grep '" 5'— uniquement les erreurs 5xx au moment où elles arrivent
L’idée essentielle est que grep effectue la correspondance sur la ligne entière : il est donc important d’ancrer votre motif. La recherche de ' 500 ' (avec des espaces) évite de détecter accidentellement un chemin d’URL contenant la chaîne 500.
#!/usr/bin/env bash
# Watch only HTTP 5xx errors arriving in real time
tail -f /var/log/nginx/access.log \
| grep --line-buffered '" 5[0-9][0-9] 'Extraire le code d’état avec cut
cut sépare chaque ligne à l’aide d’un délimiteur et affiche les champs sélectionnés. Dans le format CLF, le code d’état se trouve au champ 9 lorsque les champs sont séparés par des espaces — mais les guillemets autour de la ligne de requête rendent plus sûre une numérotation à partir d’un repère connu.
Une astuce fiable : comme la ligne de requête est toujours entre guillemets, le code d’état est toujours le premier élément après le guillemet fermant du champ de requête. cut -d'"' -f3 isole tout ce qui suit le guillemet de la requête, puis un second cut -d' ' -f2 sélectionne le code d’état.
Cette séparation en deux étapes est une tournure classique pour les journaux CLF — rapide et sans dépendances externes.
#!/usr/bin/env bash
# Print only the HTTP status code from each log line
# Input format: ... "GET /path HTTP/1.1" 200 1482 ...
cut -d'"' -f3 /var/log/nginx/access.log \
| cut -d' ' -f2 \
| sort \
| uniq -c \
| sort -rnCompter les codes d’état avec awk
awk est plus puissant que cut, car il peut conserver un état entre les lignes. Le schéma idiomatique pour compter les occurrences consiste à utiliser un tableau associatif indexé par la valeur qui vous intéresse.
Dans le CLF, le champ $9 (indexé à partir de 1 et séparé par des espaces) contient le code d’état. awk traite chaque ligne, incrémente un compteur, puis affiche un récapitulatif trié dans le bloc END.
Pourquoi préférer awk à cut | sort | uniq -c ? Parce que awk effectue le traitement en un seul parcours, sans trier d’abord l’intégralité du fichier — ce qui est essentiel lorsque le journal fait plusieurs centaines de gigaoctets.
#!/usr/bin/env bash
# Count HTTP status codes in a single awk pass
awk '{ count[$9]++ }
END {
for (status in count)
printf "%6d %s\n", count[status], status
}' /var/log/nginx/access.log \
| sort -rnFiltrer les erreurs et extraire les adresses IP des clients
L’une des tâches opérationnelles les plus courantes consiste à trouver quelles adresses IP clientes génèrent le plus d’erreurs. Cela combine le filtrage (uniquement les lignes d’erreur) et l’extraction de champs (l’IP du champ 1).
Stratégie de la chaîne de traitement :
- Utilisez
awkpour filtrer selon la plage de codes d’état et extraire l’IP en une seule étape — évitez un passage distinct degrep - Redirigez vers
sort | uniq -c | sort -rn | headpour obtenir rapidement une vue des premières valeurs
Ce schéma est assez rapide pour être exécuté sur un fichier journal de 10 Go depuis un seul serveur, sans charger le fichier en mémoire.
#!/usr/bin/env bash
# Top 10 IPs generating HTTP 4xx or 5xx errors
awk '$9 ~ /^[45][0-9][0-9]$/ { print $1 }' \
/var/log/nginx/access.log \
| sort \
| uniq -c \
| sort -rn \
| head -10Analyser la latence des réponses dans les journaux d’application
Les serveurs d’application (Rails, Gunicorn, Express avec morgan, etc.) consignent souvent la durée des requêtes. Nginx peut être configuré pour émettre $request_time comme champ supplémentaire à la fin de chaque ligne.
Exemple de format de journal Nginx personnalisé dans nginx.conf :
log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time';
Une fois la latence présente dans le journal, vous pouvez utiliser awk pour calculer la moyenne, le maximum et des approximations des percentiles sur des millions de requêtes, sans charger les données dans une base de données.
#!/usr/bin/env bash
# Compute average and max request_time from Nginx timed log
# Assumes last field is rt=<seconds> e.g. rt=0.042
awk '{
# Extract numeric value after rt=
n = split($NF, a, "=")
if (n == 2 && a[1] == "rt") {
t = a[2] + 0
sum += t
count++
if (t > max) max = t
}
}
END {
if (count > 0)
printf "Requests: %d Avg: %.4fs Max: %.4fs\n", count, sum/count, max
}' /var/log/nginx/timed_access.logCréer un histogramme de latence avec awk
Une simple moyenne masque la latence de queue. Un histogramme révèle la distribution — la plupart des requêtes sont-elles rapides avec quelques requêtes très lentes (longue traîne), ou la distribution est-elle uniforme ?
L’astuce consiste à placer chaque valeur dans une plage arrondie à l’aide de l’arithmétique entière dans awk. La multiplication par 1000 (pour convertir les secondes en millisecondes), suivie d’une division entière, produit des bornes de classes nettes.
Vous obtenez ainsi un histogramme textuel lisible directement dans un terminal, ce qui est souvent plus rapide que d’envoyer les données à Grafana pour une investigation rapide.
#!/usr/bin/env bash
# Latency histogram (50ms buckets) from Nginx timed log
awk '{
n = split($NF, a, "=")
if (n == 2 && a[1] == "rt") {
ms = int(a[2] * 1000) # convert to ms
bucket = int(ms / 50) * 50 # round down to 50ms boundary
hist[bucket]++
}
}
END {
for (b in hist)
printf "%6dms %d\n", b, hist[b]
}' /var/log/nginx/timed_access.log \
| sort -nExtraire l’agent utilisateur et détecter les robots
Le champ Agent utilisateur (champ 6 lorsque la séparation se fait sur ") identifie les clients. Les robots d’exploration, les récupérateurs de données et les robots malveillants faussent souvent vos métriques et gonflent le nombre d’erreurs. Les filtrer donne une image plus fidèle du trafic des vrais utilisateurs.
Signatures courantes des robots : bot, crawler, spider, curl, python-requests, Googlebot, Bingbot.
Utilisez grep -iv (inversion insensible à la casse) pour exclure les robots connus, ou utilisez awk pour séparer sur " et rechercher directement dans le champ UA.
#!/usr/bin/env bash
# Count top 15 User-Agent strings, excluding known bots
awk -F'"' '{ print $6 }' /var/log/nginx/access.log \
| grep -iv -e 'bot' -e 'crawler' -e 'spider' -e 'curl' \
-e 'python' -e 'wget' -e 'Go-http-client' \
| sort \
| uniq -c \
| sort -rn \
| head -15Agréger le trafic par point d’accès
Savoir quels points d’accès reçoivent le plus de trafic — et génèrent le plus d’erreurs — aide à hiérarchiser l’optimisation et la planification de capacité. Le chemin de la requête se trouve dans le champ de requête entre guillemets.
Séparez sur ", prenez le champ 2 (la ligne de requête), puis retirez la méthode et le protocole pour isoler le chemin. Pour les API dont les chemins contiennent des paramètres comme /users/12345, vous pouvez également normaliser les identifiants en /users/:id avec sed ou un motif awk plus complexe.
#!/usr/bin/env bash
# Top 20 requested endpoints (method + path, no query string)
awk -F'"' '{ print $2 }' /var/log/nginx/access.log \
| awk '{ print $1, $2 }' \
| sed 's|/[0-9][0-9]*\b|/:id|g' \
| sort \
| uniq -c \
| sort -rn \
| head -20Mettre en relation les erreurs et les points d’accès avec awk
L’analyse en un seul parcours la plus puissante combine plusieurs champs à la fois : point d’accès, code d’état et, éventuellement, latence. Les tableaux associatifs de awk indexés par des valeurs composites rendent cette opération claire et rapide.
Le schéma ci-dessous compte les erreurs 5xx par point d’accès en un seul parcours — aucun fichier temporaire et aucun tri intermédiaire avant la toute fin. C’est l’approche utilisée dans les scripts d’observabilité en production lorsqu’il faut obtenir des réponses en moins d’une minute sur un journal volumineux.
#!/usr/bin/env bash
# Count 5xx errors per endpoint path in a single pass
awk -F'"' '{
# $2 = request line e.g. "GET /api/orders HTTP/1.1"
# $0 in original space-split: $9 = status
split($0, fields, " ")
status = fields[9]
if (status ~ /^5/) {
split($2, req, " ")
path = req[2]
# Normalise numeric IDs
gsub(/\/[0-9]+/, "/:id", path)
errors[path]++
}
}
END {
for (p in errors)
printf "%6d %s\n", errors[p], p
}' /var/log/nginx/access.log \
| sort -rn \
| head -20Traiter les journaux archivés et compressés
Sur la plupart des serveurs, les journaux sont archivés quotidiennement. Les fichiers plus anciens sont compressés avec gzip sous des noms tels que access.log.1.gz, access.log.2.gz, etc. Les outils standard ne peuvent pas les lire directement, mais deux approches fonctionnent bien :
zcat— décompresser vers la sortie standard et transmettre à votre chaîne de traitementzgrep— rechercher directement dans les fichiers gzip sans les extraire
Pour analyser une semaine complète de journaux comprenant à la fois des fichiers non compressés et compressés, utilisez la substitution de processus ou concaténez-les avec zcat. L’extrait ci-dessous traite les 7 derniers fichiers archivés ainsi que le journal actif actuel dans un seul appel à awk — aucun fichier temporaire n’est nécessaire.
#!/usr/bin/env bash
# Aggregate status codes across a week of rotated logs
# Handles both plain and gzip-compressed rotation files
LOG_DIR="/var/log/nginx"
{
cat "${LOG_DIR}/access.log" 2>/dev/null
zcat "${LOG_DIR}/access.log".*.gz 2>/dev/null
} | awk '
{ count[$9]++ }
END {
for (s in count)
printf "%6d %s\n", count[s], s
}' | sort -rnQuel champ awk contient le code d’état HTTP dans le format de journal combiné ?
Vous écrivez une commande awk sur une seule ligne pour filtrer uniquement les réponses HTTP 4xx dans un journal d’accès Nginx standard au format de journal combiné (délimité par des espaces, avec la ligne de requête entre guillemets). Quel numéro de champ identifie correctement le code d’état HTTP ?
Récapitulatif de la leçon : pipelines d’analyse des journaux
Dans cette leçon, vous avez constitué une boîte à outils complète pour analyser à grande échelle les journaux web et applicatifs en utilisant uniquement les utilitaires BASH standard.
Principales techniques abordées :
- Commencer par la structure — le format de journal combiné possède une organisation prévisible des champs : la connaître vous permet de les séparer de manière fiable avec
cut -d'"'ou les références de champs deawk. - Extraction des codes d’état —
awk '{ count[$9]++ }'compte tous les codes en un seul parcours ; filtrez avec$9 ~ /^5/pour les erreurs du serveur. - Analyse de la latence — analysez le champ personnalisé
rt=avecawkpour calculer les moyennes, les valeurs maximales et les classes de l’histogramme sans aucun outil externe. - Analyse des clients et des robots — séparez sur
"avec-F'"'pour atteindre le champ User-Agent ; faites passer le résultat pargrep -ivafin d’exclure les robots avant l’agrégation. - Normalisation des points de terminaison — utilisez
gsub(/\/[0-9]+/, "/:id")dansawkpour regrouper les chemins paramétrés avant le comptage. - Journaux ayant subi une rotation — combinez
catetzcatdans un sous-shell pour envoyer tous les fichiers issus de la rotation dans un seul passage du pipeline.
Ces motifs se combinent : vous pouvez enchaîner le filtrage, l’extraction, la normalisation et l’agrégation dans un seul pipeline qui traite des centaines de millions de lignes sur du matériel standard. Maîtrisez ces primitives et vous aurez rarement besoin d’un service dédié d’agrégation des journaux pour examiner ponctuellement un incident.
Questions Fréquemment Posées
La leçon « Analyser les journaux web et applicatifs à grande échelle » est-elle gratuite ?
Oui — le texte complet de « Analyser les journaux web et applicatifs à grande échelle » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DevOps Bootcamp, passe à CoddyKit PRO. Le cours DevOps Bootcamp comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Analyser les journaux web et applicatifs à grande échelle » ?
Extrayez les codes d’état, les temps de réponse et les champs client des journaux d’accès avec grep, cut et awk. Tu pratiques DevOps Bootcamp avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer DevOps Bootcamp ?
Aucune expérience préalable n'est requise. DevOps Bootcamp sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Analyser les journaux web et applicatifs à grande échelle » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon DevOps Bootcamp ?
Oui. Chaque leçon DevOps Bootcamp inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Analyser les journaux web et applicatifs à grande échelle
- Suivre les journaux en temps réel et diffuser des alertes
- Interroger journald avec journalctl dans les scripts
- Calculer des métriques et des histogrammes à partir de flux de journaux