#!/bin/bash
# wowa-stundenrapport — eine Zeile je abgelaufener Stunde: Speicher, Zugriffe, Traffic.
#
# Anlass (2026-09-07): der Speicher lag als Reihe vor (wowa-memtrend, alle 10 min),
# Zugriffe und Traffic aber nur als Rohprotokoll. Fuer einen Stundenrapport musste
# ich deshalb 26 Stunden aus ~30 gepackten Dateien je Knoten neu zusammenrechnen —
# minutenlang, und die gepackte Historie faellt irgendwann der Rotation zum Opfer.
# Hier wird stattdessen einmal je Stunde verdichtet, solange die Zeilen noch
# unkomprimiert dastehen.
#
# Warum HH:05 und die VORIGE Stunde: um HH:00 ist die Stunde noch nicht zu Ende,
# und um 00:05 liegt die 23-Uhr-Stunde bereits in der von logrotate umbenannten
# Datei. Beide Faelle deckt derselbe Fund ab, weil er sich nach dem STUNDENBEGINN
# richtet und nicht nach einer festen Spanne: gesucht wird jede Datei, die seither
# beschrieben wurde. Eine Protokolldatei ohne Verkehr in dieser Stunde faellt
# damit heraus — sie hat auch keine Zeilen darin.
#
# Die Vorfilterung mit `grep -F` auf den Stundenstempel ist der Grund, warum das
# billig bleibt: die laufende Tagesdatei auf .10 hat abends dreistellige MB, ein
# Festtext-Durchlauf kostet Zehntelsekunden. Ein Regex ueber alles waere hier
# hundertmal teurer — die Zerlegung mit sed sieht danach nur noch die Treffer.
#
# Aufruf ohne Argument = die vorige Stunde. Mit Argument (alles, was `date -d`
# versteht, z.B. "2026-09-06 14:00") wird diese eine Stunde nachgetragen — dann
# auch aus den bereits gepackten Dateien. Doppelte Zeilen schliesst die Pruefung
# unten aus, der Nachtrag ist also gefahrlos wiederholbar.
#
# ACHTUNG beim Nachtragen einer Reihe: `date -d "2026-09-06 06:00 +3 hours"`
# liest `+3` als ZEITZONE, nicht als Verschiebung — die Zeile landet dann unter
# einem falschen Stempel, ohne dass irgendetwas scheitert (ab `+25` wird es zur
# ungueltigen Zone und faellt endlich auf). Richtig ist die Epoche:
#     B=$(date -d "2026-09-06 10:00" +%s)
#     for h in $(seq 0 20); do wowa-stundenrapport "@$((B + h*3600))"; done
#
# ACHTUNG bei der Protokollspalte: H1 und H2 stehen als "HTTP/1.1" und
# "HTTP/2.0" im Protokoll, H3 aber als "HTTP/3" OHNE Unternummer. Ein Vergleich
# auf den vollen Text zaehlt H3 deshalb nie — und weil H3 auf .10 monatelang
# abgeschaltet war, sah die Null genauso aus wie das richtige Ergebnis. Hier
# wird darum auf das PRAEFIX geprueft, nicht auf Gleichheit. Aufgefallen am
# 09.09.2026 beim Wiedereinschalten von H3.
#
# Bewusst NICHT in ein Verzeichnis, das wowa-edge selbst beschreibt
# (lhs_log_ext-Schreiberthread → unbegrenzte Warteschlange), sondern nach
# /var/log/wowa-diag wie die uebrigen Diagnosereihen.
set -u

OUT=/var/log/wowa-diag/stundenrapport.csv
TREND=/var/log/wowa-diag/memtrend.csv
LOGDIR=/var/log/wowa-edge

mkdir -p "$(dirname "$OUT")"

# --- Zielstunde: die vorige, in beiden Schreibweisen -------------------------
# Der Monatsname kommt aus einer festen Tabelle, NICHT aus `date +%b`: das
# Zugriffsprotokoll steht immer englisch, die Knoten laufen aber deutsch.
WANN=${1:--1 hour}
date -d "$WANN" >/dev/null 2>&1 || { echo "unlesbare Zeitangabe: $WANN" >&2; exit 2; }
ZEIT_CSV=$(date -d "$WANN" '+%Y-%m-%d %H')            # wie in memtrend.csv
ANFANG=$(date -d "$WANN" '+%Y-%m-%d %H:00:00')        # Stundenbeginn, fuer den Dateifund
TAG=$(date -d "$WANN" '+%d'); STD=$(date -d "$WANN" '+%H')
JAHR=$(date -d "$WANN" '+%Y'); MNR=$(date -d "$WANN" '+%m')
set -- Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
eval "MON=\${$((10#$MNR))}"
STEMPEL="[$TAG/$MON/$JAHR:$STD:"                       # wie im Zugriffsprotokoll

# schon geschrieben? (Timer-Nachhol-Lauf, Handstart)
if [ -s "$OUT" ] && grep -q "^$ZEIT_CSV;" "$OUT"; then exit 0; fi

# --- Speicher: der letzte Messpunkt innerhalb der Stunde ---------------------
MI=""; GL=""; RSS=""; EST=""; CPU=""
if [ -r "$TREND" ]; then
  read -r MI GL RSS EST CPU <<<"$(awk -F';' -v z="$ZEIT_CSV" '
      substr($1,1,13) == z { mi=$5; gl=$6; rss=$4; est=$7; cpu=$10 }
      END { print mi, gl, rss, est, cpu }' "$TREND")"
fi

# --- Zugriffe, Traffic, Protokollverteilung ----------------------------------
Z=0; B=0; H1=0; H2=0; H3=0; F=0
if [ -d "$LOGDIR" ]; then
  read -r Z B H1 H2 H3 F <<<"$(
    find "$LOGDIR" -maxdepth 1 -name '*access*' -newermt "$ANFANG" -print0 2>/dev/null |
    while IFS= read -r -d '' f; do
      case "$f" in *.gz) zcat -- "$f" ;; *) cat -- "$f" ;; esac
    done 2>/dev/null |
    grep -F "$STEMPEL" |
    sed -n 's/.*"[^"]*\(HTTP\/[0-9.]*\)" \([0-9][0-9][0-9]\) \([0-9-]*\) .*/\1 \2 \3/p' |
    awk '{ n++
           if ($3 ~ /^[0-9]+$/) b += $3
           if      ($1 ~ /^HTTP\/1/) h1++
           else if ($1 ~ /^HTTP\/2/) h2++
           else if ($1 ~ /^HTTP\/3/) h3++
           if ($2 ~ /^[45]/) f++ }
         END { printf "%d %d %d %d %d %d\n", n, b, h1, h2, h3, f }')"
fi

[ -s "$OUT" ] || echo "zeit;mimalloc_mib;glibc_mib;rss_mib;estab;cpu_s;zugriffe;bytes;h1;h2;h3;fehler" > "$OUT"
echo "$ZEIT_CSV;$MI;$GL;$RSS;$EST;$CPU;$Z;$B;$H1;$H2;$H3;$F" >> "$OUT"
