Add detail tooltips in server browser stability %

When hovering on stability percentages in the server browser, a tooltip
now shows the total downtime in the past 30 days, number of incidents,
their average length and the longest's duration.
This commit is contained in:
miruka 2021-01-11 07:50:32 -04:00
parent ae4bcffa06
commit 98b6a7b74e
3 changed files with 46 additions and 17 deletions

View File

@ -7,7 +7,7 @@ import os
import re import re
import sys import sys
import time import time
from datetime import datetime from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
from typing import Any, DefaultDict, Dict, List, Optional, Tuple, Union from typing import Any, DefaultDict, Dict, List, Optional, Tuple, Union
from urllib.parse import urlparse from urllib.parse import urlparse
@ -492,8 +492,13 @@ class Backend:
) )
def _get_homeserver_stability(self, logs: List[Dict[str, Any]]) -> float: def _get_homeserver_stability(
self, logs: List[Dict[str, Any]],
) -> Tuple[float, List[timedelta]]:
"""Return server stability % and a list of downtime durations."""
stability = 100.0 stability = 100.0
durations = []
for period in logs: for period in logs:
started_at = datetime.fromtimestamp(period["datetime"]) started_at = datetime.fromtimestamp(period["datetime"])
@ -502,14 +507,15 @@ class Backend:
if time_since_now.days > 30 or period["type"] != 1: # 1 = downtime if time_since_now.days > 30 or period["type"] != 1: # 1 = downtime
continue continue
lasted_minutes = period["duration"] / 60 lasted_minutes = period["duration"] / 60
durations.append(timedelta(seconds=period["duration"]))
stability -= ( stability -= (
(lasted_minutes * stability / 1000) / (lasted_minutes * stability / 1000) /
max(1, time_since_now.days / 3) max(1, time_since_now.days / 3)
) )
return stability return (stability, durations)
async def fetch_homeservers(self) -> None: async def fetch_homeservers(self) -> None:
@ -533,13 +539,16 @@ class Backend:
if server["country"] == "USA": if server["country"] == "USA":
server["country"] = "United States" server["country"] = "United States"
stability, durations = \
self._get_homeserver_stability(server["monitor"]["logs"])
self.models["homeservers"][homeserver_url] = Homeserver( self.models["homeservers"][homeserver_url] = Homeserver(
id = homeserver_url, id = homeserver_url,
name = server["name"], name = server["name"],
site_url = server["url"], site_url = server["url"],
country = server["country"], country = server["country"],
stability = stability = stability,
self._get_homeserver_stability(server["monitor"]["logs"]), downtimes_ms = [d.total_seconds() * 1000 for d in durations],
) )
coros.append(self._ping_homeserver(session, homeserver_url)) coros.append(self._ping_homeserver(session, homeserver_url))

View File

@ -42,13 +42,14 @@ class PingStatus(AutoStrEnum):
class Homeserver(ModelItem): class Homeserver(ModelItem):
"""A homeserver we can connect to. The `id` field is the server's URL.""" """A homeserver we can connect to. The `id` field is the server's URL."""
id: str = field() id: str = field()
name: str = field() name: str = field()
site_url: str = field() site_url: str = field()
country: str = field() country: str = field()
ping: int = -1 ping: int = -1
status: PingStatus = PingStatus.Pinging status: PingStatus = PingStatus.Pinging
stability: float = -1 stability: float = -1
downtimes_ms: List[float] = field(default_factory=list)
def __lt__(self, other: "Homeserver") -> bool: def __lt__(self, other: "Homeserver") -> bool:
return (self.name.lower(), self.id) < (other.name.lower(), other.id) return (self.name.lower(), self.id) < (other.name.lower(), other.id)

View File

@ -79,6 +79,25 @@ HTile {
model.stability >= 95 ? theme.colors.positiveText : model.stability >= 95 ? theme.colors.positiveText :
model.stability >= 85 ? theme.colors.warningText : model.stability >= 85 ? theme.colors.warningText :
theme.colors.errorText theme.colors.errorText
HoverHandler { id: rightInfoHover }
HToolTip {
readonly property var times: JSON.parse(model.downtimes_ms)
readonly property real total: utils.sum(times)
visible: model.stability !== -1 && rightInfoHover.hovered
text:
total === 0 ?
qsTr("No downtimes in the last 30 days") :
qsTr(
"Last 30 days downtimes: %1, average: %2, " +
"longest: %3, total: %4"
).arg(times.length)
.arg(utils.formatRelativeTime(total / times.length))
.arg(utils.formatRelativeTime(Math.max.apply(Math,times)))
.arg(utils.formatRelativeTime(total))
}
} }
HButton { HButton {