0Pricing
Linux Command Line & Bash Scripting Mastery · Lekcja

Obliczanie metryk i histogramów ze strumieni logów

Agreguj bezpośrednio ze strumieni danych logów częstość żądań, percentyle i raporty top-N.

Obliczanie metryk i histogramów ze strumieni logów to bezpłatna lekcja Linux Command Line & Bash Scripting Mastery na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Linux Command Line & Bash Scripting Mastery, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.

Dlaczego obliczać metryki z surowych dzienników?

Systemy produkcyjne generują tysiące wierszy dziennika na sekundę. Zamiast wysyłać surowe dzienniki do drogich platform analitycznych, mogą Państwo obliczać bezpośrednio w powłoce częstość żądań, percentyle i raporty Top-N — przy niemal zerowym koszcie.

  • Częstość żądań: Ile żądań na sekundę lub minutę obsługuje usługa?
  • Percentyle opóźnień: Jaki jest czas odpowiedzi p50/p95/p99?
  • Raporty Top-N: Które punkty końcowe, adresy IP lub kody błędów pojawiają się najczęściej?

Narzędzia powłoki, takie jak awk, sort, uniq i bc, tworzą wydajny, kompozycyjny potok, który pozwala uzyskać odpowiedzi na te pytania z bieżącego strumienia dziennika lub pliku historycznego bez opuszczania terminala.

Budowa typowego dziennika dostępu

Większość serwerów internetowych zapisuje dzienniki w Combined Log Format. Zrozumienie jego pól jest podstawą każdego potoku metryk:

127.0.0.1 - frank [10/Oct/2024:13:55:36 -0700] "GET /api/users HTTP/1.1" 200 2326 0.042
  • Pole 1: adres IP klienta
  • Pole 4 (w nawiasach): znacznik czasu
  • Pole 7 (w cudzysłowie): metoda HTTP + ścieżka
  • Pole 9: kod statusu
  • Pole 10: liczba bajtów odpowiedzi
  • Pole 11: czas odpowiedzi w sekundach (pole niestandardowe, nie zawsze obecne)

Za pomocą awk można odwoływać się do pól według pozycji ($1, $9 itd.). Pola znajdujące się w cudzysłowie są liczone jako jeden token tylko wtedy, gdy dzielenie zostanie przeprowadzone ostrożnie — należy opakować wiersz dziennika w awk -F'"' albo użyć kilku przebiegów.

Zliczanie liczby żądań na minutę

Aby obliczyć liczbę żądań na minutę, należy wyodrębnić część znacznika czasu oznaczającą minutę i zliczyć wystąpienia. Wzorzec [day/Mon/year:HH:MM określa przedział godziny i minuty.

Poniższy potok odczytuje access.log i wyświetla tabelę minuta → liczba żądań:

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

Częstość w przesuwanym oknie dla bieżącego strumienia

W przypadku śledzenia na żywo potrzebują Państwo przesuwanego okna. Sztuczka polega na przekazaniu tail -f potokiem do awk, który resetuje licznik co N sekund, korzystając z zegara systemowego (systime()).

Poniższy przykład wyświetla wiersz z częstością co 10 sekund:

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

Wyodrębnianie wartości opóźnień do obliczania percentyli

Obliczanie percentyli wymaga posortowania wszystkich zaobserwowanych wartości opóźnień. Standardowe podejście obejmuje:

  1. Wyodrębnienie kolumny opóźnienia do listy zwykłych liczb.
  2. Posortowanie liczb numerycznie.
  3. Wybranie wartości na właściwej pozycji za pomocą obliczenia liczby wierszy.

Poniższy skrypt wyodrębnia pole 11 (czas odpowiedzi w sekundach) i zapisuje je w pliku tymczasowym na potrzeby obliczenia percentyli w następnym kroku:

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

Obliczanie p50, p95 i p99 za pomocą awk

Po posortowaniu wartości opóźnień wybór percentyla sprowadza się do obliczenia: percentyl p znajduje się w wierszu ceil(p/100 * N). Sam program awk może wykonać to w jednym przebiegu po wczytaniu posortowanego pliku do tablicy:

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

Tworzenie raportu punktów końcowych Top-N

Raport Top-N odpowiada na pytanie: „które ścieżki są najczęściej wywoływane?”. Klasyczny idiom powłoki wygląda następująco:

  • awk drukuje interesujące pole (np. ścieżkę URL)
  • sort grupuje identyczne wartości
  • uniq -c zlicza kolejne duplikaty
  • sort -rn porządkuje według malejącej liczby wystąpień
  • head -n N wybiera N pierwszych wyników
#!/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 według kodu statusu: szybkie wykrywanie błędów

Kody statusu HTTP informują o kondycji usługi. Grupowanie wierszy dziennika według kodu statusu i ich zliczanie pokazuje, czy błędy występują sporadycznie, czy mają charakter systemowy.

Poniższy skrypt generuje zestawienie dla wszystkich przedziałów 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 -20

Histogramy ASCII za pomocą awk

Histogram tekstowy sprawia, że rozkłady opóźnień stają się natychmiast czytelne w terminalu lub dzienniku CI. Podejście obejmuje:

  1. Przypisanie każdej wartości opóźnienia do przedziału (np. 0–50 ms, 50–100 ms, …).
  2. Zliczenie obserwacji w każdym przedziale.
  3. Wyświetlenie paska złożonego ze znaków #, przeskalowanego względem maksymalnej liczby wystąpień.

Jest to niezwykle przydatne do wykrywania rozkładów dwumodalnych lub wartości odstających bez użycia narzędzia do tworzenia wykresów.

#!/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"
fi

Łączenie metryk: raport podsumowujący w jednym przebiegu

Produkcyjne runbooki często wymagają pojedynczego polecenia, które jednocześnie zwraca wszystkie najważniejsze metryki: częstość, percentyle opóźnień, najczęściej używane punkty końcowe i odsetek błędów. Mogą Państwo połączyć wszystkie dotychczas poznane elementy w jeden skrypt, który może wywołać człowiek lub system alertów.

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

Strumieniowe przetwarzanie metryk za pomocą potoków nazwanych i tee

W potokach obserwowalności często trzeba rozgałęzić strumień dziennika: zapisywać surowe wiersze na dysku i jednocześnie obliczać metryki. tee wraz z potokiem nazwanym (mkfifo) umożliwia to bez buforowania całego strumienia w pamięci.

  • mkfifo /tmp/log_pipe — tworzy potok nazwany
  • tee /tmp/log_pipe | metric_consumer & — rozdziela jedną gałąź do odbiorcy metryk
  • Druga gałąź zapisuje dane w pliku archiwum

Ten wzorzec rozdziela zapis na dysku od agregowania metryk i pozwala na niezależne ponowne uruchomienie każdej ze stron.

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

Która technika awk poprawnie oblicza percentyl p95 z posortowanej tablicy zawierającej N wartości opóźnienia?

Załadowano N posortowanych wartości opóźnienia do tablicy awk v[1..N]. Które wyrażenie poprawnie pobiera percentyl p95?

Podsumowanie lekcji: metryki i histogramy ze strumieni logów

W tej lekcji zbudowano kompletny potok metryk bezpośrednio w Bashu:

  • Przepływność żądań: awk wyodrębnia przedział minutowy ze znaczników czasu i zlicza wystąpienia; tail -f + systime() zapewnia bieżącą przepływność w przesuwanym oknie czasowym.
  • Percentyle opóźnienia: wyodrębnij kolumnę opóźnienia, użyj sort -n, a następnie wybierz wiersz o pozycji ceil(p/100 * N), korzystając w awk z wyrażenia int(N * p + 0.9999).
  • Raporty Top-N: klasyczny potok awk | sort | uniq -c | sort -rn | head -N działa dla dowolnego pola kategorialnego (ścieżki, adresu IP, kodu statusu).
  • Histogramy ASCII: przypisz wartości do przedziałów, zlicz elementy w każdym przedziale i przeskaluj długość słupka względem maksymalnej liczności przedziału, aby uzyskać szybki podgląd rozkładu.
  • Rozgałęzianie za pomocą nazwanych potoków: mkfifo + tee umożliwia jednoczesne archiwizowanie surowych logów i przekazywanie ich do odbiorców metryk bez ładowania strumienia do pamięci.

Te kompozycyjne elementy eliminują potrzebę korzystania z zewnętrznych narzędzi podczas incydentów i stanowią podstawę lekkich skryptów obserwowalności, które można uruchomić wszędzie tam, gdzie działa Bash.

Często zadawane pytania

Czy lekcja „Obliczanie metryk i histogramów ze strumieni logów” jest bezpłatna?

Tak — pełny tekst „Obliczanie metryk i histogramów ze strumieni logów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Linux Command Line & Bash Scripting Mastery, przejdź na CoddyKit PRO. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.

Co nauczysz się w „Obliczanie metryk i histogramów ze strumieni logów”?

Agreguj bezpośrednio ze strumieni danych logów częstość żądań, percentyle i raporty top-N. Ćwiczysz Linux Command Line & Bash Scripting Mastery z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Linux Command Line & Bash Scripting Mastery?

Nie wymagamy żadnego doświadczenia. Linux Command Line & Bash Scripting Mastery w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Obliczanie metryk i histogramów ze strumieni logów”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Linux Command Line & Bash Scripting Mastery?

Tak. Każda lekcja Linux Command Line & Bash Scripting Mastery zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Parsowanie logów internetowych i aplikacyjnych na dużą skalę
  2. Śledzenie logów w czasie rzeczywistym i alerty strumieniowe
  3. Odpytywanie journald za pomocą journalctl w skryptach
  4. Obliczanie metryk i histogramów ze strumieni logów
← Powrót do Linux Command Line & Bash Scripting Mastery