mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add server metrics graph
This commit is contained in:
parent
f3590ded0f
commit
4225de55e8
@ -4,6 +4,7 @@ import time
|
|||||||
import json
|
import json
|
||||||
import pathlib
|
import pathlib
|
||||||
import typing as t
|
import typing as t
|
||||||
|
import datetime
|
||||||
|
|
||||||
from app.classes.controllers.roles_controller import RolesController
|
from app.classes.controllers.roles_controller import RolesController
|
||||||
from app.classes.shared.file_helpers import FileHelpers
|
from app.classes.shared.file_helpers import FileHelpers
|
||||||
@ -102,6 +103,13 @@ class ServersController(metaclass=Singleton):
|
|||||||
server_instance.update_server_instance()
|
server_instance.update_server_instance()
|
||||||
return ret
|
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
|
@staticmethod
|
||||||
def update_unloaded_server(server_obj):
|
def update_unloaded_server(server_obj):
|
||||||
ret = HelperServers.update_server(server_obj)
|
ret = HelperServers.update_server(server_obj)
|
||||||
|
@ -137,6 +137,14 @@ class HelperServerStats:
|
|||||||
)
|
)
|
||||||
return server_data
|
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):
|
def insert_server_stats(self, server_stats):
|
||||||
server_id = server_stats.get("id", 0)
|
server_id = server_stats.get("id", 0)
|
||||||
|
|
||||||
|
@ -524,6 +524,7 @@ class PanelHandler(BaseHandler):
|
|||||||
"files",
|
"files",
|
||||||
"admin_controls",
|
"admin_controls",
|
||||||
"schedules",
|
"schedules",
|
||||||
|
"metrics",
|
||||||
]
|
]
|
||||||
if not self.failed_server:
|
if not self.failed_server:
|
||||||
server = self.controller.servers.get_server_instance_by_id(server_id)
|
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_list"] = []
|
||||||
page_data["backup_path"] = Helpers.wtol_path(server_info["backup_path"])
|
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():
|
def get_banned_players_html():
|
||||||
banned_players = self.controller.servers.get_banned_players(server_id)
|
banned_players = self.controller.servers.get_banned_players(server_id)
|
||||||
if banned_players is None:
|
if banned_players is None:
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
<!-- Bootstrap Toggle -->
|
<!-- Bootstrap Toggle -->
|
||||||
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
|
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
|
||||||
<script defer src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
|
<script defer src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
|
||||||
|
|
||||||
<!-- End Bootstrap Toggle -->
|
<!-- End Bootstrap Toggle -->
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
{% if data['permissions']['Players'] in data['user_permissions'] and data['server_data']['type'] != 'minecraft-bedrock' %}
|
{% if data['permissions']['Players'] in data['user_permissions'] and data['server_data']['type'] != 'minecraft-bedrock' %}
|
||||||
<a class="dropdown-item {% if data['active_link'] == 'admin_controls' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=admin_controls" role="tab" aria-selected="true"><i class="fas fa-users"></i> {{ translate('serverDetails', 'playerControls', data['lang']) }}</a>
|
<a class="dropdown-item {% if data['active_link'] == 'admin_controls' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=admin_controls" role="tab" aria-selected="true"><i class="fas fa-users"></i> {{ translate('serverDetails', 'playerControls', data['lang']) }}</a>
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<a class="dropdown-item {% if data['active_link'] == 'metrics' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=metrics" role="tab" aria-selected="true"><i class="fas fa-users"></i>Metrics</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -49,4 +49,8 @@
|
|||||||
<i class="fas fa-users"></i>{{ translate('serverDetails', 'playerControls', data['lang']) }}</a>
|
<i class="fas fa-users"></i>{{ translate('serverDetails', 'playerControls', data['lang']) }}</a>
|
||||||
</li>
|
</li>
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<li class="nav-item term-nav-item">
|
||||||
|
<a class="nav-link {% if data['active_link'] == 'metrics' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=metrics" role="tab" aria-selected="true">
|
||||||
|
<i class="fas fa-users"></i>Metrics</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
179
app/frontend/templates/panel/server_metrics.html
Normal file
179
app/frontend/templates/panel/server_metrics.html
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
{% extends ../base.html %}
|
||||||
|
|
||||||
|
{% block meta %}
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% block title %}Crafty Controller - {{ translate('serverDetails', 'serverDetails', data['lang']) }}{% end %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="content-wrapper">
|
||||||
|
|
||||||
|
<!-- Page Title Header Starts-->
|
||||||
|
<div class="row page-title-header">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="page-header">
|
||||||
|
<h4 class="page-title">
|
||||||
|
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
|
||||||
|
data['server_stats']['server_id']['server_name'] }}
|
||||||
|
<br />
|
||||||
|
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- Page Title Header Ends-->
|
||||||
|
|
||||||
|
{% include "parts/details_stats.html %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-sm-12 grid-margin">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body pt-0">
|
||||||
|
<span class="d-none d-sm-block">
|
||||||
|
{% include "parts/server_controls_list.html %}
|
||||||
|
</span>
|
||||||
|
<span class="d-block d-sm-none">
|
||||||
|
{% include "parts/m_server_controls_list.html %}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
|
||||||
|
<canvas id="lineChart"></canvas>
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-outline-info" onclick="toggle_players()">PLAYERS</button>
|
||||||
|
<button class="btn btn-outline-primary" onclick="toggle_mem()">MEM</button>
|
||||||
|
<button class="btn btn-outline-warning" onclick="toggle_cpu()">CPU</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
//line
|
||||||
|
var ctxL = document.getElementById("lineChart").getContext('2d');
|
||||||
|
const players = []
|
||||||
|
const dates = []
|
||||||
|
const ram = []
|
||||||
|
const cpu = []
|
||||||
|
{% for item in data['history_stats'] %}
|
||||||
|
players.push("{{ item.online }}");
|
||||||
|
dates.push("{{ item.created }}");
|
||||||
|
ram.push("{{ item.mem_percent }}")
|
||||||
|
cpu.push("{{ item.cpu }}")
|
||||||
|
{% end %}
|
||||||
|
max_nums = [Math.max.apply(this, players), Math.max.apply(this, ram), Math.max.apply(this, cpu)]
|
||||||
|
var hist_chart = new Chart(ctxL, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: dates,
|
||||||
|
datasets: [{
|
||||||
|
label: "Players",
|
||||||
|
data: players,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(136, 98, 224, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "MEM",
|
||||||
|
data: ram,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(33, 150, 243, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "CPU",
|
||||||
|
data: cpu,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(255, 175, 0, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
fill: false,
|
||||||
|
lineTension: 5,
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
ticks: {
|
||||||
|
min: 0,
|
||||||
|
max: Math.max.apply(this, max_nums) + 5
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var mem_hidden = false;
|
||||||
|
var cpu_hidden = false;
|
||||||
|
var players_hidden = false;
|
||||||
|
|
||||||
|
function toggle_mem() {
|
||||||
|
if (!mem_hidden) {
|
||||||
|
hist_chart.data.datasets = hist_chart.data.datasets.filter(function (obj) { return obj.label != "MEM" });
|
||||||
|
mem_hidden = true;
|
||||||
|
// Repaint
|
||||||
|
} else {
|
||||||
|
hist_chart.data.datasets.splice(1, 0, {
|
||||||
|
label: "MEM",
|
||||||
|
data: ram,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(33, 150, 243, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
});
|
||||||
|
mem_hidden = false;
|
||||||
|
}
|
||||||
|
hist_chart.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
function toggle_cpu() {
|
||||||
|
if (!cpu_hidden) {
|
||||||
|
hist_chart.data.datasets = hist_chart.data.datasets.filter(function (obj) { return obj.label != "CPU" });
|
||||||
|
cpu_hidden = true;
|
||||||
|
// Repaint
|
||||||
|
} else {
|
||||||
|
hist_chart.data.datasets.push({
|
||||||
|
label: "CPU",
|
||||||
|
data: cpu,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(255, 175, 0, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
});
|
||||||
|
cpu_hidden = false;
|
||||||
|
}
|
||||||
|
hist_chart.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
function toggle_players() {
|
||||||
|
if (!players_hidden) {
|
||||||
|
hist_chart.data.datasets = hist_chart.data.datasets.filter(function (obj) { return obj.label != "Players" });
|
||||||
|
players_hidden = true;
|
||||||
|
// Repaint
|
||||||
|
} else {
|
||||||
|
hist_chart.data.datasets.splice(0, 0, {
|
||||||
|
label: "Players",
|
||||||
|
data: players,
|
||||||
|
borderColor: [
|
||||||
|
'rgba(136, 98, 224, .5)',
|
||||||
|
],
|
||||||
|
borderWidth: 2
|
||||||
|
});
|
||||||
|
players_hidden = false;
|
||||||
|
}
|
||||||
|
hist_chart.update();
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% end %}
|
Loading…
Reference in New Issue
Block a user