diff --git a/CHANGELOG.md b/CHANGELOG.md index e8ae3dfa..aafa30f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Add server import status indicators ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/433)) - Users can now be assigned as manager of other users/roles ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/434)) - Add variable shutdown timeouts ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/435)) +- Add server metrics graph ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/436)) ### Bug fixes - Fix creation quota not refilling after server delete ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/434)) ### Tweaks diff --git a/app/classes/controllers/servers_controller.py b/app/classes/controllers/servers_controller.py index 2f0ba47b..a0948769 100644 --- a/app/classes/controllers/servers_controller.py +++ b/app/classes/controllers/servers_controller.py @@ -4,6 +4,7 @@ import time import json import pathlib import typing as t +import datetime from app.classes.controllers.roles_controller import RolesController from app.classes.shared.file_helpers import FileHelpers @@ -104,6 +105,13 @@ class ServersController(metaclass=Singleton): server_instance.update_server_instance() return ret + def get_history_stats(self, server_id): + max_age = self.helper.get_setting("history_max_age") + now = datetime.datetime.now() + minimum_to_exist = now - datetime.timedelta(days=max_age) + srv = ServersController().get_server_instance_by_id(server_id) + return srv.stats_helper.get_history_stats(server_id, minimum_to_exist) + @staticmethod def update_unloaded_server(server_obj): ret = HelperServers.update_server(server_obj) diff --git a/app/classes/models/server_stats.py b/app/classes/models/server_stats.py index 906eed8b..6e589ffc 100644 --- a/app/classes/models/server_stats.py +++ b/app/classes/models/server_stats.py @@ -137,6 +137,14 @@ class HelperServerStats: ) return server_data + def get_history_stats(self, server_id, max_age): + return ( + ServerStats.select() + .where(ServerStats.created > max_age) + .where(ServerStats.server_id == server_id) + .execute(self.database) + ) + def insert_server_stats(self, server_stats): server_id = server_stats.get("id", 0) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 8a77887e..0b2c5b96 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -1227,6 +1227,7 @@ class ServerInstance: "version": raw_ping_result.get("version"), "icon": raw_ping_result.get("icon"), "crashed": self.is_crashed, + "created": datetime.datetime.now().strftime("%Y/%m/%d, %H:%M:%S"), }, ) total_players += int(raw_ping_result.get("online")) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 8d0249da..a8bac6e2 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -524,6 +524,7 @@ class PanelHandler(BaseHandler): "files", "admin_controls", "schedules", + "metrics", ] if not self.failed_server: server = self.controller.servers.get_server_instance_by_id(server_id) @@ -754,6 +755,11 @@ class PanelHandler(BaseHandler): page_data["backup_list"] = [] page_data["backup_path"] = Helpers.wtol_path(server_info["backup_path"]) + if subpage == "metrics": + page_data["history_stats"] = self.controller.servers.get_history_stats( + server_id + ) + def get_banned_players_html(): banned_players = self.controller.servers.get_banned_players(server_id) if banned_players is None: diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index 46b6e622..1ab50da8 100755 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -40,6 +40,16 @@ + + + + diff --git a/app/frontend/templates/panel/parts/m_server_controls_list.html b/app/frontend/templates/panel/parts/m_server_controls_list.html index 4a114b52..52f3d04d 100644 --- a/app/frontend/templates/panel/parts/m_server_controls_list.html +++ b/app/frontend/templates/panel/parts/m_server_controls_list.html @@ -30,6 +30,7 @@ {% if data['permissions']['Players'] in data['user_permissions'] and data['server_data']['type'] != 'minecraft-bedrock' %} {{ translate('serverDetails', 'playerControls', data['lang']) }} {% end %} + {{ translate('serverDetails', 'metrics', data['lang']) }} \ No newline at end of file diff --git a/app/frontend/templates/panel/parts/server_controls_list.html b/app/frontend/templates/panel/parts/server_controls_list.html index 8e40e7ec..4212bde6 100644 --- a/app/frontend/templates/panel/parts/server_controls_list.html +++ b/app/frontend/templates/panel/parts/server_controls_list.html @@ -49,4 +49,8 @@ {{ translate('serverDetails', 'playerControls', data['lang']) }} {% end %} + \ No newline at end of file diff --git a/app/frontend/templates/panel/server_metrics.html b/app/frontend/templates/panel/server_metrics.html new file mode 100644 index 00000000..9bf46941 --- /dev/null +++ b/app/frontend/templates/panel/server_metrics.html @@ -0,0 +1,225 @@ +{% extends ../base.html %} + +{% block meta %} +{% end %} + +{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %} + +{% block content %} + +
+ + +
+
+ +
+ +
+ + + {% include "parts/details_stats.html %} + +
+ +
+
+
+ + {% include "parts/server_controls_list.html %} + + + {% include "parts/m_server_controls_list.html %} + + + {% if data['user_data']['hints'] %} + + {% end %} +
+ +
+ +
+
+
+
+ + + +
+ + + +{% end %} \ No newline at end of file diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 1a40e5ba..0f510b90 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -355,7 +355,8 @@ "playerControls": "Player Management", "schedule": "Schedule", "serverDetails": "Server Details", - "terminal": "Terminal" + "terminal": "Terminal", + "metrics": "Metrics" }, "serverFiles": { "clickUpload": "Click here to select your files", @@ -476,6 +477,11 @@ "stopScroll": "Stop Auto Scrolling", "updating": "Updating..." }, + "serverMetrics": { + "resetZoom": "Reset Zoom", + "zoomHint1": "To zoom on the graph hold your shift key then use your scroll wheel.", + "zoomHint2": "Alternatively hold the shift key then click and drag the area you'd like to zoom in on." + }, "serverWizard": { "absoluteServerPath": "Absolute path to your server", "absoluteZipPath": "Absolute path to your server",