A Python port of the Invisible Internet Project (I2P)
1#!/bin/bash
2# Monitor I2P router health endpoint during live test.
3# Polls every 30 seconds, writes timestamped JSON to a log file.
4# Usage: bash tools/monitor_router.sh [duration_minutes] [interval_seconds]
5
6DURATION_MIN=${1:-60}
7INTERVAL_SEC=${2:-30}
8LOG_FILE="$(dirname "$0")/router_monitor.log"
9HEALTH_URL="http://localhost:9701"
10
11TOTAL_POLLS=$(( DURATION_MIN * 60 / INTERVAL_SEC ))
12
13echo "=== I2P Router Monitor ===" | tee "$LOG_FILE"
14echo "Started: $(date -Iseconds)" | tee -a "$LOG_FILE"
15echo "Duration: ${DURATION_MIN}min, Interval: ${INTERVAL_SEC}s, Polls: ${TOTAL_POLLS}" | tee -a "$LOG_FILE"
16echo "---" | tee -a "$LOG_FILE"
17
18for i in $(seq 1 $TOTAL_POLLS); do
19 TS=$(date -Iseconds)
20 RESPONSE=$(curl -s --max-time 5 "$HEALTH_URL" 2>&1)
21 EXIT_CODE=$?
22
23 if [ $EXIT_CODE -ne 0 ]; then
24 echo "[$TS] poll=$i CURL_FAILED exit=$EXIT_CODE" | tee -a "$LOG_FILE"
25 else
26 # Extract key fields for the summary line
27 STATE=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('state','?'))" 2>/dev/null)
28 UPTIME=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('uptime_seconds',0))" 2>/dev/null)
29 PEERS=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('peer_count',0))" 2>/dev/null)
30 ATTEMPTED=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('peers_attempted',0))" 2>/dev/null)
31 SUCCESSFUL=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('peers_successful',0))" 2>/dev/null)
32 FAILED=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('peers_failed',0))" 2>/dev/null)
33 NETDB=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('netdb_routerinfos',0))" 2>/dev/null)
34 NETDB_DISK=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('netdb_disk',0))" 2>/dev/null)
35 RSS=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('resources',{}).get('rss_mb',0))" 2>/dev/null)
36 CPU=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('resources',{}).get('cpu_percent','?'))" 2>/dev/null)
37 I2NP_RX=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('i2np_messages_received',0))" 2>/dev/null)
38 I2NP_TX=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('i2np_messages_sent',0))" 2>/dev/null)
39
40 echo "[$TS] poll=$i state=$STATE uptime=${UPTIME}s peers=$PEERS attempted=$ATTEMPTED ok=$SUCCESSFUL fail=$FAILED netdb=$NETDB disk=$NETDB_DISK rss=${RSS}MB cpu=${CPU}% i2np_rx=$I2NP_RX i2np_tx=$I2NP_TX" | tee -a "$LOG_FILE"
41
42 # Write full JSON every 5th poll for detailed analysis
43 if [ $(( i % 5 )) -eq 0 ]; then
44 echo " FULL_JSON: $RESPONSE" >> "$LOG_FILE"
45 fi
46 fi
47
48 # Check if container is still running
49 if ! podman ps --filter name=i2p-router-test --format "{{.Status}}" | grep -q "Up"; then
50 echo "[$TS] CONTAINER STOPPED — aborting monitor" | tee -a "$LOG_FILE"
51 echo "Last container logs:" | tee -a "$LOG_FILE"
52 podman logs --tail 20 i2p-router-test 2>&1 | tee -a "$LOG_FILE"
53 break
54 fi
55
56 sleep $INTERVAL_SEC
57done
58
59echo "---" | tee -a "$LOG_FILE"
60echo "Finished: $(date -Iseconds)" | tee -a "$LOG_FILE"
61echo "Final health:" | tee -a "$LOG_FILE"
62curl -s --max-time 5 "$HEALTH_URL" 2>&1 | python3 -m json.tool 2>&1 | tee -a "$LOG_FILE"