cleanup: ui::pad_mb removal, watch alignment fixes, endpoint cache fallback
- ui::rule::list_row: inline padding math replaces ui::pad_mb (major perf gain)
- ui:⌚:fw_row/wg_row: drop ui::pad_mb for fw/wg labels (always 2 chars)
- watch: endpoint fallback via monitor::get_cached_endpoint
- watch: _poll_handshakes sorts by ts descending (most recent first)
- watch: empty endpoint uses - not — (avoids multi-byte padding issues)
- ui.sh: UTF-8 extra byte constants (_UI_EMDASH_EXTRA, _UI_ARROW_EXTRA, _UI_BULLET_EXTRA)
This commit is contained in:
parent
5c2e16e358
commit
3058750c3d
9 changed files with 98 additions and 76 deletions
|
|
@ -108,6 +108,9 @@ function cmd::watch::_poll_handshakes() {
|
||||||
local filter_name="${1:-}" filter_type="${2:-}" filter_peers="${3:-}"
|
local filter_name="${1:-}" filter_type="${2:-}" filter_peers="${3:-}"
|
||||||
local w_client="${4:-20}" w_dest="${5:-18}"
|
local w_client="${4:-20}" w_dest="${5:-18}"
|
||||||
|
|
||||||
|
# Collect rows with sort key before printing
|
||||||
|
local -a rows=()
|
||||||
|
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
local public_key ts
|
local public_key ts
|
||||||
public_key=$(echo "$line" | awk '{print $1}')
|
public_key=$(echo "$line" | awk '{print $1}')
|
||||||
|
|
@ -142,20 +145,34 @@ function cmd::watch::_poll_handshakes() {
|
||||||
|
|
||||||
local ts_fmt
|
local ts_fmt
|
||||||
ts_fmt=$(fmt::datetime_short "$ts")
|
ts_fmt=$(fmt::datetime_short "$ts")
|
||||||
|
|
||||||
|
# Resolve endpoint — try wg show first, fall back to endpoint cache
|
||||||
local endpoint
|
local endpoint
|
||||||
endpoint=$(monitor::endpoint_for_key "$public_key")
|
endpoint=$(monitor::endpoint_for_key "$public_key")
|
||||||
|
|
||||||
# Resolve endpoint
|
if [[ -z "$endpoint" ]]; then
|
||||||
|
endpoint=$(monitor::get_cached_endpoint "$client_name")
|
||||||
|
fi
|
||||||
|
|
||||||
local endpoint_display
|
local endpoint_display
|
||||||
endpoint_display=$(resolve::ip "${endpoint:-}")
|
endpoint_display=$(resolve::ip "${endpoint:-}")
|
||||||
[[ -z "$endpoint_display" ]] && endpoint_display="${endpoint:-—}"
|
[[ -z "$endpoint_display" ]] && endpoint_display="${endpoint:--}"
|
||||||
|
|
||||||
ui::watch::wg_row "$ts_fmt" "$client_name" "$endpoint_display" "handshake" \
|
# Build row with ts prefix for sorting
|
||||||
"$w_client" "$w_dest"
|
local row
|
||||||
|
row=$(ui::watch::wg_row "$ts_fmt" "$client_name" "$endpoint_display" "handshake" \
|
||||||
|
"$w_client" "$w_dest")
|
||||||
|
rows+=("${ts}|${row}")
|
||||||
|
|
||||||
done < <(wg show "$(config::interface)" latest-handshakes 2>/dev/null)
|
done < <(wg show "$(config::interface)" latest-handshakes 2>/dev/null)
|
||||||
}
|
|
||||||
|
|
||||||
|
# Sort by ts descending (most recent first) and print
|
||||||
|
if [[ ${#rows[@]} -gt 0 ]]; then
|
||||||
|
printf '%s\n' "${rows[@]}" | sort -t'|' -k1,1rn | while IFS= read -r entry; do
|
||||||
|
printf "%s\n" "${entry#*|}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
# ============================================
|
# ============================================
|
||||||
# Event Tailer
|
# Event Tailer
|
||||||
# ============================================
|
# ============================================
|
||||||
|
|
@ -243,8 +260,6 @@ function cmd::watch::_tail_events() {
|
||||||
local now; now=$(date +%s)
|
local now; now=$(date +%s)
|
||||||
local last="${_WATCH_LAST_WG[$wg_key]:-0}"
|
local last="${_WATCH_LAST_WG[$wg_key]:-0}"
|
||||||
|
|
||||||
# Handshakes — only show if gap > 5min (new session)
|
|
||||||
# Attempts — shorter window (30s) since each attempt is meaningful
|
|
||||||
local window=30
|
local window=30
|
||||||
[[ "$event" == "handshake" ]] && window="${WG_HANDSHAKE_CHECK_TIME_SEC:-300}"
|
[[ "$event" == "handshake" ]] && window="${WG_HANDSHAKE_CHECK_TIME_SEC:-300}"
|
||||||
|
|
||||||
|
|
@ -254,12 +269,15 @@ function cmd::watch::_tail_events() {
|
||||||
local ts_fmt
|
local ts_fmt
|
||||||
ts_fmt=$(fmt::datetime_short "$(json::iso_to_ts "$ts" 2>/dev/null || echo 0)")
|
ts_fmt=$(fmt::datetime_short "$(json::iso_to_ts "$ts" 2>/dev/null || echo 0)")
|
||||||
|
|
||||||
# Resolve endpoint
|
# Resolve endpoint — fall back to endpoint cache if empty
|
||||||
local endpoint_display
|
local endpoint_resolved
|
||||||
endpoint_display=$(resolve::ip "${endpoint:-}")
|
endpoint_resolved=$(resolve::ip "${endpoint:-}")
|
||||||
[[ -z "$endpoint_display" ]] && endpoint_display="${endpoint:-—}"
|
if [[ -z "$endpoint_resolved" && -n "$endpoint" ]]; then
|
||||||
|
endpoint_resolved="$endpoint"
|
||||||
|
fi
|
||||||
|
[[ -z "$endpoint_resolved" ]] && endpoint_resolved="-"
|
||||||
|
|
||||||
ui::watch::wg_row "$ts_fmt" "$client" "$endpoint_display" "$event" \
|
ui::watch::wg_row "$ts_fmt" "$client" "$endpoint_resolved" "$event" \
|
||||||
"$w_client" "$w_dest"
|
"$w_client" "$w_dest"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,6 +3,12 @@
|
||||||
UI_ROW_WIDTH=${UI_ROW_WIDTH:-20}
|
UI_ROW_WIDTH=${UI_ROW_WIDTH:-20}
|
||||||
UI_SECTION_WIDTH=${UI_SECTION_WIDTH:-44}
|
UI_SECTION_WIDTH=${UI_SECTION_WIDTH:-44}
|
||||||
|
|
||||||
|
# UTF-8 multi-byte character extras (bash ${#} counts bytes, not chars)
|
||||||
|
# extra = byte_length - visible_char_length
|
||||||
|
_UI_EMDASH_EXTRA=2 # — (em dash) 3 bytes, 1 visible
|
||||||
|
_UI_ARROW_EXTRA=2 # → (right arrow) 3 bytes, 1 visible
|
||||||
|
_UI_BULLET_EXTRA=1 # · (middle dot) 2 bytes, 1 visible
|
||||||
|
|
||||||
function ui::row() {
|
function ui::row() {
|
||||||
local label="$1" value="$2" width="${3:-$UI_ROW_WIDTH}"
|
local label="$1" value="$2" width="${3:-$UI_ROW_WIDTH}"
|
||||||
printf " %-${width}s %s\n" "${label}:" "$value"
|
printf " %-${width}s %s\n" "${label}:" "$value"
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ function monitor::cache_endpoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function monitor::get_cached_endpoint() {
|
function monitor::get_cached_endpoint() {
|
||||||
local client="$1"
|
local client="${1:-}"
|
||||||
json::get "$ENDPOINT_CACHE" "$client"
|
json::get "$ENDPOINT_CACHE" "$client"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,16 +95,15 @@ function ui::watch::fw_row() {
|
||||||
local ts="${1:-}" client="${2:-}" dest_display="${3:-}" \
|
local ts="${1:-}" client="${2:-}" dest_display="${3:-}" \
|
||||||
w_client="${4:-20}" w_dest="${5:-18}"
|
w_client="${4:-20}" w_dest="${5:-18}"
|
||||||
|
|
||||||
local ts_pad
|
# "fw" is always 2 visible chars — no padding needed
|
||||||
ts_pad=$(printf "%-11s" "$ts")
|
local src="${_UI_WATCH_FW_COLOR}fw\033[0m"
|
||||||
|
|
||||||
local src
|
local ts_pad client_pad dest_pad_n
|
||||||
src=$(ui::pad_mb "${_UI_WATCH_FW_COLOR}fw\033[0m" 2)
|
ts_pad=$(printf "%-11s" "$ts")
|
||||||
local client_pad dest_pad_n
|
|
||||||
client_pad=$(printf "%-${w_client}s" "$client")
|
client_pad=$(printf "%-${w_client}s" "$client")
|
||||||
dest_pad_n=$(( w_dest - ${#dest_display} ))
|
dest_pad_n=$(( w_dest - ${#dest_display} ))
|
||||||
[[ $dest_pad_n -lt 0 ]] && dest_pad_n=0
|
[[ $dest_pad_n -lt 0 ]] && dest_pad_n=0
|
||||||
# echo "DEBUG fw: ts_bytes=${#ts} src_bytes=${#src} client='$client'(${#client}) client_pad_bytes=${#client_pad}" >&2
|
|
||||||
printf " %s %b %s \033[1;31m→\033[0m %s%*s \033[1;31mdrop\033[0m\n" \
|
printf " %s %b %s \033[1;31m→\033[0m %s%*s \033[1;31mdrop\033[0m\n" \
|
||||||
"$ts_pad" "$src" "$client_pad" "$dest_display" "$dest_pad_n" ""
|
"$ts_pad" "$src" "$client_pad" "$dest_display" "$dest_pad_n" ""
|
||||||
}
|
}
|
||||||
|
|
@ -113,35 +112,31 @@ function ui::watch::wg_row() {
|
||||||
local ts="${1:-}" client="${2:-}" endpoint="${3:-}" event="${4:-}" \
|
local ts="${1:-}" client="${2:-}" endpoint="${3:-}" event="${4:-}" \
|
||||||
w_client="${5:-20}" w_endpoint="${6:-18}"
|
w_client="${5:-20}" w_endpoint="${6:-18}"
|
||||||
|
|
||||||
local ts_pad
|
|
||||||
ts_pad=$(printf "%-11s" "$ts")
|
|
||||||
|
|
||||||
local event_color
|
local event_color
|
||||||
case "$event" in
|
case "$event" in
|
||||||
handshake) event_color="\033[1;32m" ;;
|
handshake) event_color="\033[1;32m" ;;
|
||||||
attempt) event_color="\033[1;31m" ;;
|
attempt) event_color="\033[1;31m" ;;
|
||||||
*) event_color="\033[0;37m" ;;
|
*) event_color="\033[0;37m" ;;
|
||||||
esac
|
esac
|
||||||
local src
|
|
||||||
src=$(ui::pad_mb "${_UI_WATCH_WG_COLOR}wg\033[0m" 2)
|
|
||||||
|
|
||||||
case "$event" in
|
# "wg" is always 2 visible chars — no padding needed
|
||||||
handshake) src="\033[1;32m" ;; # green
|
local src="${_UI_WATCH_WG_COLOR}wg\033[0m"
|
||||||
attempt) src="\033[1;31m" ;; # red
|
|
||||||
*) src="\033[0;37m" ;; # gray
|
|
||||||
esac
|
|
||||||
local src_colored="${src}wg\033[0m"
|
|
||||||
|
|
||||||
local client_pad endpoint_pad_n
|
# Use "-" not "—" to avoid multi-byte padding issues
|
||||||
|
local endpoint_display="${endpoint:--}"
|
||||||
|
|
||||||
|
local ts_pad client_pad endpoint_pad_n
|
||||||
|
ts_pad=$(printf "%-11s" "$ts")
|
||||||
client_pad=$(printf "%-${w_client}s" "$client")
|
client_pad=$(printf "%-${w_client}s" "$client")
|
||||||
endpoint_pad_n=$(( w_endpoint - ${#endpoint} ))
|
endpoint_pad_n=$(( w_endpoint - ${#endpoint_display} ))
|
||||||
[[ $endpoint_pad_n -lt 0 ]] && endpoint_pad_n=0
|
[[ $endpoint_pad_n -lt 0 ]] && endpoint_pad_n=0
|
||||||
# echo "DEBUG wg: ts_bytes=${#ts} src_bytes=${#src} client='$client'(${#client}) client_pad_bytes=${#client_pad}" >&2
|
|
||||||
printf " %s %b %s %s%*s %b%s\033[0m\n" \
|
printf " %s %b %s %s%*s %b%s\033[0m\n" \
|
||||||
"$ts_pad" "$src_colored" "$client_pad" "$endpoint" "$endpoint_pad_n" "" \
|
"$ts_pad" "$src" "$client_pad" "$endpoint_display" "$endpoint_pad_n" "" \
|
||||||
"$event_color" "$event"
|
"$event_color" "$event"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ui::watch::header_table() {
|
function ui::watch::header_table() {
|
||||||
printf "\n %-20s %-8s %-22s %-28s %-14s %s\n" \
|
printf "\n %-20s %-8s %-22s %-28s %-14s %s\n" \
|
||||||
"TIME" "SOURCE" "CLIENT" "DESTINATION/ENDPOINT" "EVENT" "STATUS"
|
"TIME" "SOURCE" "CLIENT" "DESTINATION/ENDPOINT" "EVENT" "STATUS"
|
||||||
|
|
|
||||||
|
|
@ -331,20 +331,23 @@ function ui::rule::list_row() {
|
||||||
extends_indicator=" \033[2m↳ ${extends_display}\033[0m"
|
extends_indicator=" \033[2m↳ ${extends_display}\033[0m"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Allows column — green +N if >0, dim +0 if zero
|
# Allows — green +N, padded to 5 visible chars
|
||||||
|
# Append spaces after reset code so printf doesn't miscount
|
||||||
local allows_str
|
local allows_str
|
||||||
if [[ "$n_allows" -gt 0 ]]; then
|
if [[ "$n_allows" -gt 0 ]]; then
|
||||||
allows_str=$(ui::pad_mb "\033[1;32m+${n_allows}\033[0m" 5)
|
printf -v allows_str "\033[1;32m+%s\033[0m" "$n_allows"
|
||||||
|
allows_str="${allows_str}$(printf '%*s' "$(( 4 - ${#n_allows} ))" '')"
|
||||||
else
|
else
|
||||||
allows_str=$(ui::pad_mb "\033[2m+0\033[0m" 5)
|
printf -v allows_str "\033[2m+0\033[0m " # "+0" = 2 visible + 3 spaces = 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Blocks column — red -N if >0, dim -0 if zero
|
# Blocks — red -N, padded to 5 visible chars
|
||||||
local blocks_str
|
local blocks_str
|
||||||
if [[ "$n_blocks" -gt 0 ]]; then
|
if [[ "$n_blocks" -gt 0 ]]; then
|
||||||
blocks_str=$(ui::pad_mb "\033[1;31m-${n_blocks}\033[0m" 5)
|
printf -v blocks_str "\033[1;31m-%s\033[0m" "$n_blocks"
|
||||||
|
blocks_str="${blocks_str}$(printf '%*s' "$(( 4 - ${#n_blocks} ))" '')"
|
||||||
else
|
else
|
||||||
blocks_str=$(ui::pad_mb "\033[2m-0\033[0m" 5)
|
printf -v blocks_str "\033[2m-0\033[0m " # "-0" = 2 visible + 3 spaces = 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Peers — dim if zero
|
# Peers — dim if zero
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue