Add all 44 scripts, update CI: error severity baseline, PowerShell validation, multi-distro testing
Amp-Thread-ID: https://ampcode.com/threads/T-019cc404-c628-759e-a50b-f5eeea35b91f Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Executable
+637
@@ -0,0 +1,637 @@
|
||||
#!/bin/bash
|
||||
|
||||
#############################################################
|
||||
#### Speedtest Metrics Exporter ####
|
||||
#### Internet & LAN speed metrics for Prometheus ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version: 2.1 ####
|
||||
#### ####
|
||||
#### Usage: ./speedtest-metrics.sh [OPTIONS] ####
|
||||
#############################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
#########################
|
||||
### Output Mode ###
|
||||
#########################
|
||||
|
||||
LISTEN_PORT="${SPEEDTEST_EXPORTER_PORT:-9196}"
|
||||
TEXTFILE_DIR="/var/lib/node_exporter"
|
||||
OUTPUT_FILE=""
|
||||
HTTP_MODE=false
|
||||
|
||||
#########################
|
||||
### Parse Arguments ###
|
||||
#########################
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Speedtest Metrics Exporter for Prometheus
|
||||
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
MODES:
|
||||
--textfile Write to node_exporter textfile collector
|
||||
--http Run HTTP server on port $LISTEN_PORT
|
||||
(no flag) Output to stdout (default)
|
||||
|
||||
OPTIONS:
|
||||
-p, --port PORT HTTP port (default: 9196)
|
||||
-o, --output PATH Output file path
|
||||
--help Show this help
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
SPEEDTEST_SERVERS Comma-separated Ookla server IDs or "auto" (default: auto)
|
||||
IPERF_SERVER Local iperf3 server IP (default: 192.168.1.100)
|
||||
IPERF_PORT iperf3 port (default: 9182)
|
||||
SPEEDTEST_EXPORTER_PORT Same as --port
|
||||
|
||||
EXAMPLES:
|
||||
$0 # One-shot to stdout
|
||||
$0 --textfile # Write to textfile collector
|
||||
$0 --http --port 9196 # Run HTTP server
|
||||
$0 -o /tmp/speedtest.prom # Write to custom file
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
handle_request() {
|
||||
local request
|
||||
read -r request || true
|
||||
|
||||
local path
|
||||
path=$(echo "$request" | awk '{print $2}')
|
||||
|
||||
case "$path" in
|
||||
/metrics)
|
||||
local metrics
|
||||
metrics=$(collect_metrics)
|
||||
local content_length=${#metrics}
|
||||
printf "HTTP/1.1 200 OK\r\nContent-Type: text/plain; version=0.0.4; charset=utf-8\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s" "$content_length" "$metrics"
|
||||
;;
|
||||
/)
|
||||
local body="<html><body><h1>Speedtest Metrics Exporter</h1><p><a href='/metrics'>Metrics</a></p></body></html>"
|
||||
local content_length=${#body}
|
||||
printf "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\nConnection: close\r\n\r\n%s" "$content_length" "$body"
|
||||
;;
|
||||
*)
|
||||
printf "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: 9\r\nConnection: close\r\n\r\nNot Found"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--textfile)
|
||||
OUTPUT_FILE="$TEXTFILE_DIR/speedtest.prom"
|
||||
shift
|
||||
;;
|
||||
--http)
|
||||
HTTP_MODE=true
|
||||
shift
|
||||
;;
|
||||
--port|-p)
|
||||
LISTEN_PORT="$2"
|
||||
HTTP_MODE=true
|
||||
shift 2
|
||||
;;
|
||||
--output|-o)
|
||||
OUTPUT_FILE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--handle-request)
|
||||
handle_request
|
||||
exit 0
|
||||
;;
|
||||
--help|-h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
#########################
|
||||
### Metrics Collection ###
|
||||
#########################
|
||||
|
||||
collect_metrics() {
|
||||
|
||||
# Configuration
|
||||
TEMP_FILE="/tmp/speedtest_$$"
|
||||
IPERF_SERVER="${IPERF_SERVER:-192.168.1.100}" # Set to your local iperf3 server IP
|
||||
IPERF_PORT="${IPERF_PORT:-9182}" # iperf3 port
|
||||
# Multiple speedtest servers - add/remove server IDs as needed
|
||||
# Common server IDs for major cities:
|
||||
# Dallas/DFW: 5029 (AT&T), 12190 (Spectrum), 26847 (Verizon)
|
||||
# New York: 3737 (Verizon), 11570 (Optimum), 17395 (Spectrum)
|
||||
SPEEDTEST_SERVERS="${SPEEDTEST_SERVERS:-auto}" # Comma-separated server IDs or "auto"
|
||||
|
||||
cleanup() {
|
||||
rm -f "$TEMP_FILE"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Record script start time
|
||||
SCRIPT_START_TIME=$(date +%s.%N)
|
||||
|
||||
# Internet Speed Test - Multiple Servers
|
||||
echo "# Running internet speedtest on multiple servers..." >&2
|
||||
|
||||
# Initialize arrays to store results for all servers
|
||||
declare -a SERVER_IDS=()
|
||||
declare -a PING_LATENCIES=()
|
||||
declare -a PING_JITTERS=()
|
||||
declare -a PING_LOWS=()
|
||||
declare -a PING_HIGHS=()
|
||||
declare -a DOWNLOAD_MBPS=()
|
||||
declare -a UPLOAD_MBPS=()
|
||||
declare -a PACKET_LOSSES=()
|
||||
declare -a EXTERNAL_IPS=()
|
||||
declare -a TEST_TIMESTAMPS=()
|
||||
declare -a SERVER_NAMES=()
|
||||
declare -a SERVER_LOCATIONS=()
|
||||
declare -a SERVER_COUNTRIES=()
|
||||
declare -a ISPS=()
|
||||
declare -a RESULT_URLS=()
|
||||
declare -a DOWNLOAD_SIZES=()
|
||||
declare -a UPLOAD_SIZES=()
|
||||
declare -a SUCCESSES=()
|
||||
|
||||
# Convert comma-separated servers to array
|
||||
IFS=',' read -ra SERVERS <<< "$SPEEDTEST_SERVERS"
|
||||
|
||||
# Test each server
|
||||
for server_id in "${SERVERS[@]}"; do
|
||||
server_id=$(echo "$server_id" | xargs) # Trim whitespace
|
||||
echo "# Testing server $server_id..." >&2
|
||||
|
||||
TEMP_SERVER_FILE="/tmp/speedtest_${server_id}_$$"
|
||||
|
||||
# Handle auto server selection vs specific server ID
|
||||
if [[ "$server_id" == "auto" ]]; then
|
||||
speedtest_cmd="speedtest --format=json"
|
||||
else
|
||||
speedtest_cmd="speedtest -s $server_id --format=json"
|
||||
fi
|
||||
|
||||
if $speedtest_cmd --accept-license --accept-gdpr > "$TEMP_SERVER_FILE" 2>/dev/null; then
|
||||
echo "# Server $server_id: SUCCESS" >&2
|
||||
|
||||
# Parse results for this server
|
||||
ping_latency=$(jq -r '.ping.latency // "0"' "$TEMP_SERVER_FILE")
|
||||
ping_jitter=$(jq -r '.ping.jitter // "0"' "$TEMP_SERVER_FILE")
|
||||
ping_low=$(jq -r '.ping.low // "0"' "$TEMP_SERVER_FILE")
|
||||
ping_high=$(jq -r '.ping.high // "0"' "$TEMP_SERVER_FILE")
|
||||
download_bandwidth=$(jq -r '.download.bandwidth // "0"' "$TEMP_SERVER_FILE")
|
||||
upload_bandwidth=$(jq -r '.upload.bandwidth // "0"' "$TEMP_SERVER_FILE")
|
||||
packet_loss=$(jq -r '.packetLoss // "0"' "$TEMP_SERVER_FILE")
|
||||
external_ip=$(jq -r '.interface.externalIp // "unknown"' "$TEMP_SERVER_FILE")
|
||||
|
||||
# Handle timestamp conversion
|
||||
test_timestamp_raw=$(jq -r '.timestamp // "0"' "$TEMP_SERVER_FILE")
|
||||
if [[ "$test_timestamp_raw" != "0" ]] && [[ "$test_timestamp_raw" != "unknown" ]]; then
|
||||
test_timestamp=$(date -d "$test_timestamp_raw" +%s 2>/dev/null || echo "0")
|
||||
else
|
||||
test_timestamp=0
|
||||
fi
|
||||
|
||||
server_name=$(jq -r '.server.name // "unknown"' "$TEMP_SERVER_FILE")
|
||||
server_location=$(jq -r '.server.location // "unknown"' "$TEMP_SERVER_FILE")
|
||||
server_country=$(jq -r '.server.country // "unknown"' "$TEMP_SERVER_FILE")
|
||||
isp=$(jq -r '.isp // "unknown"' "$TEMP_SERVER_FILE")
|
||||
result_url=$(jq -r '.result.url // "unknown"' "$TEMP_SERVER_FILE")
|
||||
download_size=$(jq -r '.download.bytes // "0"' "$TEMP_SERVER_FILE")
|
||||
upload_size=$(jq -r '.upload.bytes // "0"' "$TEMP_SERVER_FILE")
|
||||
|
||||
# Convert from bits to Mbps (fallback to awk if bc unavailable)
|
||||
download_mbps=$(echo "scale=2; $download_bandwidth / 125000" | bc -l 2>/dev/null || echo "$download_bandwidth" | awk '{printf "%.2f", $1/125000}')
|
||||
upload_mbps=$(echo "scale=2; $upload_bandwidth / 125000" | bc -l 2>/dev/null || echo "$upload_bandwidth" | awk '{printf "%.2f", $1/125000}')
|
||||
|
||||
success=1
|
||||
else
|
||||
echo "# Server $server_id: FAILED" >&2
|
||||
|
||||
# Set default values for failed test
|
||||
ping_latency=0; ping_jitter=0; ping_low=0; ping_high=0
|
||||
download_mbps=0; upload_mbps=0; packet_loss=0
|
||||
external_ip="unknown"; test_timestamp=0; server_name="unknown"
|
||||
server_location="unknown"; server_country="unknown"; isp="unknown"
|
||||
result_url="unknown"; download_size=0; upload_size=0
|
||||
success=0
|
||||
fi
|
||||
|
||||
# Store results in arrays
|
||||
SERVER_IDS+=("$server_id")
|
||||
PING_LATENCIES+=("$ping_latency")
|
||||
PING_JITTERS+=("$ping_jitter")
|
||||
PING_LOWS+=("$ping_low")
|
||||
PING_HIGHS+=("$ping_high")
|
||||
DOWNLOAD_MBPS+=("$download_mbps")
|
||||
UPLOAD_MBPS+=("$upload_mbps")
|
||||
PACKET_LOSSES+=("$packet_loss")
|
||||
EXTERNAL_IPS+=("$external_ip")
|
||||
TEST_TIMESTAMPS+=("$test_timestamp")
|
||||
SERVER_NAMES+=("$server_name")
|
||||
SERVER_LOCATIONS+=("$server_location")
|
||||
SERVER_COUNTRIES+=("$server_country")
|
||||
ISPS+=("$isp")
|
||||
RESULT_URLS+=("$result_url")
|
||||
DOWNLOAD_SIZES+=("$download_size")
|
||||
UPLOAD_SIZES+=("$upload_size")
|
||||
SUCCESSES+=("$success")
|
||||
|
||||
# Cleanup temp file
|
||||
rm -f "$TEMP_SERVER_FILE"
|
||||
done
|
||||
|
||||
# Local Network Speed Test (iperf3) - Enhanced with additional metrics
|
||||
echo "# Testing local network speed..." >&2
|
||||
if command -v iperf3 >/dev/null 2>&1; then
|
||||
# Test download from local server (we are client)
|
||||
if local_down=$(timeout 10 iperf3 -c "$IPERF_SERVER" -p "$IPERF_PORT" -t 5 -J 2>/dev/null); then
|
||||
local_download_mbps=$(echo "$local_down" | jq -r '.end.sum_received.bits_per_second // "0"' | awk '{printf "%.2f", $1/1000000}')
|
||||
local_download_bytes=$(echo "$local_down" | jq -r '.end.sum_received.bytes // "0"')
|
||||
local_download_retransmits=$(echo "$local_down" | jq -r '.end.sum_sent.retransmits // "0"')
|
||||
local_download_rtt=$(echo "$local_down" | jq -r '.end.streams[0].sender.mean_rtt // "0"' | awk '{printf "%.3f", $1/1000}') # Convert to ms
|
||||
local_download_rtt_var=$(echo "$local_down" | jq -r '.end.streams[0].sender.rtt_variance // "0"' | awk '{printf "%.3f", $1/1000}')
|
||||
local_download_cpu_local=$(echo "$local_down" | jq -r '.end.cpu_utilization_percent.host_total // "0"')
|
||||
local_download_cpu_remote=$(echo "$local_down" | jq -r '.end.cpu_utilization_percent.remote_total // "0"')
|
||||
local_download_congestion_window=$(echo "$local_down" | jq -r '.end.streams[0].sender.max_snd_cwnd // "0"')
|
||||
local_download_success=1
|
||||
else
|
||||
local_download_mbps=0; local_download_bytes=0; local_download_retransmits=0
|
||||
local_download_rtt=0; local_download_rtt_var=0; local_download_cpu_local=0
|
||||
local_download_cpu_remote=0; local_download_congestion_window=0; local_download_success=0
|
||||
fi
|
||||
|
||||
# Test upload to local server (we are client, reverse mode)
|
||||
if local_up=$(timeout 10 iperf3 -c "$IPERF_SERVER" -p "$IPERF_PORT" -t 5 -R -J 2>/dev/null); then
|
||||
local_upload_mbps=$(echo "$local_up" | jq -r '.end.sum_sent.bits_per_second // "0"' | awk '{printf "%.2f", $1/1000000}')
|
||||
local_upload_bytes=$(echo "$local_up" | jq -r '.end.sum_sent.bytes // "0"')
|
||||
local_upload_retransmits=$(echo "$local_up" | jq -r '.end.sum_received.retransmits // "0"')
|
||||
local_upload_rtt=$(echo "$local_up" | jq -r '.end.streams[0].receiver.mean_rtt // "0"' | awk '{printf "%.3f", $1/1000}')
|
||||
local_upload_rtt_var=$(echo "$local_up" | jq -r '.end.streams[0].receiver.rtt_variance // "0"' | awk '{printf "%.3f", $1/1000}')
|
||||
local_upload_cpu_local=$(echo "$local_up" | jq -r '.end.cpu_utilization_percent.host_total // "0"')
|
||||
local_upload_cpu_remote=$(echo "$local_up" | jq -r '.end.cpu_utilization_percent.remote_total // "0"')
|
||||
local_upload_congestion_window=$(echo "$local_up" | jq -r '.end.streams[0].receiver.max_snd_cwnd // "0"')
|
||||
local_upload_success=1
|
||||
else
|
||||
local_upload_mbps=0; local_upload_bytes=0; local_upload_retransmits=0
|
||||
local_upload_rtt=0; local_upload_rtt_var=0; local_upload_cpu_local=0
|
||||
local_upload_cpu_remote=0; local_upload_congestion_window=0; local_upload_success=0
|
||||
fi
|
||||
else
|
||||
echo "# iperf3 not installed, skipping local network test" >&2
|
||||
local_download_mbps=0; local_upload_mbps=0; local_download_bytes=0; local_upload_bytes=0
|
||||
local_download_retransmits=0; local_upload_retransmits=0; local_download_rtt=0; local_upload_rtt=0
|
||||
local_download_rtt_var=0; local_upload_rtt_var=0; local_download_cpu_local=0; local_upload_cpu_local=0
|
||||
local_download_cpu_remote=0; local_upload_cpu_remote=0; local_download_congestion_window=0; local_upload_congestion_window=0
|
||||
local_download_success=0; local_upload_success=0
|
||||
fi
|
||||
|
||||
# Calculate script runtime
|
||||
SCRIPT_END_TIME=$(date +%s.%N)
|
||||
SCRIPT_RUNTIME=$(echo "$SCRIPT_END_TIME - $SCRIPT_START_TIME" | bc -l 2>/dev/null || echo "$SCRIPT_END_TIME $SCRIPT_START_TIME" | awk '{printf "%.3f", $1-$2}')
|
||||
|
||||
# Output Prometheus metrics
|
||||
cat <<EOF
|
||||
# HELP internet_speedtest_latency Internet connection latency in milliseconds
|
||||
# TYPE internet_speedtest_latency gauge
|
||||
EOF
|
||||
|
||||
# Generate metrics for each server
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
isp="${ISPS[$i]}"
|
||||
external_ip="${EXTERNAL_IPS[$i]}"
|
||||
result_url="${RESULT_URLS[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_latency{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${PING_LATENCIES[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_latency_low Internet connection minimum latency in milliseconds
|
||||
# TYPE internet_speedtest_latency_low gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_latency_low{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${PING_LOWS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_latency_high Internet connection maximum latency in milliseconds
|
||||
# TYPE internet_speedtest_latency_high gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_latency_high{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${PING_HIGHS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_jitter Internet connection jitter in milliseconds
|
||||
# TYPE internet_speedtest_jitter gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_jitter{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${PING_JITTERS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_download Internet download speed in Mbps
|
||||
# TYPE internet_speedtest_download gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_download{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${DOWNLOAD_MBPS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_download_size Internet download test data size in bytes
|
||||
# TYPE internet_speedtest_download_size gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_download_size{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${DOWNLOAD_SIZES[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_upload Internet upload speed in Mbps
|
||||
# TYPE internet_speedtest_upload gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_upload{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${UPLOAD_MBPS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_upload_size Internet upload test data size in bytes
|
||||
# TYPE internet_speedtest_upload_size gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_upload_size{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${UPLOAD_SIZES[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_packet_loss Internet connection packet loss percentage
|
||||
# TYPE internet_speedtest_packet_loss gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_packet_loss{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${PACKET_LOSSES[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_timestamp Unix timestamp when test was performed
|
||||
# TYPE internet_speedtest_timestamp gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_timestamp{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${TEST_TIMESTAMPS[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_info Internet speedtest metadata
|
||||
# TYPE internet_speedtest_info gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
external_ip="${EXTERNAL_IPS[$i]}"
|
||||
isp="${ISPS[$i]}"
|
||||
result_url="${RESULT_URLS[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_info{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country",external_ip="$external_ip",isp="$isp",result_url="$result_url"} 1
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP internet_speedtest_success Whether internet speedtest succeeded (1=success, 0=failed)
|
||||
# TYPE internet_speedtest_success gauge
|
||||
EOF
|
||||
|
||||
for i in "${!SERVER_IDS[@]}"; do
|
||||
server_id="${SERVER_IDS[$i]}"
|
||||
server_name="${SERVER_NAMES[$i]}"
|
||||
server_location="${SERVER_LOCATIONS[$i]}"
|
||||
server_country="${SERVER_COUNTRIES[$i]}"
|
||||
|
||||
cat <<EOF
|
||||
internet_speedtest_success{server_id="$server_id",server_name="$server_name",server_location="$server_location",server_country="$server_country"} ${SUCCESSES[$i]}
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
# HELP local_network_download Local network download speed in Mbps
|
||||
# TYPE local_network_download gauge
|
||||
local_network_download $local_download_mbps
|
||||
|
||||
# HELP local_network_upload Local network upload speed in Mbps
|
||||
# TYPE local_network_upload gauge
|
||||
local_network_upload $local_upload_mbps
|
||||
|
||||
# HELP local_network_download_bytes Total bytes downloaded in local network test
|
||||
# TYPE local_network_download_bytes gauge
|
||||
local_network_download_bytes $local_download_bytes
|
||||
|
||||
# HELP local_network_upload_bytes Total bytes uploaded in local network test
|
||||
# TYPE local_network_upload_bytes gauge
|
||||
local_network_upload_bytes $local_upload_bytes
|
||||
|
||||
# HELP local_network_download_retransmits TCP retransmissions during download test
|
||||
# TYPE local_network_download_retransmits gauge
|
||||
local_network_download_retransmits $local_download_retransmits
|
||||
|
||||
# HELP local_network_upload_retransmits TCP retransmissions during upload test
|
||||
# TYPE local_network_upload_retransmits gauge
|
||||
local_network_upload_retransmits $local_upload_retransmits
|
||||
|
||||
# HELP local_network_download_rtt Mean round-trip time during download test in milliseconds
|
||||
# TYPE local_network_download_rtt gauge
|
||||
local_network_download_rtt $local_download_rtt
|
||||
|
||||
# HELP local_network_upload_rtt Mean round-trip time during upload test in milliseconds
|
||||
# TYPE local_network_upload_rtt gauge
|
||||
local_network_upload_rtt $local_upload_rtt
|
||||
|
||||
# HELP local_network_download_rtt_variance RTT variance during download test in milliseconds
|
||||
# TYPE local_network_download_rtt_variance gauge
|
||||
local_network_download_rtt_variance $local_download_rtt_var
|
||||
|
||||
# HELP local_network_upload_rtt_variance RTT variance during upload test in milliseconds
|
||||
# TYPE local_network_upload_rtt_variance gauge
|
||||
local_network_upload_rtt_variance $local_upload_rtt_var
|
||||
|
||||
# HELP local_network_download_cpu_local Local CPU utilization during download test (percentage)
|
||||
# TYPE local_network_download_cpu_local gauge
|
||||
local_network_download_cpu_local $local_download_cpu_local
|
||||
|
||||
# HELP local_network_upload_cpu_local Local CPU utilization during upload test (percentage)
|
||||
# TYPE local_network_upload_cpu_local gauge
|
||||
local_network_upload_cpu_local $local_upload_cpu_local
|
||||
|
||||
# HELP local_network_download_cpu_remote Remote CPU utilization during download test (percentage)
|
||||
# TYPE local_network_download_cpu_remote gauge
|
||||
local_network_download_cpu_remote $local_download_cpu_remote
|
||||
|
||||
# HELP local_network_upload_cpu_remote Remote CPU utilization during upload test (percentage)
|
||||
# TYPE local_network_upload_cpu_remote gauge
|
||||
local_network_upload_cpu_remote $local_upload_cpu_remote
|
||||
|
||||
# HELP local_network_download_congestion_window Maximum TCP congestion window size during download test in bytes
|
||||
# TYPE local_network_download_congestion_window gauge
|
||||
local_network_download_congestion_window $local_download_congestion_window
|
||||
|
||||
# HELP local_network_upload_congestion_window Maximum TCP congestion window size during upload test in bytes
|
||||
# TYPE local_network_upload_congestion_window gauge
|
||||
local_network_upload_congestion_window $local_upload_congestion_window
|
||||
|
||||
# HELP local_network_test_success Whether local network test succeeded (1=success, 0=failed)
|
||||
# TYPE local_network_test_success gauge
|
||||
local_network_test_success $((local_download_success && local_upload_success))
|
||||
|
||||
# HELP speedtest_script_runtime_seconds Total script execution time in seconds
|
||||
# TYPE speedtest_script_runtime_seconds gauge
|
||||
speedtest_script_runtime_seconds $SCRIPT_RUNTIME
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
#########################
|
||||
### Output Handling ###
|
||||
#########################
|
||||
|
||||
write_output() {
|
||||
local metrics
|
||||
metrics=$(collect_metrics)
|
||||
|
||||
if [[ -n "$OUTPUT_FILE" ]]; then
|
||||
mkdir -p "$(dirname "$OUTPUT_FILE")"
|
||||
local tmp_file="${OUTPUT_FILE}.$$"
|
||||
echo "$metrics" > "$tmp_file"
|
||||
mv "$tmp_file" "$OUTPUT_FILE"
|
||||
echo "Metrics written to $OUTPUT_FILE" >&2
|
||||
else
|
||||
echo "$metrics"
|
||||
fi
|
||||
}
|
||||
|
||||
start_server() {
|
||||
if ! command -v socat >/dev/null 2>&1; then
|
||||
echo "socat is required for HTTP mode. Install it first." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Starting Speedtest Metrics Exporter on port $LISTEN_PORT" >&2
|
||||
echo "Metrics available at http://localhost:$LISTEN_PORT/metrics" >&2
|
||||
while true; do
|
||||
socat TCP-LISTEN:"$LISTEN_PORT",reuseaddr,fork EXEC:"$0 --handle-request" 2>/dev/null || {
|
||||
echo "Server error, restarting in 5 seconds..." >&2
|
||||
sleep 5
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
# Main execution
|
||||
if [[ "$HTTP_MODE" == true ]]; then
|
||||
start_server
|
||||
elif [[ -n "$OUTPUT_FILE" ]]; then
|
||||
write_output
|
||||
else
|
||||
collect_metrics
|
||||
fi
|
||||
Reference in New Issue
Block a user