Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/widget_maker.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import (
"github.com/wtfutil/wtf/modules/lunarphase"
"github.com/wtfutil/wtf/modules/mercurial"
"github.com/wtfutil/wtf/modules/nbascore"
"github.com/wtfutil/wtf/modules/netmon"
"github.com/wtfutil/wtf/modules/newrelic"
"github.com/wtfutil/wtf/modules/nextbus"
"github.com/wtfutil/wtf/modules/opsgenie"
Expand Down Expand Up @@ -260,6 +261,9 @@ func MakeWidget(
case "nbascore":
settings := nbascore.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = nbascore.NewWidget(tviewApp, redrawChan, pages, settings)
case "netmon":
settings := netmon.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = netmon.NewWidget(tviewApp, redrawChan, settings)
case "newrelic":
settings := newrelic.NewSettingsFromYAML(moduleName, moduleConfig, config)
widget = newrelic.NewWidget(tviewApp, redrawChan, pages, settings)
Expand Down
36 changes: 36 additions & 0 deletions modules/netmon/example-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
wtf:
colors:
# background: black
# foreground: blue
border:
focusable: darkslateblue
focused: orange
normal: gray
checked: yellow
highlight:
fore: black
back: gray
rows:
even: yellow
odd: white
grid:
columns: [35]
rows: [8]
refreshInterval: 1
mods:
netmon:
type: netmon
title: "Network Monitor"
enabled: true
showOnly: "wlo1"
ignoreLoopback: true
ignoreEthernet: false
ignoreBridges: true
ignoreDocker: false
ignoreVeth: true
position:
top: 0
left: 0
height: 1
width: 1
refreshInterval: 1
41 changes: 41 additions & 0 deletions modules/netmon/settings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package netmon

import (
"github.com/olebedev/config"
"github.com/wtfutil/wtf/cfg"
)

const (
defaultFocusable = false
defaultTitle = "Network Monitor"
)

type Settings struct {
*cfg.Common

showOnly string

ignoreLoopback bool
ignoreEthernet bool
ignoreWireless bool
ignoreBridges bool
ignoreDocker bool
ignoreVeth bool
}

func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
settings := Settings{
Common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),

showOnly: ymlConfig.UString("showOnly"),

ignoreLoopback: ymlConfig.UBool("ignoreLoopback"),
ignoreEthernet: ymlConfig.UBool("ignoreEthernet"),
ignoreWireless: ymlConfig.UBool("ignoreWireless"),
ignoreBridges: ymlConfig.UBool("ignoreBridges"),
ignoreDocker: ymlConfig.UBool("ignoreDocker"),
ignoreVeth: ymlConfig.UBool("ignoreVeth"),
}

return &settings
}
110 changes: 110 additions & 0 deletions modules/netmon/widget.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package netmon

import (
"fmt"
"strings"

"github.com/shirou/gopsutil/net"

"github.com/rivo/tview"
"github.com/wtfutil/wtf/view"
)

type Widget struct {
view.TextWidget
settings *Settings
interfaces map[string]*NIC
}

type NIC struct {
Name string
Sent uint64
Recv uint64
}

func NewWidget(tviewApp *tview.Application, redrawChan chan bool, settings *Settings) *Widget {
widget := Widget{
TextWidget: view.NewTextWidget(tviewApp, redrawChan, nil, settings.Common),
settings: settings,
}

widget.SetupNICs()
return &widget
}

func (widget *Widget) SetupNICs() {
widget.interfaces = make(map[string]*NIC)
interfaces, _ := net.IOCounters(true)

for _, nic := range interfaces {
if widget.settings.ignoreLoopback && strings.HasPrefix(nic.Name, "lo") ||
widget.settings.ignoreEthernet && strings.HasPrefix(nic.Name, "e") ||
widget.settings.ignoreWireless && strings.HasPrefix(nic.Name, "wl") ||
widget.settings.ignoreBridges && strings.HasPrefix(nic.Name, "br") ||
widget.settings.ignoreDocker && strings.HasPrefix(nic.Name, "docker") ||
widget.settings.ignoreVeth && strings.HasPrefix(nic.Name, "veth") {
continue
}
if widget.settings.showOnly != "" {
if widget.settings.showOnly == nic.Name {
widget.addInterface(nic)
break
}
} else {
widget.addInterface(nic)
}

}
}

func (widget *Widget) Refresh() {
widget.Redraw(widget.content)
}

func (widget *Widget) content() (string, string, bool) {
var content strings.Builder

interfaces, err := net.IOCounters(true)
if err != nil {
return widget.CommonSettings().Title, err.Error(), true
}
for _, nic := range interfaces {
if NIC, ok := widget.interfaces[nic.Name]; ok {
prevSent, prevRecv := NIC.Sent, NIC.Recv
NIC.Sent, NIC.Recv = nic.BytesSent, nic.BytesRecv
fmt.Fprintf(&content, "%-9s▲%9s ▼%9s\n",
PrettyName(nic.Name),
prettyBits(nic.BytesSent-prevSent),
prettyBits(nic.BytesRecv-prevRecv))
}
}
return widget.CommonSettings().Title, content.String(), true
}

func (widget *Widget) addInterface(nic net.IOCountersStat) {
widget.interfaces[nic.Name] = &NIC{
Name: nic.Name,
Sent: nic.BytesSent,
Recv: nic.BytesRecv,
}
}

func PrettyName(name string) string {
if len(name) > 7 {
name = name[:6] + "…"
}
return name + ":"
}

func prettyBits(bytes uint64) string {
bits := bytes * 8
bps := "bps"
if bits > 1000000 {
bits /= 1000000
bps = "M" + bps
} else if bits > 1000 {
bits /= 1000
bps = "K" + bps
}
return fmt.Sprintf("%v %s", bits, bps)
}
Loading