Files
nodeprobe/cmd/nodeprobe/main.go

173 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
"github.com/meowrain/nodeprobe/internal/netstat"
)
func main() {
// 1. 获取初始数据
prevStats, err := netstat.GetInterfaceStats()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if len(prevStats) == 0 {
fmt.Println("No network interfaces found")
os.Exit(1)
}
// 2. 设置刷新间隔(默认 1 秒)
interval := 1 * time.Second
// 3. 隐藏光标
fmt.Print("\033[?25l")
defer fmt.Print("\033[?25h") // 退出时恢复光标
// 4. 创建 ticker 定时器
ticker := time.NewTicker(interval)
defer ticker.Stop()
// 5. 监听 Ctrl+C 退出
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// 6. 首次显示
clearScreen()
currStats, _ := netstat.GetInterfaceStats()
rates := netstat.CalculateRate(prevStats, currStats, interval)
printHeader()
printStats(rates, currStats)
prevStats = currStats
// 7. 主循环
for {
select {
case <-ticker.C:
// 获取当前统计数据
currStats, err := netstat.GetInterfaceStats()
if err != nil {
continue
}
// 计算速率
rates := netstat.CalculateRate(prevStats, currStats, interval)
// 移动光标到开头并打印统计
moveCursorToTop()
printHeader()
printStats(rates, currStats)
// 更新上一次的数据
prevStats = currStats
case <-sigChan:
fmt.Print("\033[?25h") // 恢复光标
fmt.Println("\nExiting...")
return
}
}
}
// 清屏
func clearScreen() {
fmt.Print("\033[2J")
fmt.Print("\033[H")
}
// 移动光标到顶部
func moveCursorToTop() {
fmt.Print("\033[H")
}
func printHeader() {
fmt.Println("Network Interface Traffic Monitor")
fmt.Println("----------------------------------")
fmt.Printf("%-20s %30s %30s %15s %15s\n",
"Interface", "Download", "Upload", "RX Total", "TX Total")
fmt.Println("----------------------------------")
}
func printStats(rates []netstat.TrafficRate, stats []netstat.InterfaceStats) {
// 创建统计 map
statsMap := make(map[string]netstat.InterfaceStats)
for _, s := range stats {
statsMap[s.Name] = s
}
// 找出最大速率用于归一化
maxRate := 0.0
for _, r := range rates {
if r.RxKbps*1000 > maxRate {
maxRate = r.RxKbps * 1000
}
if r.TxKbps*1000 > maxRate {
maxRate = r.TxKbps * 1000
}
}
if maxRate == 0 {
maxRate = 1
}
for _, r := range rates {
s := statsMap[r.Name]
// 生成下载和上传的可视化条形图
rxBar := makeTrafficBar(r.RxKbps*1000, maxRate, true)
txBar := makeTrafficBar(r.TxKbps*1000, maxRate, false)
fmt.Printf("%-20s %30s %30s %15s %15s\n",
r.Name,
rxBar,
txBar,
netstat.FormatBytes(float64(s.RxBytes)),
netstat.FormatBytes(float64(s.TxBytes)),
)
}
// 清除剩余行(如果接口数量减少)
fmt.Print("\033[J")
}
// 生成流量条形图
func makeTrafficBar(bps, maxBps float64, isDownload bool) string {
// ANSI 颜色代码
green := "\033[32m" // 下载用绿色
blue := "\033[36m" // 上传用青色
reset := "\033[0m"
color := blue
if isDownload {
color = green
}
// 计算条形图长度最多10个字符
barLength := 10
filledLength := int((bps / maxBps) * float64(barLength))
if filledLength > barLength {
filledLength = barLength
}
// 使用不同的字符显示强度
blocks := []rune{'▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'}
bar := ""
for i := 0; i < barLength; i++ {
if i < filledLength {
bar += string(blocks[7]) // 满格
} else {
bar += string(blocks[0]) // 空格
}
}
// 格式化速率信息
speedStr := netstat.FormatBps(bps)
return fmt.Sprintf("%s%s%s %9s", color, bar, reset, speedStr)
}