Commit 68bb94d1 authored by David Huss's avatar David Huss 💬
Browse files

Add --read-load-from option to meetings

parent bcdba8a5
__version__ = '0.1.31'
__version__ = '0.1.32'
......@@ -13,6 +13,7 @@ from bbbmon.xmldict import XmlListConfig, XmlDictConfig
from bbbmon.configuration import Config, Endpoint, SERVER_PROPERTIES_FILE, Url, Secret, get_user_config_path, init_config, new_config
from bbbmon.meetings import *
from bbbmon.printing import *
from bbbmon.load import *
......@@ -53,7 +54,7 @@ def main(userconfig, watch, version):
Internally bbbmon relies on the offical bbb-API, which means you need to have the server's secret in order to create a valid request. Create a new configuration with: bbbmon config --new
"""
__version__ = "0.1.31"
__version__ = "0.1.32"
if version:
print(__version__)
......@@ -68,6 +69,7 @@ def main(userconfig, watch, version):
@click.option('--endpoint', '-e', multiple=True, help="Filter by one or more endpoints as named in the user configuration (e.g. [servername]). Order is respected.")
@click.option('--watch', '-w', help="Run repeatedly with the given interval in seconds", type=click.IntRange(2, 2147483647, clamp=True))
@click.option('-n', help="The number of meetings to show in the leaderboards (Default: 5)", type=int)
@click.option('--read-load-from', help="Read the load from file/https (if starts with http(s) request, else read from path). Looks for floats and calculates the average.", type=str)
@click.option('--leaderboards/--no-leaderboards', default=True, show_default=True, help="Hide or show the meeting leaderboards")
@click.option('--participants/--no-participants', default=True, show_default=True, help="Hide or show the participants")
@click.option('--meetings/--no-meetings', default=True, show_default=True, help="Hide or show the meetings")
......@@ -79,7 +81,7 @@ def main(userconfig, watch, version):
@click.option('--all', '-a', 'all_', is_flag=True, help="Print all")
@click.option('--fancy/--no-fancy', default=False, show_default=True, help="Use fancy headers")
@click.option('--sum','sum_', is_flag=True, help="Print all")
def meetings(ctx, userconfig, watch, short, compact, n, all_, twolines, leaderboards, participants, presenter, presenter_id, meetings, endpoint, fancy, sum_):
def meetings(ctx, userconfig, watch, short, compact, n, all_, twolines, read_load_from, leaderboards, participants, presenter, presenter_id, meetings, endpoint, fancy, sum_):
"""View currently active meetings"""
if short:
leaderboards = False
......@@ -99,21 +101,25 @@ def meetings(ctx, userconfig, watch, short, compact, n, all_, twolines, leaderbo
config = init_config(userconfig)
config.filter_endpoints(endpoint)
# Load is none if it doesn't work
load = read_load(read_load_from)
if watch is not None:
while watch is not None:
try:
if twolines:
meetings_twolines(config, watch, fancy, sum_)
meetings_twolines(config, watch, fancy, sum_, load)
else:
list_meetings(config, leaderboards, n, participants, presenter, presenter_id, meetings, watch, fancy, compact, sum_)
list_meetings(config, leaderboards, n, participants, presenter, presenter_id, meetings, watch, fancy, compact, sum_, load)
time.sleep(watch)
except KeyboardInterrupt:
sys.exit()
else:
if twolines:
meetings_twolines(config, watch, fancy, sum_)
meetings_twolines(config, watch, fancy, sum_, load)
else:
list_meetings(config, leaderboards, n, participants, presenter, presenter_id, meetings, watch, fancy, compact, sum_)
list_meetings(config, leaderboards, n, participants, presenter, presenter_id, meetings, watch, fancy, compact, sum_, load)
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import re
import requests
from typing import Optional
from bbbmon.printing import eprint
LOAD_PATTERN = re.compile(r"(?!\d+\.\d+[\./])\d+\.\d+")
def read_load(read_load_from: Optional[str]) -> Optional[float]:
"""
Read the load either from a file or a url depending on the input. Return None if anything fails.
This matches all floats in the given file/url and returns the average
"""
if read_load_from is None:
return None
text = ""
if read_load_from.lower().startswith(("http")):
try:
r = requests.get(read_load_from, timeout=3)
text = r.text
except:
eprint("Error: Ignored load - Couldn't read load from {}: Response was: {}".format(read_load_from, r))
return None
else:
if os.path.isfile(read_load_from):
with open(read_load_from, "r", encoding="utf-8") as f:
text = f.read()
else:
eprint("Error: Ignored load - Couldn't read load from {}: Not a file or not readable".format(read_load_from))
return None
text = text.strip()
if text == "":
eprint("Error: Ignored load - Couldn't read load from {}: The file was empty".format(read_load_from))
return None
matches = re.findall(LOAD_PATTERN, text)
if matches is None:
eprint("Error: Ignored load - Couldn't read load from {}: No float values found".format(read_load_from))
return None
elif len(matches) == 0:
eprint("Error: Ignored load - Couldn't read load from {}: No float values found".format(read_load_from))
return None
else:
return sum([float(m) for m in matches]) / float(len(matches))
\ No newline at end of file
......@@ -143,7 +143,7 @@ def get_duration(meeting: XmlDictConfig) -> timedelta:
return duration
def list_meetings(config: Config, leaderboards: bool, n: int, participants: bool, presenter: bool, presenter_id: bool, show_meetings: bool, watch: int, fancy: bool, compact: bool, sum_:bool):
def list_meetings(config: Config, leaderboards: bool, n: int, participants: bool, presenter: bool, presenter_id: bool, show_meetings: bool, watch: int, fancy: bool, compact: bool, sum_:bool, load: Optional[float]):
"""
For each endpoint in the configuration get the active meetings and print
out an overview of the current bbb-usage
......@@ -163,6 +163,10 @@ def list_meetings(config: Config, leaderboards: bool, n: int, participants: bool
if watch is not None:
click.clear()
# Average load
if load is not None:
print("Average load is: {:04.2f}".format(load))
for i, endpoint in enumerate(config_override.endpoints):
# Print divider if there is more than one endpoint
......@@ -270,7 +274,7 @@ def sum_meetings(config: Config, meetings: Optional[XmlDictConfig]) -> Optiona
def meetings_twolines(config: Config, watch: int, fancy: bool, sum_:bool):
def meetings_twolines(config: Config, watch: int, fancy: bool, sum_:bool, load: Optional[float]):
"""
For each endpoint in the configuration get the active meetings and print
out an overview of the current bbb-usage. This is guaranteed to fit within
......@@ -349,7 +353,7 @@ def meetings_twolines(config: Config, watch: int, fancy: bool, sum_:bool):
avg_s = avg_s/60./60.
if not fancy:
if config_override.on_server:
if config_override.on_server and load is None:
# If on server get load
w = subprocess.run(["w | head -1"], shell=True, stdout=subprocess.PIPE)
w = w.stdout.decode('utf-8').strip().split("load average:")
......@@ -366,6 +370,12 @@ def meetings_twolines(config: Config, watch: int, fancy: bool, sum_:bool):
"stats {:>2} / {:<2} {:>3} {:>3} {:>3} {:>3} {:>3} {:.1f}"\
.format(n_recording, n_running, n_participants, n_moderator, n_video, n_voice, n_listeners, w)
]
elif load is not None:
lines = [
"{} rec / ses ppl mod vid mic ear lod".format(endpoint.name[:3]),
"stats {:>2} / {:<2} {:>3} {:>3} {:>3} {:>3} {:>3} {:.1f}"\
.format(n_recording, n_running, n_participants, n_moderator, n_video, n_voice, n_listeners, load)
]
else:
lines = [
"{} rec / ses ppl mod vid mic ear".format(endpoint.name[:3]),
......
[tool.poetry]
name = "bbbmon"
version = "0.1.31"
version = "0.1.32"
description = "A small CLI utility to monitor bbb usage"
authors = ["David Huss <david.huss@hfbk-hamburg.de>"]
maintainers = ["David Huss <david.huss@hfbk-hamburg.de>"]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment