DevOps-bootcamp · Les

Web- en applicatielogs op grote schaal parseren

Haal statuscodes, latenties en clientvelden uit accesslogs met grep, cut en awk.

Les 1 van 413 stappen

Web- en applicatielogs op grote schaal parseren is een gratis DevOps-bootcamp-les op CoddyKit. Dit is les 1 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject DevOps-bootcamp. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus DevOps-bootcamp bevat in totaal 4 lessen.

Wat is een webtoegangslog?

Elke HTTP-server — Apache, Nginx, Caddy — schrijft voor elk verzoek één regel naar een toegangslog. Inzicht in de structuur van deze regels vormt de basis van alle werkzaamheden voor loganalyse.

Een typische regel in het Combined Log Format (CLF) ziet er zo uit:

  • IP-adres van de client — wie het verzoek heeft gedaan
  • Tijdstempel — wanneer het gebeurde
  • Verzoekregel — methode, pad, protocol
  • Statuscode — HTTP-antwoord (200, 404, 500…)
  • Verzonden bytes — grootte van de antwoordtekst
  • Referer — oorspronkelijke pagina
  • User-Agent — tekenreeks van de browser of bot

Voorbeeldregel uit /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"

Op grote schaal groeien deze bestanden tot miljoenen regels per dag. Het doel van deze les is om velden er efficiënt uit te halen, te filteren en te aggregeren met standaardgereedschappen van BASH.

Een live log bekijken met tail en grep

Inspecteer de log voordat je een pijplijn schrijft, zodat je de structuur begrijpt. Met tail kun je een live gegevensstroom bekijken; grep beperkt die onmiddellijk tot relevante regels.

Veelgebruikte patronen:

  • tail -n 1000 access.log — de laatste 1000 regels
  • tail -f access.log — in realtime volgen
  • tail -f access.log | grep '" 5' — alleen 5xx-fouten zodra ze binnenkomen

Het belangrijkste inzicht is dat grep zoekt in de volledige regel, dus het is belangrijk om je patroon te verankeren. Zo voorkom je met ' 500 ' (met spaties) dat je per ongeluk een URL-pad vindt waarin de tekenreeks 500 voorkomt.

#!/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] '

De statuscode extraheren met cut

cut splitst elke regel op basis van een scheidingsteken en drukt geselecteerde velden af. In het Combined Log Format staat de statuscode in veld 9 wanneer je op spaties splitst — maar door de aanhalingstekens rond de verzoekregel is het veiliger om vanaf een bekend anker te tellen.

Een betrouwbare truc: omdat de verzoekregel altijd tussen aanhalingstekens staat, is de statuscode altijd het eerste token na het afsluitende aanhalingsteken van het verzoekveld. Met cut -d'"' -f3 isoleer je alles na het aanhalingsteken van het verzoek; vervolgens selecteert een tweede cut -d' ' -f2 de statuscode.

Deze tweestapsbewerking met cut is een klassieke werkwijze voor CLF-logs — snel en zonder externe afhankelijkheden.

#!/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 -rn

Statuscodes tellen met awk

awk is krachtiger dan cut, omdat het status over meerdere regels heen kan bijhouden. Het gebruikelijke patroon om voorkomens te tellen is een associatieve array met als sleutel de waarde waarin je geïnteresseerd bent.

In CLF is veld $9 (op 1 gebaseerd en door spaties gescheiden) de statuscode. awk verwerkt elke regel, verhoogt een teller en drukt vervolgens een gesorteerd overzicht af in het END-blok.

Waarom zou je awk verkiezen boven cut | sort | uniq -c? Omdat awk dit in één enkele doorgang doet, zonder eerst het volledige bestand te sorteren — cruciaal wanneer de log honderden gigabytes groot is.

#!/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 -rn

Fouten filteren en IP-adressen van clients extraheren

Een van de meest voorkomende operationele taken is bepalen welke IP-adressen van clients de meeste fouten veroorzaken. Hierbij combineer je filteren (alleen foutregels) met velden extraheren (het IP-adres in veld 1).

De pijplijnstrategie:

  • Gebruik awk om in één stap op het statuscodebereik te filteren en het IP-adres te extraheren — vermijd een aparte grep-doorgang
  • Stuur de uitvoer door naar sort | uniq -c | sort -rn | head voor snel overzicht van de bovenste resultaten

Dit patroon is snel genoeg om op één server uit te voeren voor een logbestand van 10 GB, zonder het bestand in het geheugen te laden.

#!/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 -10

Reactievertraging uit applicatielogs parseren

Applicatieservers (Rails, Gunicorn, Express met morgan enzovoort) loggen vaak de duur van verzoeken. Nginx kan zo worden geconfigureerd dat het $request_time als extra veld aan het einde van elke regel uitvoert.

Een voorbeeld van een aangepaste Nginx-logindeling in nginx.conf:

log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time';

Zodra de vertraging in de log staat, kun je awk gebruiken om het gemiddelde, het maximum en percentielschattingen te berekenen over miljoenen verzoeken, zonder de gegevens in een database te laden.

#!/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.log

Een histogram van reactievertragingen maken met awk

Een enkel gemiddelde verbergt staartvertraging. Een histogram laat de verdeling zien — of de meeste verzoeken snel zijn en enkele zeer traag (lange staart), of dat de verdeling gelijkmatig is.

De truc is om elke waarde met gehelegetallenrekenkunde in awk in een afgerond bereik te plaatsen. Door met 1000 te vermenigvuldigen (seconden omzetten naar milliseconden) en vervolgens gehelegetallendeling te gebruiken, krijg je duidelijke bereikgrenzen.

Dit levert een tekstueel histogram op dat je rechtstreeks in een terminal kunt lezen. Dat is vaak sneller dan gegevens naar Grafana sturen voor een snel onderzoek.

#!/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 -n

User-Agent extraheren en bots detecteren

Het User-Agent-veld (veld 6 wanneer je splitst op ") identificeert clients. Crawlers, scrapers en schadelijke bots vervuilen vaak je meetgegevens en verhogen de foutaantallen. Door ze eruit te filteren krijg je een zuiverder beeld van verkeer van echte gebruikers.

Veelvoorkomende botsignaturen: bot, crawler, spider, curl, python-requests, Googlebot, Bingbot.

Gebruik grep -iv (hoofdletterongevoelig omgekeerd zoeken) om bekende bots uit te sluiten, of gebruik awk om te splitsen op " en rechtstreeks overeenkomsten te zoeken in het UA-veld.

#!/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 -15

Verkeer per eindpunt aggregeren

Weten welke eindpunten het meeste verkeer ontvangen — en de meeste fouten veroorzaken — helpt bij het prioriteren van optimalisatie en capaciteitsplanning. Het verzoekpad staat in het verzoekveld tussen aanhalingstekens.

Splits op ", neem veld 2 (de verzoekregel) en verwijder vervolgens de methode en het protocol om alleen het pad over te houden. Voor API's met padparameters zoals /users/12345 wil je ID's mogelijk ook normaliseren naar /users/:id met sed of een complexer awk-patroon.

#!/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 -20

Fouten met eindpunten correleren met awk

De krachtigste analyse in één doorgang combineert meerdere velden tegelijk: eindpunt, statuscode en eventueel reactievertraging. Associatieve arrays van awk met samengestelde waarden als sleutel maken dit overzichtelijk en snel.

Het onderstaande patroon telt 5xx-fouten per eindpunt in één doorgang — zonder tijdelijke bestanden en zonder tussentijdse sorteringen tot helemaal aan het einde. Dit is de aanpak die in scripts voor productie-observeerbaarheid wordt gebruikt wanneer je op een grote log binnen een minuut antwoorden nodig hebt.

#!/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 -20

Geroteerde en gecomprimeerde logs verwerken

Op de meeste servers worden logs dagelijks geroteerd. Oudere bestanden worden met gzip gecomprimeerd als access.log.1.gz, access.log.2.gz enzovoort. Standaardgereedschappen kunnen ze niet rechtstreeks lezen, maar twee aanpakken werken goed:

  • zcat — decomprimeert naar stdout en stuurt de uitvoer door naar je pijplijn
  • zgrep — zoekt rechtstreeks in gzip-bestanden zonder ze uit te pakken

Gebruik voor analyse van een volledige week aan logs uit zowel ongecomprimeerde als gecomprimeerde bestanden proces-substitutie of voeg bestanden samen met zcat. Het onderstaande fragment verwerkt de laatste 7 geroteerde bestanden plus de huidige live log in één aanroep van awk — tijdelijke bestanden zijn niet nodig.

#!/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 -rn

In welk awk-veld staat de HTTP-statuscode in het Combined Log Format?

Je schrijft een awk-one-liner om alleen HTTP 4xx-reacties uit een standaard Nginx-toegangslogboek in Combined Log Format te filteren (gescheiden door spaties, waarbij de aanvraagregel tussen aanhalingstekens staat). Welk veldnummer identificeert de HTTP-statuscode correct?

Samenvatting van de les: pijplijnen voor loganalyse

In deze les heb je met alleen standaardhulpprogramma's van BASH een complete gereedschapskist opgebouwd voor het op grote schaal analyseren van web- en applicatielogboeken.

Belangrijkste behandelde technieken:

  • Eerst de structuur — Combined Log Format heeft een voorspelbare veldindeling; als je die kent, kun je de invoer betrouwbaar opsplitsen met cut -d'"' of veldverwijzingen in awk.
  • Statuscodes extraheren — awk '{ count[$9]++ }' telt alle codes in één doorgang; filter met $9 ~ /^5/ op serverfouten.
  • Latentieanalyse — verwerk het aangepaste veld rt= met awk om gemiddelden, maximumwaarden en histogramintervallen te berekenen zonder extern hulpmiddel.
  • Analyse van clients en bots — splits op " met -F'"' om het User-Agent-veld te bereiken; leid de uitvoer door grep -iv om bots uit te sluiten voordat je gaat aggregeren.
  • Eindpunten normaliseren — gebruik gsub(/\/[0-9]+/, "/:id") binnen awk om paden met parameters samen te voegen voordat je gaat tellen.
  • Geroteerde logboeken — combineer cat en zcat in een subshell om alle bestanden met logboekrotaties in één pijplijndoorgang te verwerken.

Deze patronen kunnen worden gecombineerd: je kunt filteren, extraheren, normaliseren en aggregeren in één pijplijn die honderden miljoenen regels verwerkt op gangbare hardware. Als je deze basisbouwstenen beheerst, heb je voor ad-hoc onderzoek van incidenten zelden een speciale service voor logboekaggregatie nodig.

Gratis beginnen

Leer DevOps-bootcamp met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
142
Lessen
568

Veelgestelde vragen

Is de les “Web- en applicatielogs op grote schaal parseren” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad DevOps-bootcamp, waaronder “Web- en applicatielogs op grote schaal parseren”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus DevOps-bootcamp bevat in totaal 4 lessen.

Wat leer ik in “Web- en applicatielogs op grote schaal parseren”?

Haal statuscodes, latenties en clientvelden uit accesslogs met grep, cut en awk. Je oefent met DevOps-bootcamp door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met DevOps-bootcamp te beginnen?

Ervaring vooraf is niet nodig. DevOps-bootcamp op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.

Hoe lang duurt de les “Web- en applicatielogs op grote schaal parseren”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over DevOps-bootcamp?

Ja. Elke les over DevOps-bootcamp bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Web- en applicatielogs op grote schaal parseren
  2. Logs in realtime volgen en streamingwaarschuwingen
  3. journald doorzoeken met journalctl in scripts
  4. Statistieken en histogrammen uit logstreams berekenen
← Terug naar DevOps-bootcamp