2018-02-19 15:25:02 +08:00
|
|
|
package widgets
|
|
|
|
|
|
|
|
import (
|
2018-02-20 07:02:01 +08:00
|
|
|
"fmt"
|
2018-12-05 13:44:25 +08:00
|
|
|
"log"
|
2019-06-13 05:28:52 +08:00
|
|
|
"strings"
|
2018-02-19 15:25:02 +08:00
|
|
|
"time"
|
|
|
|
|
2020-05-13 07:42:45 +08:00
|
|
|
"github.com/VictoriaMetrics/metrics"
|
2019-01-31 07:20:09 +08:00
|
|
|
psNet "github.com/shirou/gopsutil/net"
|
|
|
|
|
2020-04-24 03:07:08 +08:00
|
|
|
ui "github.com/xxxserxxx/gotop/v4/termui"
|
|
|
|
"github.com/xxxserxxx/gotop/v4/utils"
|
2018-02-19 15:25:02 +08:00
|
|
|
)
|
|
|
|
|
2019-06-08 06:03:00 +08:00
|
|
|
const (
|
2020-04-28 09:33:41 +08:00
|
|
|
// NetInterfaceAll enables all network interfaces
|
|
|
|
NetInterfaceAll = "all"
|
|
|
|
// NetInterfaceVpn is the VPN interface
|
|
|
|
NetInterfaceVpn = "tun0"
|
2019-06-08 06:03:00 +08:00
|
|
|
)
|
|
|
|
|
2019-03-01 08:29:52 +08:00
|
|
|
type NetWidget struct {
|
|
|
|
*ui.SparklineGroup
|
|
|
|
updateInterval time.Duration
|
2019-01-31 07:20:09 +08:00
|
|
|
|
2018-02-23 16:42:39 +08:00
|
|
|
// used to calculate recent network activity
|
2019-03-01 08:29:52 +08:00
|
|
|
totalBytesRecv uint64
|
|
|
|
totalBytesSent uint64
|
2019-06-13 05:28:52 +08:00
|
|
|
NetInterface []string
|
2020-05-13 07:42:45 +08:00
|
|
|
sentMetric *metrics.Counter
|
|
|
|
recvMetric *metrics.Counter
|
2020-04-17 02:28:18 +08:00
|
|
|
Mbps bool
|
2018-02-19 15:25:02 +08:00
|
|
|
}
|
|
|
|
|
2020-02-21 08:56:52 +08:00
|
|
|
// TODO: state:merge #169 % option for network use (jrswab/networkPercentage)
|
2019-05-15 00:09:17 +08:00
|
|
|
func NewNetWidget(netInterface string) *NetWidget {
|
2019-03-01 08:29:52 +08:00
|
|
|
recvSparkline := ui.NewSparkline()
|
|
|
|
recvSparkline.Data = []int{}
|
2018-02-19 15:25:02 +08:00
|
|
|
|
2019-03-01 08:29:52 +08:00
|
|
|
sentSparkline := ui.NewSparkline()
|
|
|
|
sentSparkline.Data = []int{}
|
2018-02-19 15:25:02 +08:00
|
|
|
|
2019-03-01 08:29:52 +08:00
|
|
|
spark := ui.NewSparklineGroup(recvSparkline, sentSparkline)
|
|
|
|
self := &NetWidget{
|
|
|
|
SparklineGroup: spark,
|
|
|
|
updateInterval: time.Second,
|
2019-06-13 05:28:52 +08:00
|
|
|
NetInterface: strings.Split(netInterface, ","),
|
2018-03-04 09:05:52 +08:00
|
|
|
}
|
2019-01-01 08:55:50 +08:00
|
|
|
self.Title = " Network Usage "
|
2019-05-15 00:09:17 +08:00
|
|
|
if netInterface != "all" {
|
2019-05-16 08:13:36 +08:00
|
|
|
self.Title = fmt.Sprintf(" Network Usage: %s ", netInterface)
|
2019-05-15 00:09:17 +08:00
|
|
|
}
|
2018-02-19 15:25:02 +08:00
|
|
|
|
2018-04-13 11:00:34 +08:00
|
|
|
self.update()
|
|
|
|
|
2018-02-19 15:25:02 +08:00
|
|
|
go func() {
|
2019-03-01 08:29:52 +08:00
|
|
|
for range time.NewTicker(self.updateInterval).C {
|
2019-03-08 15:43:10 +08:00
|
|
|
self.Lock()
|
2018-03-28 05:27:23 +08:00
|
|
|
self.update()
|
2019-03-08 15:43:10 +08:00
|
|
|
self.Unlock()
|
2018-02-19 15:25:02 +08:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-03-28 05:27:23 +08:00
|
|
|
return self
|
2018-02-19 15:25:02 +08:00
|
|
|
}
|
|
|
|
|
2020-04-28 09:33:41 +08:00
|
|
|
func (net *NetWidget) EnableMetric() {
|
2020-05-13 07:42:45 +08:00
|
|
|
net.recvMetric = metrics.NewCounter(makeName("net", "recv"))
|
|
|
|
net.sentMetric = metrics.NewCounter(makeName("net", "sent"))
|
2020-02-18 23:44:29 +08:00
|
|
|
}
|
|
|
|
|
2020-04-28 09:33:41 +08:00
|
|
|
func (net *NetWidget) update() {
|
2018-12-11 06:41:35 +08:00
|
|
|
interfaces, err := psNet.IOCounters(true)
|
2018-12-05 13:44:25 +08:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("failed to get network activity from gopsutil: %v", err)
|
2018-12-14 13:59:45 +08:00
|
|
|
return
|
2018-12-05 13:44:25 +08:00
|
|
|
}
|
2019-03-01 08:29:52 +08:00
|
|
|
|
|
|
|
var totalBytesRecv uint64
|
|
|
|
var totalBytesSent uint64
|
2019-06-13 05:28:52 +08:00
|
|
|
interfaceMap := make(map[string]bool)
|
|
|
|
// Default behaviour
|
2020-04-28 09:33:41 +08:00
|
|
|
interfaceMap[NetInterfaceAll] = true
|
|
|
|
interfaceMap[NetInterfaceVpn] = false
|
2019-06-13 05:28:52 +08:00
|
|
|
// Build a map with wanted status for each interfaces.
|
2020-04-28 09:33:41 +08:00
|
|
|
for _, iface := range net.NetInterface {
|
2019-06-13 05:28:52 +08:00
|
|
|
if strings.HasPrefix(iface, "!") {
|
|
|
|
interfaceMap[strings.TrimPrefix(iface, "!")] = false
|
|
|
|
} else {
|
|
|
|
// if we specify a wanted interface, remove capture on all.
|
2020-04-28 09:33:41 +08:00
|
|
|
delete(interfaceMap, NetInterfaceAll)
|
2019-06-13 05:28:52 +08:00
|
|
|
interfaceMap[iface] = true
|
|
|
|
}
|
|
|
|
}
|
2018-12-11 06:41:35 +08:00
|
|
|
for _, _interface := range interfaces {
|
2019-06-13 05:28:52 +08:00
|
|
|
wanted, ok := interfaceMap[_interface.Name]
|
|
|
|
if wanted && ok { // Simple case
|
|
|
|
totalBytesRecv += _interface.BytesRecv
|
|
|
|
totalBytesSent += _interface.BytesSent
|
|
|
|
} else if ok { // Present but unwanted
|
|
|
|
continue
|
2020-04-28 09:33:41 +08:00
|
|
|
} else if interfaceMap[NetInterfaceAll] { // Capture other
|
2019-03-01 08:29:52 +08:00
|
|
|
totalBytesRecv += _interface.BytesRecv
|
|
|
|
totalBytesSent += _interface.BytesSent
|
2018-12-11 06:41:35 +08:00
|
|
|
}
|
|
|
|
}
|
2018-02-19 15:25:02 +08:00
|
|
|
|
2019-03-01 08:29:52 +08:00
|
|
|
var recentBytesRecv uint64
|
|
|
|
var recentBytesSent uint64
|
|
|
|
|
2020-04-28 09:33:41 +08:00
|
|
|
if net.totalBytesRecv != 0 { // if this isn't the first update
|
|
|
|
recentBytesRecv = totalBytesRecv - net.totalBytesRecv
|
|
|
|
recentBytesSent = totalBytesSent - net.totalBytesSent
|
2018-02-19 15:25:02 +08:00
|
|
|
|
2019-03-01 08:29:52 +08:00
|
|
|
if int(recentBytesRecv) < 0 {
|
|
|
|
log.Printf("error: negative value for recently received network data from gopsutil. recentBytesRecv: %v", recentBytesRecv)
|
2018-12-05 13:44:25 +08:00
|
|
|
// recover from error
|
2019-03-01 08:29:52 +08:00
|
|
|
recentBytesRecv = 0
|
2018-12-05 13:44:25 +08:00
|
|
|
}
|
2019-03-01 08:29:52 +08:00
|
|
|
if int(recentBytesSent) < 0 {
|
|
|
|
log.Printf("error: negative value for recently sent network data from gopsutil. recentBytesSent: %v", recentBytesSent)
|
2018-12-05 13:44:25 +08:00
|
|
|
// recover from error
|
2019-03-01 08:29:52 +08:00
|
|
|
recentBytesSent = 0
|
2018-12-05 13:44:25 +08:00
|
|
|
}
|
|
|
|
|
2020-04-28 09:33:41 +08:00
|
|
|
net.Lines[0].Data = append(net.Lines[0].Data, int(recentBytesRecv))
|
|
|
|
net.Lines[1].Data = append(net.Lines[1].Data, int(recentBytesSent))
|
|
|
|
if net.sentMetric != nil {
|
2020-05-13 07:42:45 +08:00
|
|
|
net.sentMetric.Add(int(recentBytesSent))
|
|
|
|
net.recvMetric.Add(int(recentBytesRecv))
|
2020-02-19 03:47:52 +08:00
|
|
|
}
|
2018-02-19 15:25:02 +08:00
|
|
|
}
|
|
|
|
|
2018-03-04 09:05:52 +08:00
|
|
|
// used in later calls to update
|
2020-04-28 09:33:41 +08:00
|
|
|
net.totalBytesRecv = totalBytesRecv
|
|
|
|
net.totalBytesSent = totalBytesSent
|
2018-02-20 07:02:01 +08:00
|
|
|
|
2020-04-17 02:28:18 +08:00
|
|
|
rx, tx := "RX/s", "TX/s"
|
2020-04-28 09:33:41 +08:00
|
|
|
if net.Mbps {
|
2020-04-17 02:28:18 +08:00
|
|
|
rx, tx = "mbps", "mbps"
|
|
|
|
}
|
|
|
|
format := " %s: %9.1f %2s/s"
|
|
|
|
|
|
|
|
var total, recent uint64
|
|
|
|
var label, unitRecent, rate string
|
|
|
|
var recentConverted float64
|
2018-05-22 07:02:31 +08:00
|
|
|
// render widget titles
|
2018-02-20 07:02:01 +08:00
|
|
|
for i := 0; i < 2; i++ {
|
2020-04-17 02:28:18 +08:00
|
|
|
if i == 0 {
|
|
|
|
total, label, rate, recent = totalBytesRecv, "RX", rx, recentBytesRecv
|
|
|
|
} else {
|
|
|
|
total, label, rate, recent = totalBytesSent, "TX", tx, recentBytesSent
|
|
|
|
}
|
2018-08-24 02:43:21 +08:00
|
|
|
|
2020-04-17 02:28:18 +08:00
|
|
|
totalConverted, unitTotal := utils.ConvertBytes(total)
|
2020-04-28 09:33:41 +08:00
|
|
|
if net.Mbps {
|
2020-04-17 02:28:18 +08:00
|
|
|
recentConverted, unitRecent, format = float64(recent)*0.000008, "", " %s: %11.3f %2s"
|
|
|
|
} else {
|
|
|
|
recentConverted, unitRecent = utils.ConvertBytes(recent)
|
|
|
|
}
|
2018-08-24 02:43:21 +08:00
|
|
|
|
2020-04-28 09:33:41 +08:00
|
|
|
net.Lines[i].Title1 = fmt.Sprintf(" Total %s: %5.1f %s", label, totalConverted, unitTotal)
|
|
|
|
net.Lines[i].Title2 = fmt.Sprintf(format, rate, recentConverted, unitRecent)
|
2018-02-20 07:02:01 +08:00
|
|
|
}
|
2018-02-19 15:25:02 +08:00
|
|
|
}
|