TUI is now more optimized

This commit is contained in:
Sam
2026-01-29 01:46:17 -06:00
parent 1ab375593d
commit a6db1beaab

View File

@@ -1122,17 +1122,8 @@ show_dashboard() {
local snap_file="$INSTALL_DIR/traffic_stats/tracker_snapshot"
local data_file="$INSTALL_DIR/traffic_stats/cumulative_data"
if [ -s "$snap_file" ] || [ -s "$data_file" ]; then
# Get actual total connected clients from docker logs
local dash_clients=0
local dash_ps=$(docker ps --format '{{.Names}}' 2>/dev/null)
for ci in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $ci)
if echo "$dash_ps" | grep -q "^${cname}$"; then
local lg=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
local cn=$(echo "$lg" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
[[ "$cn" =~ ^[0-9]+$ ]] && dash_clients=$((dash_clients + cn))
fi
done
# Reuse connected count from show_status (already cached)
local dash_clients=${_total_connected:-0}
# Left column: Active Clients per country (estimated from snapshot distribution)
local left_lines=()
@@ -1164,13 +1155,14 @@ show_dashboard() {
# Right column: Top 5 Upload (cumulative outbound bytes per country)
local right_lines=()
if [ -s "$data_file" ]; then
local top5_upload
top5_upload=$(awk -F'|' '{if($1!="" && $3+0>0) print $3"|"$1}' "$data_file" 2>/dev/null | sort -t'|' -k1 -nr | head -5)
local all_upload
all_upload=$(awk -F'|' '{if($1!="" && $3+0>0) print $3"|"$1}' "$data_file" 2>/dev/null | sort -t'|' -k1 -nr)
local top5_upload=$(echo "$all_upload" | head -5)
local total_upload=0
if [ -n "$top5_upload" ]; then
if [ -n "$all_upload" ]; then
while IFS='|' read -r bytes co; do
total_upload=$((total_upload + bytes))
done < <(awk -F'|' '{if($1!="" && $3+0>0) print $3"|"$1}' "$data_file" 2>/dev/null)
done <<< "$all_upload"
fi
[ "$total_upload" -eq 0 ] && total_upload=1
if [ -n "$top5_upload" ]; then
@@ -1233,51 +1225,35 @@ show_dashboard() {
get_container_stats() {
# Get CPU and RAM usage across all conduit containers
# Returns: "CPU_PERCENT RAM_USAGE"
if [ "$CONTAINER_COUNT" -le 1 ]; then
local stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" conduit 2>/dev/null)
if [ -z "$stats" ]; then
echo "0% 0MiB"
else
echo "$stats"
fi
else
# Aggregate stats across all containers
local total_cpu=0
local total_mem=0
local mem_limit=""
local any_found=false
# Single docker stats call for all containers at once
local names=""
for i in $(seq 1 $CONTAINER_COUNT); do
local name=$(get_container_name $i)
local stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" "$name" 2>/dev/null)
if [ -n "$stats" ]; then
any_found=true
local cpu=$(echo "$stats" | awk '{print $1}' | tr -d '%')
total_cpu=$(awk -v a="$total_cpu" -v b="$cpu" 'BEGIN{printf "%.2f", a+b}')
# Parse mem: "123.4MiB / 1.5GiB"
local mem_used=$(echo "$stats" | awk '{print $2}')
if [ -z "$mem_limit" ]; then
mem_limit=$(echo "$stats" | awk '{print $4}')
fi
# Convert to MiB for summing
local mem_val=$(echo "$mem_used" | sed 's/[^0-9.]//g')
if echo "$mem_used" | grep -qi "gib"; then
mem_val=$(awk -v v="$mem_val" 'BEGIN{printf "%.1f", v*1024}')
fi
total_mem=$(awk -v a="$total_mem" -v b="$mem_val" 'BEGIN{printf "%.1f", a+b}')
fi
names+=" $(get_container_name $i)"
done
if [ "$any_found" = true ]; then
# Format mem back
local mem_display
if [ "$(echo "$total_mem" | awk '{print ($1 >= 1024)}')" = "1" ]; then
mem_display=$(awk -v m="$total_mem" 'BEGIN{printf "%.2fGiB", m/1024}')
else
mem_display="${total_mem}MiB"
fi
echo "${total_cpu}% ${mem_display} / ${mem_limit}"
else
local all_stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $names 2>/dev/null)
if [ -z "$all_stats" ]; then
echo "0% 0MiB"
fi
elif [ "$CONTAINER_COUNT" -le 1 ]; then
echo "$all_stats"
else
# Single awk to aggregate all container stats at once
echo "$all_stats" | awk '{
# CPU: strip % and sum
cpu = $1; gsub(/%/, "", cpu); total_cpu += cpu + 0
# Memory used: convert to MiB and sum
mem = $2; gsub(/[^0-9.]/, "", mem); mem += 0
if ($2 ~ /GiB/) mem *= 1024
else if ($2 ~ /KiB/) mem /= 1024
total_mem += mem
# Memory limit: take first one
if (mem_limit == "") mem_limit = $4
found = 1
} END {
if (!found) { print "0% 0MiB"; exit }
if (total_mem >= 1024) mem_display = sprintf("%.2fGiB", total_mem/1024)
else mem_display = sprintf("%.1fMiB", total_mem)
printf "%.2f%% %s / %s\n", total_cpu, mem_display, mem_limit
}'
fi
}
@@ -1329,24 +1305,29 @@ get_system_stats() {
local sys_ram_pct="N/A"
if command -v free &>/dev/null; then
# Output: used total percentage
local ram_data=$(free -m 2>/dev/null | awk '/^Mem:/{printf "%s %s %.2f%%", $3, $2, ($3/$2)*100}')
local ram_human=$(free -h 2>/dev/null | awk '/^Mem:/{print $3 " " $2}')
sys_ram_used=$(echo "$ram_human" | awk '{print $1}')
sys_ram_total=$(echo "$ram_human" | awk '{print $2}')
sys_ram_pct=$(echo "$ram_data" | awk '{print $3}')
# Single free -m call: MiB values for percentage + display
local free_out=$(free -m 2>/dev/null)
if [ -n "$free_out" ]; then
read -r sys_ram_used sys_ram_total sys_ram_pct <<< $(echo "$free_out" | awk '/^Mem:/{
used_mb=$3; total_mb=$2
pct = (total_mb > 0) ? (used_mb/total_mb)*100 : 0
if (total_mb >= 1024) { total_str=sprintf("%.1fGiB", total_mb/1024) } else { total_str=sprintf("%.1fMiB", total_mb) }
if (used_mb >= 1024) { used_str=sprintf("%.1fGiB", used_mb/1024) } else { used_str=sprintf("%.1fMiB", used_mb) }
printf "%s %s %.2f%%", used_str, total_str, pct
}')
fi
fi
echo "$sys_cpu $sys_ram_used $sys_ram_total $sys_ram_pct"
}
show_live_stats() {
# Check if any container is running
# Check if any container is running (single docker ps call)
local ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
local any_running=false
for i in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $i)
if docker ps 2>/dev/null | grep -q "[[:space:]]${cname}$"; then
if echo "$ps_cache" | grep -q "^${cname}$"; then
any_running=true
break
fi
@@ -1379,7 +1360,7 @@ show_live_stats() {
for i in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $i)
local status="${RED}Stopped${NC}"
docker ps 2>/dev/null | grep -q "[[:space:]]${cname}$" && status="${GREEN}Running${NC}"
echo "$ps_cache" | grep -q "^${cname}$" && status="${GREEN}Running${NC}"
echo -e " ${i}. ${cname} [${status}]"
done
echo ""
@@ -1733,7 +1714,8 @@ show_advanced_stats() {
while [ "$exit_stats" -eq 0 ]; do
local now=$(date +%s)
local term_height=$(tput lines 2>/dev/null || echo 24)
local term_height=$(stty size </dev/tty 2>/dev/null | awk '{print $1}')
[ -z "$term_height" ] || [ "$term_height" -lt 10 ] 2>/dev/null && term_height=$(tput lines 2>/dev/null || echo "${LINES:-24}")
local cycle_elapsed=$(( (now - cycle_start) % 15 ))
local time_until_next=$((15 - cycle_elapsed))
@@ -1762,16 +1744,28 @@ show_advanced_stats() {
local total_mem_mib=0 first_mem_limit=""
echo -e "${CYAN}║${NC} ${GREEN}CONTAINER${NC} ${DIM}|${NC} ${YELLOW}NETWORK${NC} ${DIM}|${NC} ${MAGENTA}TRACKER${NC}\033[K"
# Single docker stats call for all running containers
local adv_running_names=""
for ci in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $ci)
echo "$docker_ps_cache" | grep -q "^${cname}$" && adv_running_names+=" $cname"
done
local adv_all_stats=""
if [ -n "$adv_running_names" ]; then
adv_all_stats=$(docker stats --no-stream --format "{{.Name}}|{{.CPUPerc}}|{{.MemUsage}}" $adv_running_names 2>/dev/null)
fi
for ci in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $ci)
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
container_count=$((container_count + 1))
local stats=$(docker stats --no-stream --format "{{.CPUPerc}}|{{.MemUsage}}" "$cname" 2>/dev/null)
local cpu=$(echo "$stats" | cut -d'|' -f1 | tr -d '%')
local stats=$(echo "$adv_all_stats" | grep "^${cname}|" 2>/dev/null)
local cpu=$(echo "$stats" | cut -d'|' -f2 | tr -d '%')
[[ "$cpu" =~ ^[0-9.]+$ ]] && total_cpu=$(awk -v a="$total_cpu" -v b="$cpu" 'BEGIN{printf "%.2f", a+b}')
local cmem_str=$(echo "$stats" | cut -d'|' -f2 | awk '{print $1}')
local cmem_str=$(echo "$stats" | cut -d'|' -f3 | awk '{print $1}')
local cmem_val=$(echo "$cmem_str" | sed 's/[^0-9.]//g')
local cmem_unit=$(echo "$cmem_str" | sed 's/[0-9.]//g')
if [[ "$cmem_val" =~ ^[0-9.]+$ ]]; then
@@ -1781,7 +1775,7 @@ show_advanced_stats() {
esac
total_mem_mib=$(awk -v a="$total_mem_mib" -v b="$cmem_val" 'BEGIN{printf "%.2f", a+b}')
fi
[ -z "$first_mem_limit" ] && first_mem_limit=$(echo "$stats" | cut -d'|' -f2 | awk -F'/' '{print $2}' | xargs)
[ -z "$first_mem_limit" ] && first_mem_limit=$(echo "$stats" | cut -d'|' -f3 | awk -F'/' '{print $2}' | xargs)
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
@@ -1961,7 +1955,8 @@ show_peers() {
while [ $stop_peers -eq 0 ]; do
local now=$(date +%s)
local term_height=$(tput lines 2>/dev/null || echo 24)
local term_height=$(stty size </dev/tty 2>/dev/null | awk '{print $1}')
[ -z "$term_height" ] || [ "$term_height" -lt 10 ] 2>/dev/null && term_height=$(tput lines 2>/dev/null || echo "${LINES:-24}")
local cycle_elapsed=$(( (now - cycle_start) % 15 ))
local time_left=$((15 - cycle_elapsed))
@@ -2185,24 +2180,36 @@ show_status() {
if echo "$docker_ps_cache" | grep -q "[[:space:]]${cname}$"; then
_c_running[$i]=true
running_count=$((running_count + 1))
local logs=$(docker logs --tail 1000 "$cname" 2>&1 | grep "STATS" | tail -1)
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "STATS" | tail -1)
if [ -n "$logs" ]; then
local c_connecting=$(echo "$logs" | sed -n 's/.*Connecting:[[:space:]]*\([0-9]*\).*/\1/p')
local c_connected=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
# Single awk to extract all 5 fields, pipe-delimited
IFS='|' read -r c_connecting c_connected c_up_val c_down_val c_uptime_val <<< $(echo "$logs" | awk '{
cing=0; conn=0; up=""; down=""; ut=""
for(j=1;j<=NF;j++){
if($j=="Connecting:") cing=$(j+1)+0
else if($j=="Connected:") conn=$(j+1)+0
else if($j=="Up:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Down:/)break; up=up (up?" ":"") $k}}
else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}}
else if($j=="Uptime:"){for(k=j+1;k<=NF;k++){ut=ut (ut?" ":"") $k}}
}
printf "%d|%d|%s|%s|%s", cing, conn, up, down, ut
}')
_c_conn[$i]="${c_connected:-0}"
_c_cing[$i]="${c_connecting:-0}"
_c_up[$i]=$(echo "$logs" | sed -n 's/.*Up:[[:space:]]*\([^|]*\).*/\1/p' | xargs)
_c_down[$i]=$(echo "$logs" | sed -n 's/.*Down:[[:space:]]*\([^|]*\).*/\1/p' | xargs)
_c_up[$i]="${c_up_val}"
_c_down[$i]="${c_down_val}"
total_connecting=$((total_connecting + ${c_connecting:-0}))
total_connected=$((total_connected + ${c_connected:-0}))
if [ -z "$uptime" ]; then
uptime=$(echo "$logs" | sed -n 's/.*Uptime:[[:space:]]*\(.*\)/\1/p' | xargs)
uptime="${c_uptime_val}"
fi
fi
fi
done
local connecting=$total_connecting
local connected=$total_connected
# Export for parent function to reuse (avoids duplicate docker logs calls)
_total_connected=$total_connected
# Aggregate upload/download across all containers
local upload=""
@@ -2824,6 +2831,20 @@ manage_containers() {
# Per-container stats table
local docker_ps_cache=$(docker ps --format '{{.Names}}' 2>/dev/null)
# Single docker stats call for all running containers (instead of per-container)
local all_dstats=""
local running_names=""
for ci in $(seq 1 $CONTAINER_COUNT); do
local cname=$(get_container_name $ci)
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
running_names+=" $cname"
fi
done
if [ -n "$running_names" ]; then
all_dstats=$(docker stats --no-stream --format "{{.Name}} {{.CPUPerc}} {{.MemUsage}}" $running_names 2>/dev/null)
fi
printf " ${BOLD}%-2s %-11s %-8s %-7s %-8s %-8s %-6s %-7s${NC}${EL}\n" \
"#" "Container" "Status" "Clients" "Up" "Down" "CPU" "RAM"
echo -e " ${CYAN}─────────────────────────────────────────────────────────${NC}${EL}"
@@ -2837,20 +2858,28 @@ manage_containers() {
if echo "$docker_ps_cache" | grep -q "^${cname}$"; then
status_text="Running"
status_color="${GREEN}"
local logs=$(docker logs --tail 1000 "$cname" 2>&1 | grep "STATS" | tail -1)
local logs=$(docker logs --tail 50 "$cname" 2>&1 | grep "STATS" | tail -1)
if [ -n "$logs" ]; then
local conn=$(echo "$logs" | sed -n 's/.*Connected:[[:space:]]*\([0-9]*\).*/\1/p')
local cing=$(echo "$logs" | sed -n 's/.*Connecting:[[:space:]]*\([0-9]*\).*/\1/p')
IFS='|' read -r conn cing mc_up mc_down <<< $(echo "$logs" | awk '{
cing=0; conn=0; up=""; down=""
for(j=1;j<=NF;j++){
if($j=="Connecting:") cing=$(j+1)+0
else if($j=="Connected:") conn=$(j+1)+0
else if($j=="Up:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Down:/)break; up=up (up?" ":"") $k}}
else if($j=="Down:"){for(k=j+1;k<=NF;k++){if($k=="|"||$k~/Uptime:/)break; down=down (down?" ":"") $k}}
}
printf "%d|%d|%s|%s", conn, cing, up, down
}')
c_clients="${conn:-0}/${cing:-0}"
c_up=$(echo "$logs" | sed -n 's/.*Up:[[:space:]]*\([^|]*\).*/\1/p' | xargs)
c_down=$(echo "$logs" | sed -n 's/.*Down:[[:space:]]*\([^|]*\).*/\1/p' | xargs)
c_up="${mc_up:-"-"}"
c_down="${mc_down:-"-"}"
[ -z "$c_up" ] && c_up="-"
[ -z "$c_down" ] && c_down="-"
fi
local dstats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" "$cname" 2>/dev/null)
if [ -n "$dstats" ]; then
c_cpu=$(echo "$dstats" | awk '{print $1}')
c_ram=$(echo "$dstats" | awk '{print $2}')
local dstats_line=$(echo "$all_dstats" | grep "^${cname} " 2>/dev/null)
if [ -n "$dstats_line" ]; then
c_cpu=$(echo "$dstats_line" | awk '{print $2}')
c_ram=$(echo "$dstats_line" | awk '{print $3}')
fi
else
status_text="Stopped"
@@ -4263,3 +4292,5 @@ main() {
# REACHED END OF SCRIPT - VERSION 1.1
# ###############################################################################
main "$@"