mirror of
https://github.com/anten-ka/gotelegram_pro.git
synced 2026-05-19 18:06:09 +00:00
fix: stats crash (set -u + CSV header), header box, QR spacing
This commit is contained in:
116
lib/stats.sh
116
lib/stats.sh
@@ -85,16 +85,19 @@ EOF
|
||||
fi
|
||||
|
||||
# Save snapshot for rate calculation (one per minute)
|
||||
local minute_key=$(date +%s -d "1 minute ago" +%Y%m%d%H%M 2>/dev/null || date +%Y%m%d%H%M)
|
||||
local minute_key
|
||||
minute_key=$(date +%Y%m%d%H%M 2>/dev/null)
|
||||
local snapshot_file="$SNAPSHOTS_DIR/snap_${minute_key}.json"
|
||||
cp "$CURRENT_SNAPSHOT" "$snapshot_file" 2>/dev/null
|
||||
|
||||
# Append to history CSV (once per minute, check if last entry is fresh)
|
||||
if [[ -f "$HISTORY_FILE" ]]; then
|
||||
local last_ts=$(tail -1 "$HISTORY_FILE" 2>/dev/null | cut -d, -f1)
|
||||
local last_ts
|
||||
last_ts=$(grep -E '^[0-9]' "$HISTORY_FILE" 2>/dev/null | tail -1 | cut -d, -f1)
|
||||
last_ts="${last_ts:-0}"
|
||||
local current_minute=$((ts - (ts % 60)))
|
||||
|
||||
if [[ -z "$last_ts" ]] || [[ $((current_minute - last_ts)) -ge 60 ]]; then
|
||||
if [[ "$last_ts" -eq 0 ]] || [[ $((current_minute - last_ts)) -ge 60 ]]; then
|
||||
echo "$current_minute,$proxy_bytes,$site_bytes" >> "$HISTORY_FILE" 2>/dev/null
|
||||
|
||||
# Cleanup old entries (keep only 365 days)
|
||||
@@ -158,82 +161,61 @@ format_rate() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Safely convert value to integer (returns 0 for empty/non-numeric)
|
||||
_to_int() {
|
||||
local val="${1:-0}"
|
||||
# Strip non-numeric chars, default to 0
|
||||
val="${val//[^0-9]/}"
|
||||
echo "${val:-0}"
|
||||
}
|
||||
|
||||
# Calculate diff safely (never negative, never crashes on empty)
|
||||
_safe_diff() {
|
||||
local a=$(_to_int "$1")
|
||||
local b=$(_to_int "$2")
|
||||
local d=$((a - b))
|
||||
(( d < 0 )) && d=0
|
||||
echo "$d"
|
||||
}
|
||||
|
||||
# Calculate traffic rates and totals from history
|
||||
stats_calculate_rates() {
|
||||
local traffic_type="$1" # "proxy" or "site"
|
||||
local col_idx=2 # proxy_bytes is column 2
|
||||
[[ "$traffic_type" == "site" ]] && col_idx=3
|
||||
|
||||
[[ "$traffic_type" == "site" ]] && col_idx=3 # site_bytes is column 3
|
||||
local now
|
||||
now=$(date +%s)
|
||||
|
||||
local now=$(date +%s)
|
||||
local result=""
|
||||
# Get latest data line (skip header with grep -E '^[0-9]')
|
||||
local bytes_now
|
||||
bytes_now=$(_to_int "$(grep -E '^[0-9]' "$HISTORY_FILE" 2>/dev/null | tail -1 | cut -d, -f"$col_idx")")
|
||||
|
||||
# 1 minute rate
|
||||
local ts_1m=$((now - 60))
|
||||
local bytes_now=$(tail -1 "$HISTORY_FILE" 2>/dev/null | cut -d, -f"$col_idx")
|
||||
local bytes_1m=$(awk -F, -v ts="$ts_1m" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_1m=$((bytes_now - (bytes_1m > 0 ? bytes_1m : bytes_now)))
|
||||
[[ $diff_1m -lt 0 ]] && diff_1m=0
|
||||
local rate_1m=$((diff_1m / 60))
|
||||
local bytes_1m_fmt=$(format_bytes "$diff_1m")
|
||||
local rate_1m_fmt=$(format_rate "$rate_1m")
|
||||
local periods="60 300 3600 86400 604800 2592000 31536000"
|
||||
local results=""
|
||||
|
||||
# 5 minute rate
|
||||
local ts_5m=$((now - 300))
|
||||
local bytes_5m=$(awk -F, -v ts="$ts_5m" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_5m=$((bytes_now - (bytes_5m > 0 ? bytes_5m : bytes_now)))
|
||||
[[ $diff_5m -lt 0 ]] && diff_5m=0
|
||||
local rate_5m=$((diff_5m / 300))
|
||||
local bytes_5m_fmt=$(format_bytes "$diff_5m")
|
||||
local rate_5m_fmt=$(format_rate "$rate_5m")
|
||||
for secs in $periods; do
|
||||
local target_ts=$((now - secs))
|
||||
# Find closest entry at or after target timestamp (skip header)
|
||||
local old_val
|
||||
old_val=$(_to_int "$(awk -F, -v ts="$target_ts" '$1 ~ /^[0-9]/ && $1 <= ts' "$HISTORY_FILE" 2>/dev/null | tail -1 | cut -d, -f"$col_idx")")
|
||||
|
||||
# 60 minute rate
|
||||
local ts_60m=$((now - 3600))
|
||||
local bytes_60m=$(awk -F, -v ts="$ts_60m" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_60m=$((bytes_now - (bytes_60m > 0 ? bytes_60m : bytes_now)))
|
||||
[[ $diff_60m -lt 0 ]] && diff_60m=0
|
||||
local rate_60m=$((diff_60m / 3600))
|
||||
local bytes_60m_fmt=$(format_bytes "$diff_60m")
|
||||
local rate_60m_fmt=$(format_rate "$rate_60m")
|
||||
local diff
|
||||
diff=$(_safe_diff "$bytes_now" "$old_val")
|
||||
local rate=$(( secs > 0 ? diff / secs : 0 ))
|
||||
|
||||
# 1 day total
|
||||
local ts_1d=$((now - 86400))
|
||||
local bytes_1d=$(awk -F, -v ts="$ts_1d" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_1d=$((bytes_now - (bytes_1d > 0 ? bytes_1d : bytes_now)))
|
||||
[[ $diff_1d -lt 0 ]] && diff_1d=0
|
||||
local rate_1d=$((diff_1d > 0 ? diff_1d / 86400 : 0))
|
||||
local bytes_1d_fmt=$(format_bytes "$diff_1d")
|
||||
local rate_1d_fmt=$(format_rate "$rate_1d")
|
||||
local bytes_fmt rate_fmt
|
||||
bytes_fmt=$(format_bytes "$diff")
|
||||
rate_fmt=$(format_rate "$rate")
|
||||
|
||||
# 7 days total
|
||||
local ts_7d=$((now - 604800))
|
||||
local bytes_7d=$(awk -F, -v ts="$ts_7d" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_7d=$((bytes_now - (bytes_7d > 0 ? bytes_7d : bytes_now)))
|
||||
[[ $diff_7d -lt 0 ]] && diff_7d=0
|
||||
local rate_7d=$((diff_7d > 0 ? diff_7d / 604800 : 0))
|
||||
local bytes_7d_fmt=$(format_bytes "$diff_7d")
|
||||
local rate_7d_fmt=$(format_rate "$rate_7d")
|
||||
if [ -z "$results" ]; then
|
||||
results="${bytes_fmt}|${rate_fmt}"
|
||||
else
|
||||
results="${results}|${bytes_fmt}|${rate_fmt}"
|
||||
fi
|
||||
done
|
||||
|
||||
# 30 days total
|
||||
local ts_30d=$((now - 2592000))
|
||||
local bytes_30d=$(awk -F, -v ts="$ts_30d" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_30d=$((bytes_now - (bytes_30d > 0 ? bytes_30d : bytes_now)))
|
||||
[[ $diff_30d -lt 0 ]] && diff_30d=0
|
||||
local rate_30d=$((diff_30d > 0 ? diff_30d / 2592000 : 0))
|
||||
local bytes_30d_fmt=$(format_bytes "$diff_30d")
|
||||
local rate_30d_fmt=$(format_rate "$rate_30d")
|
||||
|
||||
# 365 days total
|
||||
local ts_365d=$((now - 31536000))
|
||||
local bytes_365d=$(awk -F, -v ts="$ts_365d" '$1 >= ts' "$HISTORY_FILE" 2>/dev/null | head -1 | cut -d, -f"$col_idx")
|
||||
local diff_365d=$((bytes_now - (bytes_365d > 0 ? bytes_365d : bytes_now)))
|
||||
[[ $diff_365d -lt 0 ]] && diff_365d=0
|
||||
local rate_365d=$((diff_365d > 0 ? diff_365d / 31536000 : 0))
|
||||
local bytes_365d_fmt=$(format_bytes "$diff_365d")
|
||||
local rate_365d_fmt=$(format_rate "$rate_365d")
|
||||
|
||||
# Return as pipe-delimited format for table display
|
||||
echo "$bytes_1m_fmt|$rate_1m_fmt|$bytes_5m_fmt|$rate_5m_fmt|$bytes_60m_fmt|$rate_60m_fmt|$bytes_1d_fmt|$rate_1d_fmt|$bytes_7d_fmt|$rate_7d_fmt|$bytes_30d_fmt|$rate_30d_fmt|$bytes_365d_fmt|$rate_365d_fmt"
|
||||
echo "$results"
|
||||
}
|
||||
|
||||
# Main display function for traffic statistics
|
||||
|
||||
Reference in New Issue
Block a user