admin: allow disabling display of metrics

This is useful in situations where the admins of the Snikket
server (i.e. those who care for the docker containers) are not the
same people as the people who are admins of the Snikket service
(i.e. those who care for the users).
This commit is contained in:
Jonas Schäfer
2021-05-27 17:53:42 +02:00
parent 8a293985ca
commit b40a625283
5 changed files with 132 additions and 107 deletions

View File

@@ -160,6 +160,7 @@ class AppConfig:
# Future versions may change this default, and the standard deployment # Future versions may change this default, and the standard deployment
# tools may also very well override it. # tools may also very well override it.
max_avatar_size = environ.var(1024*1024, converter=int) max_avatar_size = environ.var(1024*1024, converter=int)
show_metrics = environ.bool_var(True)
_UPPER_CASE = "".join(map(chr, range(ord("A"), ord("Z")+1))) _UPPER_CASE = "".join(map(chr, range(ord("A"), ord("Z")+1)))
@@ -191,6 +192,7 @@ def create_app() -> quart.Quart:
app.config["AVATAR_CACHE_TTL"] = config.avatar_cache_ttl app.config["AVATAR_CACHE_TTL"] = config.avatar_cache_ttl
app.config["APPLE_STORE_URL"] = config.apple_store_url app.config["APPLE_STORE_URL"] = config.apple_store_url
app.config["MAX_AVATAR_SIZE"] = config.max_avatar_size app.config["MAX_AVATAR_SIZE"] = config.max_avatar_size
app.config["SHOW_METRICS"] = config.show_metrics
app.context_processor(proc) app.context_processor(proc)
app.register_error_handler( app.register_error_handler(

View File

@@ -20,6 +20,7 @@ from quart import (
request, request,
abort, abort,
flash, flash,
current_app,
) )
from flask_babel import lazy_gettext as _l, _ from flask_babel import lazy_gettext as _l, _
@@ -33,7 +34,11 @@ bp = Blueprint("admin", __name__, url_prefix="/admin")
@bp.route("/") @bp.route("/")
@client.require_admin_session() @client.require_admin_session()
async def index() -> str: async def index() -> str:
return await render_template("admin_home.html") show_metrics = current_app.config["SHOW_METRICS"]
return await render_template(
"admin_home.html",
show_metrics=show_metrics,
)
class PasswordResetLinkPost(BaseForm): class PasswordResetLinkPost(BaseForm):
@@ -575,7 +580,9 @@ def get_system_stats() -> typing.MutableMapping[
(time.monotonic() - _MONOTONIC_EPOCH) (time.monotonic() - _MONOTONIC_EPOCH)
) )
mem_total, mem_available = None, None
load5: typing.Optional[float] = None load5: typing.Optional[float] = None
try: try:
with open("/proc/loadavg") as f: with open("/proc/loadavg") as f:
stats = f.read().split() stats = f.read().split()
@@ -583,7 +590,6 @@ def get_system_stats() -> typing.MutableMapping[
except (ValueError, IndexError, TypeError, OSError): except (ValueError, IndexError, TypeError, OSError):
pass pass
mem_total, mem_available = None, None
try: try:
with open("/proc/meminfo") as f: with open("/proc/meminfo") as f:
for line in f: for line in f:
@@ -650,37 +656,43 @@ async def system() -> typing.Union[str, quart.Response]:
# redirect only if not previewing # redirect only if not previewing
return redirect(url_for(".system")) return redirect(url_for(".system"))
version = await client.get_server_version() version = None
now = time.time() now = None
try: show_metrics = current_app.config["SHOW_METRICS"]
prosody_metrics = await client.get_system_metrics() if show_metrics:
except quart.exceptions.NotFound: version = await client.get_server_version()
# server does not offer the endpoint for whatever reason -- ignore now = time.time()
prosody_metrics = {} try:
prosody_metrics = await client.get_system_metrics()
except quart.exceptions.NotFound:
# server does not offer the endpoint for whatever reason -- ignore
prosody_metrics = {}
metrics = get_system_stats() metrics = get_system_stats()
try: try:
prosody_cpu_metrics = prosody_metrics["cpu"] prosody_cpu_metrics = prosody_metrics["cpu"]
except KeyError: except KeyError:
pass pass
else:
metrics["prosody_cpu"] = (prosody_cpu_metrics["value"] /
(now - prosody_cpu_metrics["since"]))
try:
metrics["prosody_rss"] = prosody_metrics["memory"]
except KeyError:
pass
try:
metrics["prosody_devices"] = prosody_metrics["c2s"]
except KeyError:
pass
for k in list(metrics.keys()):
if metrics[k] is None:
# so that defaulting in jinja works
del metrics[k]
else: else:
metrics["prosody_cpu"] = (prosody_cpu_metrics["value"] / metrics = {}
(now - prosody_cpu_metrics["since"]))
try:
metrics["prosody_rss"] = prosody_metrics["memory"]
except KeyError:
pass
try:
metrics["prosody_devices"] = prosody_metrics["c2s"]
except KeyError:
pass
for k in list(metrics.keys()):
if metrics[k] is None:
# so that defaulting in jinja works
del metrics[k]
return await render_template( return await render_template(
"admin_system.html", "admin_system.html",
@@ -688,4 +700,5 @@ async def system() -> typing.Union[str, quart.Response]:
version=_version.version, version=_version.version,
prosody_version=version, prosody_version=version,
form=form, form=form,
show_metrics=show_metrics,
) )

View File

@@ -34,7 +34,11 @@
<li> <li>
<h2>{% trans %}System health{% endtrans %}</h2> <h2>{% trans %}System health{% endtrans %}</h2>
{#- -#} {#- -#}
{%- if show_metrics -%}
<p>{% trans %}View the server status or send a broadcast message to all users.{% endtrans %}</p> <p>{% trans %}View the server status or send a broadcast message to all users.{% endtrans %}</p>
{%- else -%}
<p>{% trans %}Send a broadcast message to all users.{% endtrans %}</p>
{%- endif -%}
{#- -#} {#- -#}
<div>{% call standard_button("insights", url_for(".system"), class="primary") %}{% trans %}Manage system{% endtrans %}{% endcall %}</div> <div>{% call standard_button("insights", url_for(".system"), class="primary") %}{% trans %}Manage system{% endtrans %}{% endcall %}</div>
{#- -#} {#- -#}

View File

@@ -2,6 +2,7 @@
{% from "library.j2" import form_button %} {% from "library.j2" import form_button %}
{% block content %} {% block content %}
<h1>{% trans %}Manage system{% endtrans %}</h1> <h1>{% trans %}Manage system{% endtrans %}</h1>
{% if show_metrics %}
<h2>{% trans %}Overall system status{% endtrans %}</h2> <h2>{% trans %}Overall system status{% endtrans %}</h2>
<div class="elevated el-2"> <div class="elevated el-2">
<dl> <dl>
@@ -77,6 +78,7 @@
</dd> </dd>
</dl> </dl>
</div> </div>
{% endif %}
<h2>{% trans %}Broadcast message{% endtrans %}</h2> <h2>{% trans %}Broadcast message{% endtrans %}</h2>
<form method="POST">{{ form.csrf_token }}<div class="form layout-expanded"> <form method="POST">{{ form.csrf_token }}<div class="form layout-expanded">
<p class="form-desc">{% trans %}This form allows you to send a message to all users currently online on your Snikket server. Use it wisely.{% endtrans %}</p> <p class="form-desc">{% trans %}This form allows you to send a message to all users currently online on your Snikket server. Use it wisely.{% endtrans %}</p>

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-05-27 17:21+0200\n" "POT-Creation-Date: 2021-05-27 17:59+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,193 +17,193 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.9.1\n" "Generated-By: Babel 2.9.1\n"
#: snikket_web/admin.py:61 #: snikket_web/admin.py:66
msgid "Limited" msgid "Limited"
msgstr "" msgstr ""
#: snikket_web/admin.py:66 snikket_web/templates/admin_delete_user.html:10 #: snikket_web/admin.py:71 snikket_web/templates/admin_delete_user.html:10
#: snikket_web/templates/admin_users.html:8 #: snikket_web/templates/admin_users.html:8
msgid "Login name" msgid "Login name"
msgstr "" msgstr ""
#: snikket_web/admin.py:70 snikket_web/templates/admin_delete_user.html:12 #: snikket_web/admin.py:75 snikket_web/templates/admin_delete_user.html:12
#: snikket_web/templates/admin_users.html:9 snikket_web/user.py:61 #: snikket_web/templates/admin_users.html:9 snikket_web/user.py:61
msgid "Display name" msgid "Display name"
msgstr "" msgstr ""
#: snikket_web/admin.py:74 snikket_web/templates/admin_edit_user.html:32 #: snikket_web/admin.py:79 snikket_web/templates/admin_edit_user.html:32
msgid "Access Level" msgid "Access Level"
msgstr "" msgstr ""
#: snikket_web/admin.py:79 #: snikket_web/admin.py:84
msgid "Normal user" msgid "Normal user"
msgstr "" msgstr ""
#: snikket_web/admin.py:80 #: snikket_web/admin.py:85
msgid "Administrator" msgid "Administrator"
msgstr "" msgstr ""
#: snikket_web/admin.py:85 #: snikket_web/admin.py:90
msgid "Update user" msgid "Update user"
msgstr "" msgstr ""
#: snikket_web/admin.py:89 #: snikket_web/admin.py:94
msgid "Create password reset link" msgid "Create password reset link"
msgstr "" msgstr ""
#: snikket_web/admin.py:107 #: snikket_web/admin.py:112
msgid "Password reset link created" msgid "Password reset link created"
msgstr "" msgstr ""
#: snikket_web/admin.py:122 #: snikket_web/admin.py:127
msgid "User information updated." msgid "User information updated."
msgstr "" msgstr ""
#: snikket_web/admin.py:144 #: snikket_web/admin.py:149
msgid "Delete user permanently" msgid "Delete user permanently"
msgstr "" msgstr ""
#: snikket_web/admin.py:157 #: snikket_web/admin.py:162
msgid "User deleted" msgid "User deleted"
msgstr "" msgstr ""
#: snikket_web/admin.py:195 #: snikket_web/admin.py:200
msgid "Password reset link not found" msgid "Password reset link not found"
msgstr "" msgstr ""
#: snikket_web/admin.py:207 #: snikket_web/admin.py:212
msgid "Password reset link deleted" msgid "Password reset link deleted"
msgstr "" msgstr ""
#: snikket_web/admin.py:227 #: snikket_web/admin.py:232
msgid "Invite to circle" msgid "Invite to circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:233 #: snikket_web/admin.py:238
msgid "At least one circle must be selected" msgid "At least one circle must be selected"
msgstr "" msgstr ""
#: snikket_web/admin.py:238 #: snikket_web/admin.py:243
msgid "Valid for" msgid "Valid for"
msgstr "" msgstr ""
#: snikket_web/admin.py:240 #: snikket_web/admin.py:245
msgid "One hour" msgid "One hour"
msgstr "" msgstr ""
#: snikket_web/admin.py:241 #: snikket_web/admin.py:246
msgid "Twelve hours" msgid "Twelve hours"
msgstr "" msgstr ""
#: snikket_web/admin.py:242 #: snikket_web/admin.py:247
msgid "One day" msgid "One day"
msgstr "" msgstr ""
#: snikket_web/admin.py:243 #: snikket_web/admin.py:248
msgid "One week" msgid "One week"
msgstr "" msgstr ""
#: snikket_web/admin.py:244 #: snikket_web/admin.py:249
msgid "Four weeks" msgid "Four weeks"
msgstr "" msgstr ""
#: snikket_web/admin.py:250 snikket_web/templates/admin_edit_invite.html:17 #: snikket_web/admin.py:255 snikket_web/templates/admin_edit_invite.html:17
msgid "Invitation type" msgid "Invitation type"
msgstr "" msgstr ""
#: snikket_web/admin.py:252 snikket_web/templates/library.j2:116 #: snikket_web/admin.py:257 snikket_web/templates/library.j2:116
msgid "Individual" msgid "Individual"
msgstr "" msgstr ""
#: snikket_web/admin.py:253 snikket_web/templates/library.j2:114 #: snikket_web/admin.py:258 snikket_web/templates/library.j2:114
msgid "Group" msgid "Group"
msgstr "" msgstr ""
#: snikket_web/admin.py:259 #: snikket_web/admin.py:264
msgid "New invitation link" msgid "New invitation link"
msgstr "" msgstr ""
#: snikket_web/admin.py:321 #: snikket_web/admin.py:326
msgid "Revoke" msgid "Revoke"
msgstr "" msgstr ""
#: snikket_web/admin.py:345 #: snikket_web/admin.py:350
msgid "Invitation created" msgid "Invitation created"
msgstr "" msgstr ""
#: snikket_web/admin.py:361 #: snikket_web/admin.py:366
msgid "No such invitation exists" msgid "No such invitation exists"
msgstr "" msgstr ""
#: snikket_web/admin.py:376 #: snikket_web/admin.py:381
msgid "Invitation revoked" msgid "Invitation revoked"
msgstr "" msgstr ""
#: snikket_web/admin.py:393 snikket_web/admin.py:441 #: snikket_web/admin.py:398 snikket_web/admin.py:446
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#: snikket_web/admin.py:398 snikket_web/templates/admin_circles.html:47 #: snikket_web/admin.py:403 snikket_web/templates/admin_circles.html:47
msgid "Create circle" msgid "Create circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:428 #: snikket_web/admin.py:433
msgid "Circle created" msgid "Circle created"
msgstr "" msgstr ""
#: snikket_web/admin.py:446 #: snikket_web/admin.py:451
msgid "Select user" msgid "Select user"
msgstr "" msgstr ""
#: snikket_web/admin.py:451 #: snikket_web/admin.py:456
msgid "Update circle" msgid "Update circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:455 #: snikket_web/admin.py:460
msgid "Delete circle permanently" msgid "Delete circle permanently"
msgstr "" msgstr ""
#: snikket_web/admin.py:461 #: snikket_web/admin.py:466
msgid "Add user" msgid "Add user"
msgstr "" msgstr ""
#: snikket_web/admin.py:477 #: snikket_web/admin.py:482
msgid "No such circle exists" msgid "No such circle exists"
msgstr "" msgstr ""
#: snikket_web/admin.py:514 #: snikket_web/admin.py:519
msgid "Circle data updated" msgid "Circle data updated"
msgstr "" msgstr ""
#: snikket_web/admin.py:520 #: snikket_web/admin.py:525
msgid "Circle deleted" msgid "Circle deleted"
msgstr "" msgstr ""
#: snikket_web/admin.py:531 #: snikket_web/admin.py:536
msgid "User added to circle" msgid "User added to circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:540 #: snikket_web/admin.py:545
msgid "User removed from circle" msgid "User removed from circle"
msgstr "" msgstr ""
#: snikket_web/admin.py:610 #: snikket_web/admin.py:616
msgid "Message contents" msgid "Message contents"
msgstr "" msgstr ""
#: snikket_web/admin.py:616 #: snikket_web/admin.py:622
msgid "Only send to online users" msgid "Only send to online users"
msgstr "" msgstr ""
#: snikket_web/admin.py:620 #: snikket_web/admin.py:626
msgid "Post to all users" msgid "Post to all users"
msgstr "" msgstr ""
#: snikket_web/admin.py:624 #: snikket_web/admin.py:630
msgid "Send preview to yourself" msgid "Send preview to yourself"
msgstr "" msgstr ""
#: snikket_web/admin.py:646 #: snikket_web/admin.py:652
msgid "Announcement sent!" msgid "Announcement sent!"
msgstr "" msgstr ""
@@ -780,20 +780,24 @@ msgstr ""
msgid "System health" msgid "System health"
msgstr "" msgstr ""
#: snikket_web/templates/admin_home.html:37 #: snikket_web/templates/admin_home.html:38
msgid "View the server status or send a broadcast message to all users." msgid "View the server status or send a broadcast message to all users."
msgstr "" msgstr ""
#: snikket_web/templates/admin_home.html:39 #: snikket_web/templates/admin_home.html:40
msgid "Send a broadcast message to all users."
msgstr ""
#: snikket_web/templates/admin_home.html:43
#: snikket_web/templates/admin_system.html:4 #: snikket_web/templates/admin_system.html:4
msgid "Manage system" msgid "Manage system"
msgstr "" msgstr ""
#: snikket_web/templates/admin_home.html:44 #: snikket_web/templates/admin_home.html:48
msgid "Go back to your user's web portal page." msgid "Go back to your user's web portal page."
msgstr "" msgstr ""
#: snikket_web/templates/admin_home.html:46 #: snikket_web/templates/admin_home.html:50
msgid "Exit admin panel" msgid "Exit admin panel"
msgstr "" msgstr ""
@@ -844,72 +848,72 @@ msgstr ""
msgid "Destroy link" msgid "Destroy link"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:5 #: snikket_web/templates/admin_system.html:6
msgid "Overall system status" msgid "Overall system status"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:8 #: snikket_web/templates/admin_system.html:9
msgid "System load (5 minute average)" msgid "System load (5 minute average)"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:13 #: snikket_web/templates/admin_system.html:14
#: snikket_web/templates/admin_system.html:21 #: snikket_web/templates/admin_system.html:22
#: snikket_web/templates/admin_system.html:36 #: snikket_web/templates/admin_system.html:37
#: snikket_web/templates/admin_system.html:44 #: snikket_web/templates/admin_system.html:45
#: snikket_web/templates/admin_system.html:59 #: snikket_web/templates/admin_system.html:60
#: snikket_web/templates/admin_system.html:67 #: snikket_web/templates/admin_system.html:68
#: snikket_web/templates/admin_system.html:75 #: snikket_web/templates/admin_system.html:76
msgid "unknown" msgid "unknown"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:16 #: snikket_web/templates/admin_system.html:17
msgid "Memory use" msgid "Memory use"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:19 #: snikket_web/templates/admin_system.html:20
#, python-format #, python-format
msgid "" msgid ""
"%(percentage_global)s of %(mem_available)s. Of that, Snikket uses " "%(percentage_global)s of %(mem_available)s. Of that, Snikket uses "
"%(percentage_snikket)s." "%(percentage_snikket)s."
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:26 #: snikket_web/templates/admin_system.html:27
msgid "Web portal status" msgid "Web portal status"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:29
#: snikket_web/templates/admin_system.html:52
msgid "Version"
msgstr ""
#: snikket_web/templates/admin_system.html:30 #: snikket_web/templates/admin_system.html:30
#: snikket_web/templates/admin_system.html:53 #: snikket_web/templates/admin_system.html:53
msgid "View all versions" msgid "Version"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:31 #: snikket_web/templates/admin_system.html:31
#: snikket_web/templates/admin_system.html:54 #: snikket_web/templates/admin_system.html:54
msgid "View all versions"
msgstr ""
#: snikket_web/templates/admin_system.html:32
#: snikket_web/templates/admin_system.html:55
msgid "Average CPU use" msgid "Average CPU use"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:39 #: snikket_web/templates/admin_system.html:40
#: snikket_web/templates/admin_system.html:62 #: snikket_web/templates/admin_system.html:63
msgid "Current memory use" msgid "Current memory use"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:49 #: snikket_web/templates/admin_system.html:50
msgid "Snikket server status" msgid "Snikket server status"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:70 #: snikket_web/templates/admin_system.html:71
msgid "Connected devices" msgid "Connected devices"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:80 #: snikket_web/templates/admin_system.html:82
msgid "Broadcast message" msgid "Broadcast message"
msgstr "" msgstr ""
#: snikket_web/templates/admin_system.html:82 #: snikket_web/templates/admin_system.html:84
msgid "" msgid ""
"This form allows you to send a message to all users currently online on " "This form allows you to send a message to all users currently online on "
"your Snikket server. Use it wisely." "your Snikket server. Use it wisely."