tgbot_misaka_5882f7/stats/vnstat.go

87 lines
1.8 KiB
Go
Raw Normal View History

2022-11-21 04:39:21 +09:00
package stats
import (
"fmt"
"os/exec"
"github.com/go-errors/errors"
"github.com/goccy/go-json"
)
const (
vnstatBin = "/usr/bin/vnstat"
)
type VnstatTrafficRecord struct {
Date struct {
Year uint `json:"year"`
Month uint `json:"month"`
Day uint `json:"day"`
} `json:"date"`
Time struct {
Hour uint `json:"hour"`
Minute uint `json:"minute"`
} `json:"time"`
Rx uint64 `json:"rx"`
Tx uint64 `json:"tx"`
}
type vnstatResponse struct {
Interfaces []struct {
Name string `json:"name"`
Traffic struct {
FiveMinute []VnstatTrafficRecord `json:"fiveminute"`
Hour []VnstatTrafficRecord `json:"hour"`
Day []VnstatTrafficRecord `json:"day"`
Month []VnstatTrafficRecord `json:"month"`
} `json:"traffic"`
} `json:"interfaces"`
}
func VnstatMonthlyTraffic(ifname string) ([]VnstatTrafficRecord, error) {
resp, err := callVnstat("--json", "m")
if err != nil {
return nil, errors.WrapPrefix(err, "failed to run vnstat", 0)
}
for _, iface := range resp.Interfaces {
if iface.Name == ifname {
return iface.Traffic.Month, nil
}
}
return nil, errors.New(fmt.Sprintf("interface %s not found", ifname))
}
func VnstatDailyTraffic(ifname string) ([]VnstatTrafficRecord, error) {
resp, err := callVnstat("--json", "d")
if err != nil {
return nil, errors.WrapPrefix(err, "failed to run vnstat", 0)
}
for _, iface := range resp.Interfaces {
if iface.Name == ifname {
return iface.Traffic.Day, nil
}
}
return nil, errors.New(fmt.Sprintf("interface %s not found", ifname))
}
func callVnstat(args ...string) (*vnstatResponse, error) {
cmd := exec.Command(vnstatBin, args...)
cmd.Stdin = nil
output, err := cmd.Output()
if err != nil {
return nil, err
}
var resp vnstatResponse
err = json.Unmarshal(output, &resp)
if err != nil {
return nil, errors.Wrap(err, 0)
}
return &resp, nil
}