autoscaling network usage units (#684)
* bytes_info_dict * network auto unit selection * network
This commit is contained in:
parent
a333effc88
commit
d30773b92d
@ -4,7 +4,7 @@ import netifaces
|
||||
|
||||
from i3pystatus import IntervalModule, formatp
|
||||
from i3pystatus.core.color import ColorRangeModule
|
||||
from i3pystatus.core.util import make_graph, round_dict, make_bar
|
||||
from i3pystatus.core.util import make_graph, round_dict, make_bar, bytes_info_dict
|
||||
|
||||
|
||||
def count_bits(integer):
|
||||
@ -184,10 +184,8 @@ class NetworkTraffic:
|
||||
pnic = None
|
||||
pnic_before = None
|
||||
|
||||
def __init__(self, unknown_up, divisor, round_size):
|
||||
def __init__(self, unknown_up):
|
||||
self.unknown_up = unknown_up
|
||||
self.divisor = divisor
|
||||
self.round_size = round_size
|
||||
|
||||
def update_counters(self, interface):
|
||||
import psutil
|
||||
@ -201,10 +199,10 @@ class NetworkTraffic:
|
||||
self.pnic = None
|
||||
|
||||
def get_bytes_sent(self):
|
||||
return (self.pnic.bytes_sent - self.pnic_before.bytes_sent) / self.divisor
|
||||
return self.pnic.bytes_sent - self.pnic_before.bytes_sent
|
||||
|
||||
def get_bytes_received(self):
|
||||
return (self.pnic.bytes_recv - self.pnic_before.bytes_recv) / self.divisor
|
||||
return self.pnic.bytes_recv - self.pnic_before.bytes_recv
|
||||
|
||||
def get_packets_sent(self):
|
||||
return self.pnic.packets_sent - self.pnic_before.packets_sent
|
||||
@ -212,23 +210,23 @@ class NetworkTraffic:
|
||||
def get_packets_received(self):
|
||||
return self.pnic.packets_recv - self.pnic_before.packets_recv
|
||||
|
||||
def get_rx_tot_Mbytes(self, interface):
|
||||
def get_rx_total(self, interface):
|
||||
try:
|
||||
with open("/sys/class/net/{}/statistics/rx_bytes".format(interface)) as f:
|
||||
return int(f.readline().split('\n')[0]) / (1024 * 1024)
|
||||
return int(f.readline().split('\n')[0])
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
def get_tx_tot_Mbytes(self, interface):
|
||||
def get_tx_total(self, interface):
|
||||
try:
|
||||
with open("/sys/class/net/{}/statistics/tx_bytes".format(interface)) as f:
|
||||
return int(f.readline().split('\n')[0]) / (1024 * 1024)
|
||||
return int(f.readline().split('\n')[0])
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
def get_usage(self, interface):
|
||||
self.update_counters(interface)
|
||||
usage = dict(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0)
|
||||
usage = dict(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, rx_total=0, tx_total=0)
|
||||
|
||||
if not sysfs_interface_up(interface, self.unknown_up) or not self.pnic_before:
|
||||
return usage
|
||||
@ -237,9 +235,8 @@ class NetworkTraffic:
|
||||
usage["bytes_recv"] = self.get_bytes_received()
|
||||
usage["packets_sent"] = self.get_packets_sent()
|
||||
usage["packets_recv"] = self.get_packets_received()
|
||||
usage["rx_tot_Mbytes"] = self.get_rx_tot_Mbytes(interface)
|
||||
usage["tx_tot_Mbytes"] = self.get_tx_tot_Mbytes(interface)
|
||||
round_dict(usage, self.round_size)
|
||||
usage["rx_total"] = self.get_rx_total(interface)
|
||||
usage["tx_total"] = self.get_tx_total(interface)
|
||||
return usage
|
||||
|
||||
|
||||
@ -278,12 +275,14 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
* `{interface}` — the configured network interface
|
||||
* `{network_graph_recv}` – Unicode graph representing incoming network traffic
|
||||
* `{network_graph_sent}` – Unicode graph representing outgoing network traffic
|
||||
* `{bytes_sent}` — bytes sent per second (divided by divisor)
|
||||
* `{bytes_recv}` — bytes received per second (divided by divisor)
|
||||
* `{packets_sent}` — bytes sent per second (divided by divisor)
|
||||
* `{packets_recv}` — bytes received per second (divided by divisor)
|
||||
* `{bytes_sent}` — bytes sent per second (divided by divisor | auto calculated if auto_units == True)
|
||||
* `{bytes_recv}` — bytes received per second (divided by divisor | auto calculated if auto_units == True)
|
||||
* `{packets_sent}` — packets sent per second
|
||||
* `{packets_recv}` — packets received per second
|
||||
* `{rx_tot_Mbytes}` — total Mbytes received
|
||||
* `{tx_tot_Mbytes}` — total Mbytes sent
|
||||
* `{rx_tot}` — total traffic recieved (rounded to nearest unit: KB, MB, GB)
|
||||
* `{tx_tot}` — total traffic sent (rounded to nearest unit: KB, MB, GB)
|
||||
"""
|
||||
|
||||
settings = (
|
||||
@ -301,13 +300,13 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
("end_color", "Hex or English name for end of color range, eg '#FF0000' or 'red'"),
|
||||
("graph_width", "Width of the network traffic graph"),
|
||||
("graph_style", "Graph style ('blocks', 'braille-fill', 'braille-peak', or 'braille-snake')"),
|
||||
("recv_limit", "Expected max KiB/s. This value controls the drawing color of receive speed"),
|
||||
("sent_limit", "Expected max KiB/s. similar with receive_limit"),
|
||||
("separate_color", "display recv/send color separate in dynamic color mode."
|
||||
"Note: only network speed formatters will display with range color "),
|
||||
("coloring_type", "Whether to use the sent or received kb/s for dynamic coloring with non-separate colors. "
|
||||
"Allowed values 'recv' or 'sent'"),
|
||||
("divisor", "divide all byte values by this value"),
|
||||
("recv_limit", "Expected max KiB/s. This value controls the drawing color of receive speed"),
|
||||
("sent_limit", "Expected max KiB/s. similar with receive_limit"),
|
||||
("freq_divisor", "divide Wifi frequency by this value"),
|
||||
("ignore_interfaces", "Array of interfaces to ignore when cycling through "
|
||||
"on click, eg, ['lo']"),
|
||||
@ -316,6 +315,7 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
("unknown_up", "If the interface is in unknown state, display it as if it were up"),
|
||||
("next_if_down", "Change to next interface if current one is down"),
|
||||
("detect_active", "Attempt to detect the active interface"),
|
||||
("auto_units", "foo"),
|
||||
)
|
||||
|
||||
# Continue processing statistics when i3bar is hidden.
|
||||
@ -341,6 +341,7 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
# Network traffic settings
|
||||
divisor = 1024
|
||||
round_size = None
|
||||
auto_units = False
|
||||
|
||||
# Network info settings
|
||||
detached_down = True
|
||||
@ -368,8 +369,8 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
# Don't require importing psutil unless using the functionality it offers.
|
||||
if any(s in self.format_up or s in self.format_down for s in
|
||||
['bytes_sent', 'bytes_recv', 'packets_sent', 'packets_recv', 'network_graph_recv',
|
||||
'network_graph_sent', 'rx_tot_Mbytes', 'tx_tot_Mbytes']):
|
||||
self.network_traffic = NetworkTraffic(self.unknown_up, self.divisor, self.round_size)
|
||||
'network_graph_sent', 'rx_tot_Mbytes', 'tx_tot_Mbytes', 'tx_tot', 'rx_tot']):
|
||||
self.network_traffic = NetworkTraffic(self.unknown_up)
|
||||
else:
|
||||
self.network_traffic = None
|
||||
|
||||
@ -380,6 +381,10 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
self.kbs_sent_arr = [0.0] * self.graph_width
|
||||
self.pango_enabled = self.hints.get("markup", False) and self.hints["markup"] == "pango"
|
||||
|
||||
# convert settings from the nominated unit to bytes (backwards compatibility)
|
||||
self.sent_limit *= 1024
|
||||
self.recv_limit *= 1024
|
||||
|
||||
def cycle_interface(self, increment=1):
|
||||
"""Cycle through available interfaces in `increment` steps. Sign indicates direction."""
|
||||
interfaces = [i for i in netifaces.interfaces() if i not in self.ignore_interfaces]
|
||||
@ -409,7 +414,7 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
format_values = dict(network_graph_recv="", network_graph_sent="", bytes_sent="", bytes_recv="",
|
||||
packets_sent="", packets_recv="", rx_tot_Mbytes="", tx_tot_Mbytes="",
|
||||
interface="", v4="", v4mask="", v4cidr="", v6="", v6mask="", v6cidr="", mac="",
|
||||
essid="", freq="", quality="", quality_bar="")
|
||||
essid="", freq="", quality="", quality_bar="", rx_tot='', tx_tot="")
|
||||
|
||||
if self.detect_active:
|
||||
self.interface = detect_active_interface(self.ignore_interfaces, self.interface)
|
||||
@ -420,12 +425,20 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
format_values['network_graph_recv'] = self.get_network_graph_recv(network_usage['bytes_recv'], self.recv_limit)
|
||||
format_values['network_graph_sent'] = self.get_network_graph_sent(network_usage['bytes_sent'], self.sent_limit)
|
||||
|
||||
format_values['tx_tot_Mbytes'] = network_usage['tx_total'] / (1024 * 1024)
|
||||
format_values['rx_tot_Mbytes'] = network_usage['rx_total'] / (1024 * 1024)
|
||||
|
||||
format_values['rx_tot'] = '{value:.{round}f}{unit}'.format(
|
||||
round=self.round_size, **bytes_info_dict(network_usage['rx_total']))
|
||||
format_values['tx_tot'] = '{value:.{round}f}{unit}'.format(
|
||||
round=self.round_size, **bytes_info_dict(network_usage['tx_total']))
|
||||
|
||||
if self.dynamic_color:
|
||||
if self.separate_color and self.pango_enabled:
|
||||
color = self.color_up
|
||||
color_template = "<span color=\"{}\">{}</span>"
|
||||
per_recv = network_usage["bytes_recv"] * self.divisor / (self.recv_limit * 1024)
|
||||
per_sent = network_usage["bytes_sent"] * self.divisor / (self.sent_limit * 1024)
|
||||
per_recv = network_usage["bytes_recv"] / self.recv_limit
|
||||
per_sent = network_usage["bytes_sent"] / self.sent_limit
|
||||
c_recv = self.get_gradient(int(per_recv * 100), self.colors, 100)
|
||||
c_sent = self.get_gradient(int(per_sent * 100), self.colors, 100)
|
||||
format_values["bytes_recv"] = color_template.format(c_recv, network_usage["bytes_recv"])
|
||||
@ -463,6 +476,13 @@ class Network(IntervalModule, ColorRangeModule):
|
||||
format_values.update(network_info)
|
||||
format_values['interface'] = self.interface
|
||||
|
||||
for metric in ('bytes_recv', 'bytes_sent'):
|
||||
if self.auto_units:
|
||||
format_values[metric] = '{value:.{round}f}{unit}'.format(
|
||||
round=self.round_size, **bytes_info_dict(format_values[metric]))
|
||||
else:
|
||||
format_values[metric] = '{:.{round}f}'.format(format_values[metric] / self.divisor, round=self.round_size)
|
||||
|
||||
self.data = format_values
|
||||
self.output = {
|
||||
"full_text": formatp(format_str, **format_values).strip(),
|
||||
|
Loading…
Reference in New Issue
Block a user