Files
ProxmoxDash/network.go

91 lines
2.3 KiB
Go

package main
import (
"bufio"
"os"
"strconv"
"strings"
"sync"
"time"
)
type NetworkMetrics struct {
Interface string `json:"interface"`
ReceiveBytes uint64 `json:"receiveBytes"`
TransmitBytes uint64 `json:"transmitBytes"`
ReceivePerSec float64 `json:"receivePerSec"`
TransmitPerSec float64 `json:"transmitPerSec"`
}
type networkSnapshot struct {
at time.Time
received uint64
sent uint64
}
type networkCollector struct {
mu sync.Mutex
path string
previous networkSnapshot
}
func newNetworkCollector(path string) (*networkCollector, error) {
snapshot, _, err := readNetworkSnapshot(path)
if err != nil {
return nil, err
}
return &networkCollector{path: path, previous: snapshot}, nil
}
func (c *networkCollector) collect() (NetworkMetrics, error) {
c.mu.Lock()
defer c.mu.Unlock()
current, interfaces, err := readNetworkSnapshot(c.path)
if err != nil {
return NetworkMetrics{}, err
}
elapsed := current.at.Sub(c.previous.at).Seconds()
var receivedRate, sentRate float64
if elapsed > 0 && current.received >= c.previous.received && current.sent >= c.previous.sent {
receivedRate = float64(current.received-c.previous.received) / elapsed
sentRate = float64(current.sent-c.previous.sent) / elapsed
}
c.previous = current
return NetworkMetrics{
Interface: strings.Join(interfaces, ", "), ReceiveBytes: current.received,
TransmitBytes: current.sent, ReceivePerSec: receivedRate, TransmitPerSec: sentRate,
}, nil
}
func readNetworkSnapshot(path string) (networkSnapshot, []string, error) {
file, err := os.Open(path)
if err != nil {
return networkSnapshot{}, nil, err
}
defer file.Close()
var received, sent uint64
var interfaces []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
name, values, found := strings.Cut(line, ":")
if !found || strings.TrimSpace(name) == "lo" {
continue
}
fields := strings.Fields(values)
if len(fields) < 9 {
continue
}
rx, errRX := strconv.ParseUint(fields[0], 10, 64)
tx, errTX := strconv.ParseUint(fields[8], 10, 64)
if errRX == nil && errTX == nil {
received += rx
sent += tx
interfaces = append(interfaces, strings.TrimSpace(name))
}
}
return networkSnapshot{at: time.Now(), received: received, sent: sent}, interfaces, scanner.Err()
}