Gracefully degrade under load, fixes #2

This commit is contained in:
Martinez 2016-10-06 11:42:15 +02:00
parent 79b47e1130
commit 3358c807a0

View file

@ -268,14 +268,15 @@ class PathPart(Part):
""" """
/path/to/cwd /path/to/cwd
Contructs a list of Dirs from the root to CWD. When fit is called, some Dirs may be shortened. Contructs a list of Dirs from the root to CWD. When shrink_fit is called, some Dirs may be shortened.
""" """
def __init__(self, settings):
def __init__(self, settings, overloaded):
Part.__init__(self) Part.__init__(self)
self.term_width = settings.term_width self.term_width = settings.term_width
self.dirs = [] self.dirs = []
homes = dict(list_homes()) homes = {} if overloaded else dict(list_homes())
dirs = settings.cwd.split("/")[1:] dirs = settings.cwd.split("/")[1:]
path = "" path = ""
@ -490,126 +491,135 @@ class StatsPart(Part):
# tasks # tasks
self.fragments.append("%d " %(sysload.tasks_total)) self.fragments.append("%d " %(sysload.tasks_total))
# memory (and swap, if used) if sysload.load1 >= settings.load_error:
mem_total = 0 self.fragments.append(" | ")
mem_free = 0
swap_total = 0
swap_free = 0
# MemAvailable is not available on <linux-3.14 and we'll bitch about that
old_linux = True
with open("/proc/meminfo") as f:
for line in f:
if line.startswith("MemTotal"):
mem_total = int(line.split()[1]) * 1024
elif line.startswith("MemAvailable"):
mem_free = int(line.split()[1]) * 1024
old_linux = False
elif line.startswith("SwapTotal"):
swap_total = int(line.split()[1]) * 1024
elif line.startswith("SwapFree"):
swap_free = int(line.split()[1]) * 1024
if old_linux:
self.fragments.append(style_color(COLOR_ERROR)) self.fragments.append(style_color(COLOR_ERROR))
self.fragments.append(style_bold()) self.fragments.append(style_bold())
self.fragments.append("❌ <linux-3.14 ❌") self.fragments.append("⚠ OVERLOAD ⚠ ")
else:
self.fragments.append(style_color(COLOR_MEMSWAP))
self.fragments.append("m")
self.fragments.append(style_bold())
self.fragments.append(style_color(settings.get_space_color(mem_free, mem_total)))
mem_free_si = si_number(mem_free)
self.fragments.append(space_string(mem_free) %(mem_free_si[0], mem_free_si[1]))
self.fragments.append(style_reset())
if swap_total - swap_free > 2**20:
self.fragments.append(style_color(COLOR_MEMSWAP))
self.fragments.append(" s")
self.fragments.append(style_bold())
self.fragments.append(style_color(settings.get_space_color(swap_free, swap_total)))
swap_free_si = si_number(swap_free)
self.fragments.append(space_string(swap_free) %(swap_free_si[0], swap_free_si[1]))
self.fragments.append(style_reset()) self.fragments.append(style_reset())
# mountpoints else:
names = [] # memory (and swap, if used)
first_mountpoint = True mem_total = 0
mem_free = 0
with open("/proc/self/mounts") as f: swap_total = 0
for line in f: swap_free = 0
_, dir, type, options, *rest = line.split()
# MemAvailable is not available on <linux-3.14 and we'll bitch about that
# skip non-storage mounts old_linux = True
if type in MOUNT_IGNORE_FS:
continue with open("/proc/meminfo") as f:
for line in f:
if any([dir.startswith(d) for d in MOUNT_IGNORE_DIR]): if line.startswith("MemTotal"):
continue mem_total = int(line.split()[1]) * 1024
elif line.startswith("MemAvailable"):
if "rw" not in options.split(","): mem_free = int(line.split()[1]) * 1024
continue old_linux = False
elif line.startswith("SwapTotal"):
# /proc/self/mounts uses a literal \040 string to escape spaces swap_total = int(line.split()[1]) * 1024
dir = dir.replace("\\040", " ") elif line.startswith("SwapFree"):
swap_free = int(line.split()[1]) * 1024
basename = os.path.basename(dir)
if old_linux:
if basename: self.fragments.append(style_color(COLOR_ERROR))
short_name = " " self.fragments.append(style_bold())
self.fragments.append("⚠ <linux-3.14 ⚠")
else:
self.fragments.append(style_color(COLOR_MEMSWAP))
self.fragments.append("m")
self.fragments.append(style_bold())
self.fragments.append(style_color(settings.get_space_color(mem_free, mem_total)))
mem_free_si = si_number(mem_free)
self.fragments.append(space_string(mem_free) %(mem_free_si[0], mem_free_si[1]))
self.fragments.append(style_reset())
if swap_total - swap_free > 2**20:
self.fragments.append(style_color(COLOR_MEMSWAP))
self.fragments.append(" s")
self.fragments.append(style_bold())
self.fragments.append(style_color(settings.get_space_color(swap_free, swap_total)))
swap_free_si = si_number(swap_free)
self.fragments.append(space_string(swap_free) %(swap_free_si[0], swap_free_si[1]))
self.fragments.append(style_reset())
# mountpoints
names = []
first_mountpoint = True
with open("/proc/self/mounts") as f:
for line in f:
_, dir, type, options, *rest = line.split()
for c in basename: # skip non-storage mounts
short_name += c if type in MOUNT_IGNORE_FS:
if short_name not in names:
break
else:
short_name = " /"
# handle btrfs separately
if type == "btrfs":
btrfs_raw = command(["/sbin/btrfs", "fi", "usage", "-b", dir])
for line in btrfs_raw.split("\n"):
if "Device size" in line:
stor_total = int(line.split()[-1])
elif "Free" in line:
stor_free = int(line.split()[-3])
break
else:
try:
stat = os.statvfs(dir)
except PermissionError:
continue continue
stor_total = stat.f_blocks * stat.f_bsize if any([dir.startswith(d) for d in MOUNT_IGNORE_DIR]):
stor_free = stat.f_bavail * stat.f_bsize continue
# ignore virtual filesystems if "rw" not in options.split(","):
if stor_total == 0: continue
continue
# /proc/self/mounts uses a literal \040 string to escape spaces
if first_mountpoint: dir = dir.replace("\\040", " ")
self.fragments.append(" |")
first_mountpoint = False basename = os.path.basename(dir)
self.fragments.append(short_name) if basename:
self.fragments.append(style_bold()) short_name = " "
self.fragments.append(style_color(settings.get_space_color(stor_free, stor_total)))
stor_free_si = si_number(stor_free) for c in basename:
self.fragments.append(space_string(stor_free) %(stor_free_si[0], stor_free_si[1])) short_name += c
self.fragments.append(style_reset())
if short_name not in names:
break
else:
short_name = " /"
# handle btrfs separately
if type == "btrfs":
btrfs_raw = command(["/sbin/btrfs", "fi", "usage", "-b", dir])
for line in btrfs_raw.split("\n"):
if "Device size" in line:
stor_total = int(line.split()[-1])
elif "Free" in line:
stor_free = int(line.split()[-3])
break
else:
try:
stat = os.statvfs(dir)
except PermissionError:
continue
stor_total = stat.f_blocks * stat.f_bsize
stor_free = stat.f_bavail * stat.f_bsize
# ignore virtual filesystems
if stor_total == 0:
continue
if first_mountpoint:
self.fragments.append(" |")
first_mountpoint = False
self.fragments.append(short_name)
self.fragments.append(style_bold())
self.fragments.append(style_color(settings.get_space_color(stor_free, stor_total)))
stor_free_si = si_number(stor_free)
self.fragments.append(space_string(stor_free) %(stor_free_si[0], stor_free_si[1]))
self.fragments.append(style_reset())
if __name__ == "__main__": if __name__ == "__main__":
settings = Settings(sys.argv) settings = Settings(sys.argv)
sysload = Sysload() sysload = Sysload()
overloaded = sysload.load1 >= settings.load_error
lp = LoginPart(settings, sysload) lp = LoginPart(settings, sysload)
pp = PathPart(settings) pp = PathPart(settings, overloaded)
gp = GitPart() gp = "" if overloaded else GitPart()
vp = VirtualEnvPart() vp = VirtualEnvPart()
wp = WineprefixPart() wp = WineprefixPart()
pad = Padding(settings.term_width) pad = Padding(settings.term_width)