From 7591795d2d3d24b9e1bce8e8d67a25006dd90ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=BCmel=20Branko?= Date: Fri, 2 Jan 2026 18:43:02 +0100 Subject: [PATCH] shaolin dojo doktor --- crumbpages-doktor.sh | 131 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 127 insertions(+), 4 deletions(-) diff --git a/crumbpages-doktor.sh b/crumbpages-doktor.sh index 10f3fb4..09a8b30 100755 --- a/crumbpages-doktor.sh +++ b/crumbpages-doktor.sh @@ -487,6 +487,127 @@ EOF } +# ----------------------------------------------------------------------------- +# Modul: Shaolin Log Doktor (Logfile Analyse) +# ----------------------------------------------------------------------------- +function shaolin_doktor() { + echo -e "${BLUE}--- 🥋 Shaolin Log Doktor ---${NC}" + export LOG_RC="${CRUMB_CACHE_DIR}/shaolin_doktor_${CRUMB_SESSION_ID}.rc" + + cat > "${LOG_RC}" << 'EOF' +if [ -f /etc/bashrc ]; then source /etc/bashrc; fi +if [ -f ~/.bashrc ]; then source ~/.bashrc; fi + +export PS1="\[\033[0;35m\](🥋 Shaolin) \u@\h:\w$ \[\033[0m\]" + +function shaolin_help() { + echo "Willkommen im Dojo der Log-Analyse." + echo "" + echo "Befehle:" + echo " log_analyze -> Detaillierte Time-Range Analyse" + echo " log_p90 -> Berechne 90. Perzentil (Latenz)" + echo " log_top -> Top URLs & User Agents" + echo " log_errors -> Finde Fehler (40x, 50x, CRITICAL)" + echo "" + echo " Tipp: Nutzung oft mit access.log" +} + +function log_analyze() { + FILE="${1:-access.log}" + if [ ! -f "$FILE" ]; then echo "❌ Datei nicht gefunden: $FILE"; return; fi + + echo "🥋 Analysiere Zeit-Verteilung für: $FILE" + + # Check if we can find relevant data columns (heuristic) + # Asking user or guessing is hard in script, assuming standard formats or user knows + echo "⚠️ Annahme: $(NF-1) ist Antwortzeit in Sekunden (Nginx Default oft am Ende)" + + TOTAL_REQ=$(cat "$FILE" | grep -v elapsed | wc -l) + echo "Total Requests: $TOTAL_REQ" + + awk -v treq="$TOTAL_REQ" '{ + val = $(NF-1) + if (val < 0.5) a[1]++; + else if(val >= 0.5 && val < 1) a[2]++; + else if(val >= 1 && val < 2) a[3]++; + else if(val >= 2 && val < 5) a[4]++; + else if(val >= 5 && val < 10) a[5]++; + else if(val >= 10 && val < 60) a[6]++; + else if(val >= 60 && val < 300) a[7]++; + else if(val >= 300) a[8]++; + } END { + labels[1]="0 - 500 ms"; + labels[2]="500 ms - 1 sec"; + labels[3]="1 sec - 2 secs"; + labels[4]="2 secs - 5 secs"; + labels[5]="5 secs - 10 secs"; + labels[6]="10 secs - 60 secs"; + labels[7]="1 min - 5 mins"; + labels[8]="> 5 mins"; + + for (i=1;i<=8;i++) { + if (a[i] == "") a[i]=0; + printf "%-20s , %d (%d%%)\n", labels[i], a[i], int(a[i]*100/treq) + } + }' "$FILE" +} + +function log_p90() { + FILE="${1:-access.log}" + if [ ! -f "$FILE" ]; then echo "❌ Datei nicht gefunden: $FILE"; return; fi + + echo "🥋 Berechne P90 Latenz für: $FILE" + + # Create temp file with just the times + cat "$FILE" | grep -v '^#' | awk '{print $(NF-1)}' | grep "[0-9]" | sort -n > /tmp/sl_csv.$$ + N=$(wc -l < /tmp/sl_csv.$$) + + if [ "$N" -eq 0 ]; then echo "Keine Datenpunkte."; rm /tmp/sl_csv.$$; return; fi + + P90_IDX=$(echo "$N * 0.9" | bc 2>/dev/null | awk -F'.' '{print $1}') + if [ -z "$P90_IDX" ] || [ "$P90_IDX" -eq 0 ]; then P90_IDX=1; fi + + VAL=$(awk "NR==$P90_IDX" /tmp/sl_csv.$$) + + echo "📊 P90 Request Time: ${VAL}s" + echo " (90% aller Requests waren schneller als dies)" + + rm /tmp/sl_csv.$$ +} + +function log_top() { + FILE="${1:-access.log}" + if [ ! -f "$FILE" ]; then echo "❌ Datei nicht gefunden: $FILE"; return; fi + + echo "🏆 Top 5 URLs:" + cat "$FILE" | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -n 5 + echo "" + echo "🕵️ Top 5 User Agents:" + cat "$FILE" | awk '{print "User-Agent="$(NF)}' | sort | uniq -c | sort -nr | head -n 5 + echo "" + echo "🔢 HTTP Status Codes:" + cat "$FILE" | awk '{print "Code="$(NF-2)}' | sort | uniq -c | sort -nr +} + +function log_errors() { + FILE="${1:-access.log}" + if [ ! -f "$FILE" ]; then echo "❌ Datei nicht gefunden: $FILE"; return; fi + + echo "🚨 Suche nach Standard-Fehlern..." + grep -E "error|CRITICAL|FATAL|Exception" "$FILE" | head -n 20 + echo "..." + echo "(Zeige max 20 Treffer. Nutze 'grep' für mehr)" +} + +echo "" +shaolin_help +EOF + + bash --rcfile "${LOG_RC}" + rm -f "${LOG_RC}" +} + + # ----------------------------------------------------------------------------- # Hauptmenü # ----------------------------------------------------------------------------- @@ -501,9 +622,10 @@ while true; do echo "5) 🔐 Remote Tools (SSH / SCP)" echo "6) 🛠️ General Tools (Shell)" echo "7) 🧠 Qdrant Doktor (Vektor DB)" - echo "8) 👋 Beenden" + echo "8) 🥋 Shaolin Log Doktor (Logfile Analyse)" + echo "9) 👋 Beenden" echo "" - read -p "Auswahl [1-8]: " CHOICE + read -p "Auswahl [1-9]: " CHOICE case $CHOICE in 1) git_doktor ;; @@ -513,7 +635,8 @@ while true; do 5) remote_doktor ;; 6) tools_doktor ;; 7) qdrant_doktor ;; - 8) echo "Ahoi!"; exit 0 ;; - *) echo "Bitte 1-8 wählen."; sleep 1 ;; + 8) shaolin_doktor ;; + 9) echo "Ahoi!"; exit 0 ;; + *) echo "Bitte 1-9 wählen."; sleep 1 ;; esac done