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() }