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:
parent
ae4bcffa06
commit
98b6a7b74e
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user