feat: logs endpoint annotation, alignment, descending sort
- fw/wg events: raw_ip → resolved_name annotation (dim) - fw events: endpoint column with pre-resolved names (two-pass render) - fw events: raw IP:port dim suffix after service name - wg events: endpoint annotation in logs (same as watch) - fw/wg: descending sort default, --ascending/--descending flags - wg events: gap/offline indicator, threshold * 2 for offline label - fw_row: no-endpoint rows show dim — placeholder for alignment - section headers: dynamic width via tput cols
This commit is contained in:
parent
d5de344d99
commit
fb33aa1b6d
5 changed files with 176 additions and 60 deletions
|
|
@ -225,34 +225,65 @@ function cmd::logs::show_fw_events() {
|
||||||
"$filter_dest_ip" "$filter_dest_port" \
|
"$filter_dest_ip" "$filter_dest_port" \
|
||||||
"$sort_order" \
|
"$sort_order" \
|
||||||
2>/dev/null)
|
2>/dev/null)
|
||||||
|
|
||||||
[[ -z "$data" ]] && return 0
|
[[ -z "$data" ]] && return 0
|
||||||
|
|
||||||
# Measure column widths
|
# ── Pass 1: resolve endpoints and measure widths ──
|
||||||
local w_client=16 w_dest=20
|
local w_client=16 w_dest=20 w_endpoint=0
|
||||||
while IFS='|' read -r ts client dest_ip dest_port proto svc count; do
|
local resolved_data=""
|
||||||
|
|
||||||
|
while IFS='|' read -r ts client dest_ip dest_port proto svc count src_endpoint; do
|
||||||
[[ -z "$ts" ]] && continue
|
[[ -z "$ts" ]] && continue
|
||||||
|
|
||||||
|
# Measure client
|
||||||
(( ${#client} > w_client )) && w_client=${#client}
|
(( ${#client} > w_client )) && w_client=${#client}
|
||||||
local dest_display host_name
|
|
||||||
host_name=$(hosts::resolve_ip "$dest_ip")
|
# Build svc_display (for w_dest measurement)
|
||||||
if [[ -n "$host_name" ]]; then
|
local svc_display=""
|
||||||
dest_display="$host_name"
|
if [[ -n "$svc" ]]; then
|
||||||
elif [[ -n "$svc" ]]; then
|
[[ -n "$dest_port" ]] && svc_display="${svc}/${proto}" \
|
||||||
[[ -n "$dest_port" ]] && dest_display="${svc}/${proto}" || dest_display="${svc} (${proto})"
|
|| svc_display="${svc} (${proto})"
|
||||||
else
|
else
|
||||||
[[ -n "$dest_port" ]] && dest_display="${dest_ip}:${dest_port}/${proto}" || dest_display="${dest_ip} (${proto})"
|
[[ -n "$dest_port" ]] && svc_display="${dest_ip}:${dest_port}/${proto}" \
|
||||||
|
|| svc_display="${dest_ip} (${proto})"
|
||||||
fi
|
fi
|
||||||
(( ${#dest_display} > w_dest )) && w_dest=${#dest_display}
|
|
||||||
|
# Build raw_suffix plain (no ANSI) for w_dest measurement
|
||||||
|
local raw_plain=""
|
||||||
|
if [[ -n "$svc" ]]; then
|
||||||
|
[[ -n "$dest_port" ]] && raw_plain=" (${dest_ip}:${dest_port})" \
|
||||||
|
|| raw_plain=" (${dest_ip})"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local full_dest_len=$(( ${#svc_display} + ${#raw_plain} ))
|
||||||
|
(( full_dest_len > w_dest )) && w_dest=$full_dest_len
|
||||||
|
|
||||||
|
# Resolve endpoint once
|
||||||
|
local src_resolved=""
|
||||||
|
if [[ -n "$src_endpoint" ]]; then
|
||||||
|
src_resolved=$(resolve::ip "$src_endpoint" 2>/dev/null || true)
|
||||||
|
[[ "$src_resolved" == "$src_endpoint" ]] && src_resolved=""
|
||||||
|
# Measure endpoint column: raw IP + " → resolved"
|
||||||
|
local ep_display_len=${#src_endpoint}
|
||||||
|
[[ -n "$src_resolved" ]] && ep_display_len=$(( ep_display_len + 4 + ${#src_resolved} ))
|
||||||
|
(( ep_display_len > w_endpoint )) && w_endpoint=$ep_display_len
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolved_data+="${ts}|${client}|${dest_ip}|${dest_port}|${proto}|${svc}|${count}|${src_endpoint}|${src_resolved}"$'\n'
|
||||||
done <<< "$data"
|
done <<< "$data"
|
||||||
(( w_client += 2 ))
|
|
||||||
(( w_dest += 2 ))
|
(( w_client += 2 ))
|
||||||
|
(( w_dest += 2 ))
|
||||||
|
[[ "$w_endpoint" -gt 0 ]] && (( w_endpoint += 2 ))
|
||||||
|
|
||||||
|
# ── Pass 2: render ──
|
||||||
ui::logs::fw_section_header
|
ui::logs::fw_section_header
|
||||||
while IFS='|' read -r ts client dest_ip dest_port proto svc count; do
|
while IFS='|' read -r ts client dest_ip dest_port proto svc count src_endpoint src_resolved; do
|
||||||
[[ -z "$ts" ]] && continue
|
[[ -z "$ts" ]] && continue
|
||||||
ui::logs::fw_row "$ts" "$client" "$dest_ip" "$dest_port" \
|
ui::logs::fw_row "$ts" "$client" "$dest_ip" "$dest_port" \
|
||||||
"$proto" "$svc" "$count" "$w_client" "$w_dest"
|
"$proto" "$svc" "$count" "$w_client" "$w_dest" \
|
||||||
done <<< "$data"
|
"$src_endpoint" "$src_resolved" "$w_endpoint"
|
||||||
|
done <<< "$resolved_data"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,21 +308,26 @@ function cmd::logs::show_wg_events() {
|
||||||
local resolved_data=""
|
local resolved_data=""
|
||||||
while IFS='|' read -r ts client endpoint event count gap_seconds; do
|
while IFS='|' read -r ts client endpoint event count gap_seconds; do
|
||||||
[[ -z "$ts" ]] && continue
|
[[ -z "$ts" ]] && continue
|
||||||
local endpoint_display
|
(( ${#client} > w_client )) && w_client=${#client}
|
||||||
endpoint_display=$(resolve::ip "$endpoint")
|
local ep_len=${#endpoint}
|
||||||
[[ -z "$endpoint_display" ]] && endpoint_display="$endpoint"
|
[[ -z "$endpoint" ]] && ep_len=1
|
||||||
resolved_data+="${ts}|${client}|${endpoint_display}|${event}|${count}|${gap_seconds}"$'\n'
|
(( ep_len > w_endpoint )) && w_endpoint=$ep_len
|
||||||
(( ${#client} > w_client )) && w_client=${#client}
|
|
||||||
(( ${#endpoint_display} > w_endpoint )) && w_endpoint=${#endpoint_display}
|
# Resolve endpoint
|
||||||
|
local resolved=""
|
||||||
|
[[ -n "$endpoint" ]] && resolved=$(resolve::ip "$endpoint" 2>/dev/null || true)
|
||||||
|
[[ "$resolved" == "$endpoint" ]] && resolved=""
|
||||||
|
|
||||||
|
resolved_data+="${ts}|${client}|${endpoint}|${event}|${count}|${gap_seconds}|${resolved}"$'\n'
|
||||||
done <<< "$data"
|
done <<< "$data"
|
||||||
(( w_client += 2 ))
|
(( w_client += 2 ))
|
||||||
(( w_endpoint += 2 ))
|
(( w_endpoint += 18 ))
|
||||||
|
|
||||||
ui::logs::wg_section_header
|
ui::logs::wg_section_header
|
||||||
while IFS='|' read -r ts client endpoint event count gap_seconds; do
|
while IFS='|' read -r ts client endpoint event count gap_seconds resolved; do
|
||||||
[[ -z "$ts" ]] && continue
|
[[ -z "$ts" ]] && continue
|
||||||
ui::logs::wg_row "$ts" "$client" "$endpoint" "$event" \
|
ui::logs::wg_row "$ts" "$client" "$endpoint" "$event" \
|
||||||
"$count" "$w_client" "$w_endpoint" "$gap_seconds"
|
"$count" "$w_client" "$w_endpoint" "$gap_seconds" "$resolved"
|
||||||
done <<< "$resolved_data"
|
done <<< "$resolved_data"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1690,7 +1690,8 @@ commands = {
|
||||||
args[7] if len(args) > 7 else '',
|
args[7] if len(args) > 7 else '',
|
||||||
args[8] if len(args) > 8 else '',
|
args[8] if len(args) > 8 else '',
|
||||||
args[9] if len(args) > 9 else '',
|
args[9] if len(args) > 9 else '',
|
||||||
args[10] if len(args) > 10 else 'desc'),
|
args[10] if len(args) > 10 else 'desc',
|
||||||
|
args[11] if len(args) > 11 else ''),
|
||||||
'wg_events': lambda args: __import__('lib.events', fromlist=['wg_events']).wg_events(
|
'wg_events': lambda args: __import__('lib.events', fromlist=['wg_events']).wg_events(
|
||||||
args[0], args[1], args[2],
|
args[0], args[1], args[2],
|
||||||
args[3] if len(args) > 3 else '50',
|
args[3] if len(args) > 3 else '50',
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -22,7 +22,8 @@ from lib.util import (
|
||||||
# ──────────────────────────────────────────
|
# ──────────────────────────────────────────
|
||||||
|
|
||||||
def fw_events(file, filter_ip, filter_type, clients_dir, net_file,
|
def fw_events(file, filter_ip, filter_type, clients_dir, net_file,
|
||||||
limit, collapse='1', since='', filter_dest_ip='', filter_dest_port='', sort_order='desc'):
|
limit, collapse='1', since='', filter_dest_ip='',
|
||||||
|
filter_dest_port='', sort_order='desc', endpoint_cache_file=''):
|
||||||
"""
|
"""
|
||||||
Format firewall drop events with dedup, counts, and service annotation.
|
Format firewall drop events with dedup, counts, and service annotation.
|
||||||
|
|
||||||
|
|
@ -42,6 +43,14 @@ def fw_events(file, filter_ip, filter_type, clients_dir, net_file,
|
||||||
net_data = load_net_data(net_file)
|
net_data = load_net_data(net_file)
|
||||||
hosts_data = load_hosts_data(None) # hosts lookup done in bash for now
|
hosts_data = load_hosts_data(None) # hosts lookup done in bash for now
|
||||||
|
|
||||||
|
endpoint_cache = {}
|
||||||
|
if endpoint_cache_file and os.path.exists(endpoint_cache_file):
|
||||||
|
try:
|
||||||
|
with open(endpoint_cache_file) as f:
|
||||||
|
endpoint_cache = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
since_dt = parse_since(since) if since else None
|
since_dt = parse_since(since) if since else None
|
||||||
|
|
||||||
def _reverse(dest_ip, dest_port, proto):
|
def _reverse(dest_ip, dest_port, proto):
|
||||||
|
|
@ -129,9 +138,10 @@ def fw_events(file, filter_ip, filter_type, clients_dir, net_file,
|
||||||
output = list(reversed(output))
|
output = list(reversed(output))
|
||||||
for hour_key, dt in output:
|
for hour_key, dt in output:
|
||||||
client, dst, port, proto, svc_name, _ = hour_key
|
client, dst, port, proto, svc_name, _ = hour_key
|
||||||
count = hourly[hour_key]
|
count = hourly[hour_key]
|
||||||
ts_fmt = fmt_ts_hour(dt.isoformat())
|
ts_fmt = fmt_ts_hour(hourly_ts[hour_key].isoformat())
|
||||||
print(f"{ts_fmt}|{client}|{dst}|{port}|{proto}|{svc_name}|{count}")
|
src_endpoint = endpoint_cache.get(client, '')
|
||||||
|
print(f"{ts_fmt}|{client}|{dst}|{port}|{proto}|{svc_name}|{count}|{src_endpoint}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Detailed — consecutive dedup only
|
# Detailed — consecutive dedup only
|
||||||
|
|
@ -172,9 +182,14 @@ def fw_events(file, filter_ip, filter_type, clients_dir, net_file,
|
||||||
proto_num = int(e.get('ip.protocol', 0))
|
proto_num = int(e.get('ip.protocol', 0))
|
||||||
proto = PROTO_MAP.get(proto_num, str(proto_num))
|
proto = PROTO_MAP.get(proto_num, str(proto_num))
|
||||||
client = ip_to_name.get(src, src)
|
client = ip_to_name.get(src, src)
|
||||||
svc_name = _reverse(dst, port, proto)
|
svc_name = reverse_lookup(net_data, dst, port, proto)
|
||||||
ts_fmt = fmt_ts(e.get('timestamp', ''))
|
src_endpoint = endpoint_cache.get(client, '')
|
||||||
print(f"{ts_fmt}|{client}|{dst}|{port}|{proto}|{svc_name}|{count}")
|
try:
|
||||||
|
dt = datetime.fromisoformat(e.get('timestamp', ''))
|
||||||
|
ts_fmt = dt.strftime(DATETIME_FMT)
|
||||||
|
except Exception:
|
||||||
|
ts_fmt = e.get('timestamp', '')
|
||||||
|
print(f"{ts_fmt}|{client}|{dst}|{port}|{proto}|{svc_name}|{count}|{src_endpoint}")
|
||||||
|
|
||||||
|
|
||||||
# ──────────────────────────────────────────
|
# ──────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,15 @@ function ui::logs::build_dest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ui::logs::fw_section_header() {
|
function ui::logs::fw_section_header() {
|
||||||
|
local cols=$(( $(tput cols 2>/dev/null || echo 80) - 4 ))
|
||||||
printf " Firewall Drops\n"
|
printf " Firewall Drops\n"
|
||||||
printf " %s\n" "$(printf '─%.0s' {1..42})"
|
printf " %s\n" "$(printf '─%.0s' $(seq 1 $cols))"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ui::logs::wg_section_header() {
|
function ui::logs::wg_section_header() {
|
||||||
|
local cols=$(( $(tput cols 2>/dev/null || echo 80) - 4 ))
|
||||||
printf " WireGuard Events\n"
|
printf " WireGuard Events\n"
|
||||||
printf " %s\n" "$(printf '─%.0s' {1..42})"
|
printf " %s\n" "$(printf '─%.0s' $(seq 1 $cols))"
|
||||||
}
|
}
|
||||||
|
|
||||||
function ui::logs::fw_section_header_table() {
|
function ui::logs::fw_section_header_table() {
|
||||||
|
|
@ -35,17 +37,67 @@ function ui::logs::wg_section_header_table() {
|
||||||
function ui::logs::fw_row() {
|
function ui::logs::fw_row() {
|
||||||
local ts="${1:-}" client="${2:-}" dest_ip="${3:-}" dest_port="${4:-}" \
|
local ts="${1:-}" client="${2:-}" dest_ip="${3:-}" dest_port="${4:-}" \
|
||||||
proto="${5:-}" svc_name="${6:-}" count="${7:-1}" \
|
proto="${5:-}" svc_name="${6:-}" count="${7:-1}" \
|
||||||
w_client="${8:-20}" w_dest="${9:-30}"
|
w_client="${8:-20}" w_dest="${9:-30}" \
|
||||||
local dest_display
|
src_endpoint="${10:-}" src_resolved="${11:-}" w_endpoint="${12:-0}"
|
||||||
dest_display=$(ui::logs::build_dest "$dest_ip" "$dest_port" "$proto" "$svc_name")
|
|
||||||
|
local ts_pad client_pad
|
||||||
|
ts_pad=$(printf "%-11s" "$ts")
|
||||||
|
client_pad=$(printf "%-${w_client}s" "$client")
|
||||||
|
|
||||||
|
# ── Source endpoint — always render at w_endpoint width ──
|
||||||
|
local src_padded=""
|
||||||
|
if [[ "$w_endpoint" -gt 0 ]]; then
|
||||||
|
if [[ -n "$src_endpoint" ]]; then
|
||||||
|
local src_colored="$src_endpoint"
|
||||||
|
[[ -n "$src_resolved" ]] && \
|
||||||
|
src_colored="${src_endpoint} \033[2m→ ${src_resolved}\033[0m"
|
||||||
|
src_padded=$(ui::pad_mb "$src_colored" "$w_endpoint")
|
||||||
|
else
|
||||||
|
# No endpoint — use dim dash padded to w_endpoint
|
||||||
|
src_padded=$(ui::pad_mb "\033[2m—\033[0m" "$w_endpoint")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Destination ──
|
||||||
|
local svc_display=""
|
||||||
|
local raw_suffix=""
|
||||||
|
if [[ -n "$svc_name" ]]; then
|
||||||
|
[[ -n "$dest_port" ]] && svc_display="${svc_name}/${proto}" \
|
||||||
|
|| svc_display="${svc_name} (${proto})"
|
||||||
|
[[ -n "$dest_port" ]] && raw_suffix=" \033[2m(${dest_ip}:${dest_port})\033[0m" \
|
||||||
|
|| raw_suffix=" \033[2m(${dest_ip})\033[0m"
|
||||||
|
else
|
||||||
|
[[ -n "$dest_port" ]] && svc_display="${dest_ip}:${dest_port}/${proto}" \
|
||||||
|
|| svc_display="${dest_ip} (${proto})"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pad so count aligns — based on full dest (svc + raw_suffix plain length)
|
||||||
|
local raw_plain=""
|
||||||
|
[[ -n "$svc_name" && -n "$dest_port" ]] && raw_plain=" (${dest_ip}:${dest_port})"
|
||||||
|
[[ -n "$svc_name" && -z "$dest_port" ]] && raw_plain=" (${dest_ip})"
|
||||||
|
local full_dest_len=$(( ${#svc_display} + ${#raw_plain} ))
|
||||||
|
local dest_pad_n=$(( w_dest - full_dest_len ))
|
||||||
|
[[ $dest_pad_n -lt 0 ]] && dest_pad_n=0
|
||||||
|
|
||||||
|
# ── Count ──
|
||||||
local count_suffix=""
|
local count_suffix=""
|
||||||
[[ "$count" -gt 1 ]] && count_suffix=" \033[2m(x${count})\033[0m"
|
[[ "$count" -gt 1 ]] && count_suffix=" \033[2m(x${count})\033[0m"
|
||||||
local client_pad dest_pad_n
|
|
||||||
client_pad=$(printf "%-${w_client}s" "$client")
|
# ── Render ──
|
||||||
dest_pad_n=$(( w_dest - ${#dest_display} ))
|
if [[ "$w_endpoint" -gt 0 ]]; then
|
||||||
[[ $dest_pad_n -lt 0 ]] && dest_pad_n=0
|
printf " %s %s %b \033[1;31m→\033[0m %s%b%*s%b\n" \
|
||||||
printf " %s %s \033[1;31m→\033[0m %s%*s%b\n" \
|
"$ts_pad" "$client_pad" \
|
||||||
"$ts" "$client_pad" "$dest_display" "$dest_pad_n" "" "$count_suffix"
|
"$src_padded" \
|
||||||
|
"$svc_display" "$raw_suffix" \
|
||||||
|
"$dest_pad_n" "" \
|
||||||
|
"$count_suffix"
|
||||||
|
else
|
||||||
|
printf " %s %s \033[1;31m→\033[0m %s%b%*s%b\n" \
|
||||||
|
"$ts_pad" "$client_pad" \
|
||||||
|
"$svc_display" "$raw_suffix" \
|
||||||
|
"$dest_pad_n" "" \
|
||||||
|
"$count_suffix"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function ui::logs::fw_row_table() {
|
function ui::logs::fw_row_table() {
|
||||||
|
|
@ -58,39 +110,51 @@ function ui::logs::fw_row_table() {
|
||||||
function ui::logs::wg_row() {
|
function ui::logs::wg_row() {
|
||||||
local ts="${1:-}" client="${2:-}" endpoint="${3:-}" event="${4:-}" \
|
local ts="${1:-}" client="${2:-}" endpoint="${3:-}" event="${4:-}" \
|
||||||
count="${5:-1}" w_client="${6:-20}" w_endpoint="${7:-20}" \
|
count="${5:-1}" w_client="${6:-20}" w_endpoint="${7:-20}" \
|
||||||
gap_seconds="${8:-}"
|
gap_seconds="${8:-}" resolved="${9:-}"
|
||||||
|
|
||||||
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 count_suffix=""
|
local count_suffix=""
|
||||||
[[ "$count" -gt 1 ]] && count_suffix=" \033[2m(x${count})\033[0m"
|
[[ "$count" -gt 1 ]] && count_suffix=" \033[2m(x${count})\033[0m"
|
||||||
|
|
||||||
# Gap suffix — only for handshakes with a meaningful gap
|
# Gap suffix — offline label only when gap > threshold * 2
|
||||||
local gap_suffix=""
|
local gap_suffix=""
|
||||||
if [[ "$event" == "handshake" && -n "$gap_seconds" && "$gap_seconds" -gt 0 ]]; then
|
if [[ "$event" == "handshake" && -n "$gap_seconds" && "$gap_seconds" -gt 0 ]]; then
|
||||||
local gap_int="$gap_seconds"
|
local gap_int="$gap_seconds"
|
||||||
local threshold="${WG_HANDSHAKE_CHECK_TIME_SEC:-300}"
|
local threshold="${WG_HANDSHAKE_CHECK_TIME_SEC:-300}"
|
||||||
local offline_label=""
|
local offline_label=""
|
||||||
[[ "$gap_int" -gt "$threshold" ]] && offline_label=" offline"
|
[[ "$gap_int" -gt $(( threshold * 2 )) ]] && offline_label=" offline"
|
||||||
if (( gap_int >= 3600 )); then
|
if (( gap_int >= 3600 )); then
|
||||||
gap_suffix=" \033[2m↑ $(( gap_int / 3600 ))h${offline_label}\033[0m"
|
gap_suffix=" \033[2m↑ $(( gap_int / 3600 ))h${offline_label}\033[0m"
|
||||||
elif (( gap_int >= 60 )); then
|
elif (( gap_int >= 60 )); then
|
||||||
gap_suffix=" \033[2m↑ $(( gap_int / 60 ))m${offline_label}\033[0m"
|
gap_suffix=" \033[2m↑ $(( gap_int / 60 ))m${offline_label}\033[0m"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local client_pad endpoint_pad_n
|
# Build endpoint display: raw_ip [dim → resolved]
|
||||||
|
# Use ui::pad_mb so ANSI annotation doesn't affect column alignment
|
||||||
|
local endpoint_raw="${endpoint:--}"
|
||||||
|
local endpoint_colored
|
||||||
|
if [[ -n "$resolved" && -n "$endpoint" ]]; then
|
||||||
|
endpoint_colored="${endpoint} \033[2m→ ${resolved}\033[0m"
|
||||||
|
else
|
||||||
|
endpoint_colored="$endpoint_raw"
|
||||||
|
fi
|
||||||
|
local endpoint_padded
|
||||||
|
endpoint_padded=$(ui::pad_mb "$endpoint_colored" "$w_endpoint")
|
||||||
|
|
||||||
|
local ts_pad client_pad
|
||||||
|
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 -lt 0 ]] && endpoint_pad_n=0
|
printf " %s %s %b %b%s\033[0m%b%b\n" \
|
||||||
|
"$ts_pad" "$client_pad" \
|
||||||
printf " %s %s %s%*s %b%s\033[0m%b%b\n" \
|
"$endpoint_padded" \
|
||||||
"$ts" "$client_pad" "$endpoint" "$endpoint_pad_n" "" \
|
|
||||||
"$event_color" "$event" "$count_suffix" "$gap_suffix"
|
"$event_color" "$event" "$count_suffix" "$gap_suffix"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue