Calcolare metriche e istogrammi dai flussi di log
Aggrregi tassi di richiesta, percentili e report top-N direttamente dai dati di log in streaming.
Calcolare metriche e istogrammi dai flussi di log è una lezione DevOps Bootcamp gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento DevOps Bootcamp, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso DevOps Bootcamp include 4 lezioni in totale.
Perché calcolare le metriche dai log grezzi?
I sistemi in produzione generano migliaia di righe di log al secondo. Anziché inviare i log grezzi a costose piattaforme di analisi, è possibile calcolare direttamente nella shell tassi di richieste, percentili e report top-N, a un costo quasi nullo.
- Tasso di richieste: quante richieste al secondo o al minuto gestisce il servizio?
- Percentili della latenza: qual è il tempo di risposta p50/p95/p99?
- Report top-N: quali endpoint, indirizzi IP o codici di errore compaiono più frequentemente?
Gli strumenti shell come awk, sort, uniq e bc formano una potente pipeline componibile, in grado di rispondere a queste domande a partire da un flusso di log in tempo reale o da un file storico, senza uscire dal terminale.
Anatomia di un access log comune
La maggior parte dei server web scrive i log nel Combined Log Format. Comprenderne i campi è il fondamento di ogni pipeline per le metriche:
127.0.0.1 - frank [10/Oct/2024:13:55:36 -0700] "GET /api/users HTTP/1.1" 200 2326 0.042- Campo 1: IP client
- Campo 4 (tra parentesi quadre): timestamp
- Campo 7 (tra virgolette): metodo HTTP + percorso
- Campo 9: codice di stato
- Campo 10: byte della risposta
- Campo 11: tempo di risposta in secondi (campo personalizzato, non sempre presente)
Usare awk per fare riferimento ai campi in base alla posizione ($1, $9, ecc.). I campi tra virgolette vengono conteggiati come un unico token solo se si esegue la suddivisione con attenzione: racchiudere la riga di log in awk -F'"' oppure usare più passaggi.
Conteggio del tasso di richieste al minuto
Per calcolare le richieste al minuto, estrarre la parte relativa al minuto da ogni timestamp e contare le occorrenze. Il pattern [day/Mon/year:HH:MM fornisce il raggruppamento ora:minuto.
La pipeline seguente legge access.log e stampa una tabella di minuto → numero di richieste:
#!/usr/bin/env bash
# Requests per minute from an nginx/apache access log
# Usage: bash req_per_min.sh access.log
LOG="${1:-access.log}"
awk '{
# Extract [day/Mon/year:HH:MM from field 4
match($0, /\[([^:]+:[0-9]+:[0-9]+)/, arr)
minute = arr[1]
if (minute != "") count[minute]++
} END {
for (m in count) print count[m], m
}' "$LOG" | sort -k2Tasso su finestra scorrevole con un flusso in tempo reale
Per un live tail è necessaria una finestra scorrevole. Il trucco consiste nell'usare tail -f reindirizzato a awk, che azzera il contatore ogni N secondi usando l'orologio di sistema (systime()).
Questo esempio stampa una riga con il tasso ogni 10 secondi:
#!/usr/bin/env bash
# Live request rate — prints lines/10s from a tailed log
# Usage: bash live_rate.sh /var/log/nginx/access.log
LOG="${1:-/var/log/nginx/access.log}"
WINDOW=10
tail -f "$LOG" | awk -v win="$WINDOW" '
BEGIN { start = systime(); count = 0 }
{
count++
now = systime()
if (now - start >= win) {
printf "[%s] %d req/%ds (%.1f req/s)\n",
strftime("%H:%M:%S", now), count, win, count/win
count = 0
start = now
}
}'Estrazione dei valori di latenza per il calcolo dei percentili
Per calcolare i percentili è necessario ordinare tutti i valori di latenza osservati. L'approccio standard è:
- Estrarre la colonna della latenza in un elenco di numeri semplice.
- Ordinare numericamente.
- Selezionare il valore nella posizione corretta usando il conteggio delle righe.
Lo script seguente estrae il campo 11 (tempo di risposta in secondi) e lo salva in un file temporaneo per il calcolo dei percentili nel passaggio successivo:
#!/usr/bin/env bash
# Extract latency column from access log (field 11)
# Assumes last field on each line is response time in seconds
LOG="${1:-access.log}"
TMP=$(mktemp /tmp/latency_XXXXXX.txt)
awk '{ if ($NF ~ /^[0-9]+\.?[0-9]*$/) print $NF }' "$LOG" \
| sort -n > "$TMP"
echo "Extracted $(wc -l < "$TMP") latency samples -> $TMP"
echo "$TMP" # callers can read this fileCalcolo di p50, p95 e p99 con awk
Una volta ordinati i valori di latenza, selezionare un percentile è un'operazione aritmetica: il percentile p si trova alla riga ceil(p/100 * N). Il solo awk può eseguire questa operazione in un unico passaggio dopo aver caricato il file ordinato in un array:
#!/usr/bin/env bash
# Compute p50 / p95 / p99 from a sorted latency file
# Usage: bash percentiles.sh latency_sorted.txt
# Demo: generate 1000 random latencies if no file given
if [[ $# -eq 0 ]]; then
SORTED=$(mktemp)
for i in $(seq 1 1000); do
awk 'BEGIN { srand(); printf "%.4f\n", 0.001 + rand()*0.999 }'
done | sort -n > "$SORTED"
else
SORTED="$1"
fi
awk '
{ values[NR] = $1 }
END {
n = NR
if (n == 0) { print "No data"; exit }
p50 = values[int(n * 0.50 + 0.9999)]
p95 = values[int(n * 0.95 + 0.9999)]
p99 = values[int(n * 0.99 + 0.9999)]
printf "p50 = %.4fs\np95 = %.4fs\np99 = %.4fs\nN = %d\n",
p50, p95, p99, n
}' "$SORTED"Creazione di un report degli endpoint top-N
Un report top-N risponde alla domanda "quali percorsi ricevono più richieste?" L'idioma classico della shell è:
awkper stampare il campo di interesse (ad esempio, il percorso dell'URL)sortper raggruppare i valori identiciuniq -cper contare i duplicati consecutivisort -rnper ordinare in base al conteggio decrescentehead -n Nper prendere i primi N
#!/usr/bin/env bash
# Top-10 most requested URL paths from access log
# Usage: bash top_endpoints.sh access.log [N]
LOG="${1:-access.log}"
N="${2:-10}"
echo "=== Top $N endpoints ==="
awk -F'"' '{ print $2 }' "$LOG" \
| awk '{ print $2 }' \
| sort \
| uniq -c \
| sort -rn \
| head -n "$N" \
| awk '{ printf "%6d %s\n", $1, $2 }'Top-N per codice di stato: individuare gli errori a colpo d'occhio
I codici di stato HTTP indicano lo stato di salute del servizio. Raggruppare le righe di log per codice di stato e contarle rivela se gli errori sono rari o sistemici.
Lo script seguente genera una suddivisione tra tutti i gruppi 2xx/3xx/4xx/5xx:
#!/usr/bin/env bash
# Status code frequency breakdown
# Usage: bash status_breakdown.sh access.log
LOG="${1:-access.log}"
echo "=== HTTP Status Code Distribution ==="
awk '{ print $9 }' "$LOG" \
| grep -E '^[0-9]{3}$' \
| sort \
| uniq -c \
| sort -rn \
| awk '{ printf "%6d %s\n", $1, $2 }'
echo
echo "=== 5xx Error Spike Check ==="
awk '$9 ~ /^5/ { print $9, $7 }' "$LOG" \
| sort | uniq -c | sort -rn | head -20Istogrammi ASCII con awk
Un istogramma testuale rende immediatamente leggibili le distribuzioni della latenza in un terminale o in un log CI. L'approccio è:
- Inserire ogni valore di latenza in un intervallo (ad esempio, 0-50ms, 50-100ms, …).
- Contare le osservazioni per intervallo.
- Stampare una barra di caratteri
#proporzionata al conteggio massimo.
È estremamente utile per individuare distribuzioni bimodali o valori anomali senza uno strumento per la creazione di grafici.
#!/usr/bin/env bash
# ASCII latency histogram from a list of latency values in seconds
# Demo: generates synthetic data if no input file is provided
if [[ $# -eq 0 ]]; then
# Generate 500 synthetic latencies (ms converted to s)
python3 -c "
import random, math
for _ in range(500):
# bimodal: fast cluster ~50ms, slow cluster ~300ms
if random.random() < 0.75:
v = max(1, random.gauss(50, 15))
else:
v = max(1, random.gauss(300, 80))
print(f'{v/1000:.4f}')
" | sort -n | awk '
{ values[NR] = $1 * 1000 } # convert to ms
END {
buckets = 10; maxVal = 500
step = maxVal / buckets
for (i = 0; i < buckets; i++) hist[i] = 0
for (i = 1; i <= NR; i++) {
b = int(values[i] / step)
if (b >= buckets) b = buckets - 1
hist[b]++
}
maxCount = 0
for (i = 0; i < buckets; i++) if (hist[i] > maxCount) maxCount = hist[i]
print "Latency (ms) Count Distribution"
print "---------------------------------------"
for (i = 0; i < buckets; i++) {
lo = i * step; hi = lo + step
barLen = int(hist[i] / maxCount * 40)
bar = ""
for (j = 0; j < barLen; j++) bar = bar "#"
printf "%4d-%4dms %5d %s\n", lo, hi, hist[i], bar
}
}'
else
echo "Usage: pipe a sorted latency file (in seconds) to this pattern"
fiCombinazione delle metriche: report riepilogativo in un'unica esecuzione
I runbook di produzione richiedono spesso un singolo comando che emetta tutte le metriche principali contemporaneamente: tasso, percentili della latenza, endpoint principali e tasso di errore. È possibile combinare in un unico script tutto ciò che ha imparato finora, richiamabile da una persona o da un sistema di alerting.
#!/usr/bin/env bash
# One-shot log summary report
# Usage: bash log_summary.sh access.log
LOG="${1:-access.log}"
[[ -f "$LOG" ]] || { echo "File not found: $LOG"; exit 1; }
TOTAL=$(wc -l < "$LOG")
ERRORS=$(awk '$9 ~ /^[45]/' "$LOG" | wc -l)
ERR_RATE=$(awk "BEGIN { printf \"%.1f\", ($ERRORS / ($TOTAL || 1)) * 100 }")
echo "====================================="
echo " Log Summary: $LOG"
echo "====================================="
printf " Total requests : %d\n" "$TOTAL"
printf " 4xx/5xx errors : %d (%.1f%%)\n" "$ERRORS" "$ERR_RATE"
echo
echo "--- Top 5 Endpoints ---"
awk -F'"' '{ print $2 }' "$LOG" | awk '{ print $2 }' \
| sort | uniq -c | sort -rn | head -5 \
| awk '{ printf " %6d %s\n", $1, $2 }'
echo
echo "--- Latency Percentiles ---"
awk '{ if ($NF ~ /^[0-9]+\.?[0-9]*$/) print $NF * 1000 }' "$LOG" \
| sort -n \
| awk '
{ v[NR]=$1 }
END {
if (NR==0) { print " No latency data"; exit }
printf " p50 = %.1fms\n", v[int(NR*0.50+0.9999)]
printf " p95 = %.1fms\n", v[int(NR*0.95+0.9999)]
printf " p99 = %.1fms\n", v[int(NR*0.99+0.9999)]
}'Metriche in streaming tramite named pipe e tee
Nelle pipeline di osservabilità è spesso necessario diramare un flusso di log: scrivere le righe grezze su disco e calcolare contemporaneamente le metriche. tee con una named pipe (mkfifo) lo rende possibile senza memorizzare l'intero flusso in memoria.
mkfifo /tmp/log_pipe— crea la named pipetee /tmp/log_pipe | metric_consumer &— dirama un ramo verso il consumer delle metriche- L'altro ramo scrive nel file di archivio
Questo modello mantiene separati le scritture su disco e l'aggregazione delle metriche e consente a ciascun lato di riavviarsi in modo indipendente.
#!/usr/bin/env bash
# Fan-out: write to archive AND count errors in real time
# Run: bash fanout_pipeline.sh /var/log/nginx/access.log
LOG="${1:-/var/log/nginx/access.log}"
ARCHIVE="/tmp/access_archive.log"
PIPE="/tmp/log_metrics_pipe"
# Clean up on exit
trap 'rm -f "$PIPE"' EXIT
mkfifo "$PIPE"
# Branch 1: count 5xx errors per minute from the pipe
awk '$9 ~ /^5/ {
match($0, /\[([^:]+:[0-9]+:[0-9]+)/, arr)
errors[arr[1]]++
} END {
for (m in errors) printf "5xx errors at %s: %d\n", m, errors[m]
}' "$PIPE" &
# Branch 2: archive to disk + feed Branch 1 via pipe
tail -f "$LOG" | tee "$PIPE" >> "$ARCHIVE"Quale tecnica di awk calcola correttamente il percentile p95 a partire da un array ordinato di N valori di latenza?
Avete caricato N valori di latenza ordinati in un array awk v[1..N]. Quale espressione recupera correttamente il percentile p95?
Riepilogo della lezione: metriche e istogrammi dai flussi di log
In questa lezione avete creato un'intera pipeline di metriche direttamente in Bash:
- Frequenza delle richieste:
awkestrae il minuto dai timestamp e conta le occorrenze;tail -f+systime()fornisce una frequenza in tempo reale su una finestra scorrevole. - Percentili della latenza: estraete la colonna della latenza, applicate
sort -n, quindi selezionate la riga in posizioneceil(p/100 * N)usandoint(N * p + 0.9999)in awk. - Report dei primi N valori: la pipeline classica
awk | sort | uniq -c | sort -rn | head -Nfunziona per qualsiasi campo categoriale (percorso, IP, codice di stato). - Istogrammi ASCII: raggruppate i valori in intervalli, contate gli elementi di ciascun intervallo e dimensionate la lunghezza della barra in base al conteggio massimo, per visualizzare la distribuzione a colpo d'occhio.
- Fan-out con pipe denominate:
mkfifo+teeconsentono di archiviare i log grezzi e alimentare contemporaneamente i consumer delle metriche senza caricare il flusso in memoria.
Questi elementi costitutivi componibili eliminano la necessità di strumenti esterni durante gli incidenti e costituiscono la base di script di osservabilità leggeri, eseguibili ovunque sia disponibile Bash.
Domande Frequenti
La lezione «Calcolare metriche e istogrammi dai flussi di log» è gratuita?
Sì — il testo completo di «Calcolare metriche e istogrammi dai flussi di log» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso DevOps Bootcamp, passa a CoddyKit PRO. Il corso DevOps Bootcamp include 4 lezioni in totale.
Cosa imparerò in «Calcolare metriche e istogrammi dai flussi di log»?
Aggrregi tassi di richiesta, percentili e report top-N direttamente dai dati di log in streaming. Eserciti DevOps Bootcamp con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare DevOps Bootcamp?
Non è richiesta alcuna esperienza precedente. DevOps Bootcamp su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Calcolare metriche e istogrammi dai flussi di log»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione DevOps Bootcamp?
Sì. Ogni lezione DevOps Bootcamp include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Analizzare log web e applicativi su larga scala
- Seguire i log in tempo reale e generare avvisi in streaming
- Interrogare journald negli script con journalctl
- Calcolare metriche e istogrammi dai flussi di log