mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-19 09:45:28 +01:00
Merge branch 'feature/pretzel-metrics-graph' into 'dev'
Add metrics graph See merge request crafty-controller/crafty-4!436
This commit is contained in:
commit
9876f37c85
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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"))
|
||||
|
@ -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:
|
||||
|
@ -40,6 +40,16 @@
|
||||
<!-- Bootstrap Toggle -->
|
||||
<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 src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"
|
||||
integrity="sha512-ElRFoEQdI5Ht6kZvyzXhYG9NqjtkmlkfYk0wr6wHxU9JEHakS7UJZNeml5ALk+8IKlU6jDgMabC3vkumRokgJA=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"
|
||||
integrity="sha512-UXumZrZNiOwnTcZSHLOfcTs0aos2MzBWHXOHOuB0J/R44QB0dwY5JgfbvljXcklVf65Gc4El6RjZ+lnwd2az2g=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.1/chartjs-plugin-zoom.min.js"
|
||||
integrity="sha512-klQv6lz2YR+MecyFYMFRuU2eAl8IPRo6zHnsc9n142TJuJHS8CG0ix4Oq9na9ceeg1u5EkBfZsFcV3U7J51iew=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
|
||||
<!-- End Bootstrap Toggle -->
|
||||
|
||||
</head>
|
||||
|
@ -30,6 +30,7 @@
|
||||
{% 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>
|
||||
{% 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-chart-area'></i>{{ translate('serverDetails', 'metrics', data['lang']) }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -49,4 +49,8 @@
|
||||
<i class="fas fa-users"></i>{{ translate('serverDetails', 'playerControls', data['lang']) }}</a>
|
||||
</li>
|
||||
{% 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-chart-area'></i>{{ translate('serverDetails', 'metrics', data['lang']) }}</a>
|
||||
</li>
|
||||
</ul>
|
225
app/frontend/templates/panel/server_metrics.html
Normal file
225
app/frontend/templates/panel/server_metrics.html
Normal file
@ -0,0 +1,225 @@
|
||||
{% 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>
|
||||
<button style="float: right; visibility: hidden;" class="btn btn-outline-success reset-button"
|
||||
id="reset-button"><i class="fas fa-undo"></i> {{ translate('serverMetrics', 'resetZoom', data['lang'])
|
||||
}}</button>
|
||||
{% if data['user_data']['hints'] %}
|
||||
<span data-html="true" class="hints text-center" title="<i class='fa fa-info-circle'></i> " ,
|
||||
data-content="{{
|
||||
translate('serverMetrics', 'zoomHint1' , data['lang'])}} <br> <br> {{ translate('serverMetrics', 'zoomHint2', data['lang'])}}" , data-placement="top"></span>
|
||||
{% end %}
|
||||
<div class="chart-wrapper">
|
||||
<canvas id="lineChart"></canvas>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<style>
|
||||
.chart-wrapper {
|
||||
height: 65vh;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
color: white !important;
|
||||
;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var zoomed = false;
|
||||
//line
|
||||
var ctxL = document.getElementById("lineChart").getContext('2d');
|
||||
const players = []
|
||||
const dates = []
|
||||
const ram = []
|
||||
const cpu = []
|
||||
{% for item in data['history_stats'] %}
|
||||
{% if 'minecraft-java' in data['server_stats']['server_type'] %}
|
||||
players.push("{{ item.online }}");
|
||||
{% end %}
|
||||
dates.push("{{ item.created.strftime('%Y/%m/%d, %H:%M:%S') }}");
|
||||
ram.push("{{ item.mem_percent }}")
|
||||
cpu.push("{{ item.cpu }}")
|
||||
{% end %}
|
||||
var hist_chart = new Chart(ctxL, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: dates,
|
||||
datasets: [{
|
||||
label: "Players",
|
||||
data: players,
|
||||
borderColor: [
|
||||
'rgba(136, 98, 224, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
{
|
||||
label: "MEM",
|
||||
data: ram,
|
||||
borderColor: [
|
||||
'rgba(33, 150, 243, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
{
|
||||
label: "CPU",
|
||||
data: cpu,
|
||||
borderColor: [
|
||||
'rgba(255, 175, 0, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
zoom: {
|
||||
zoom: {
|
||||
onZoom({ hist_chart }) {
|
||||
console.log("zooming");
|
||||
document.getElementById("reset-button").style.visibility = "visible";
|
||||
zoomed = true;
|
||||
},
|
||||
wheel: {
|
||||
enabled: true,
|
||||
modifierKey: 'shift',
|
||||
},
|
||||
drag: {
|
||||
enabled: true,
|
||||
modifierKey: "shift"
|
||||
},
|
||||
pinch: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x',
|
||||
},
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: "x",
|
||||
threshhold: 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
fill: false,
|
||||
lineTension: 5,
|
||||
responsive: true,
|
||||
scales: {
|
||||
y: {
|
||||
min: 0,
|
||||
},
|
||||
x: {
|
||||
position: 'right',
|
||||
min: dates.length - 200,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$(window).ready(function () {
|
||||
$('body').click(function () {
|
||||
$('.hints').popover("hide");
|
||||
});
|
||||
});
|
||||
$(document).ready(function () {
|
||||
if ($(window).width() > 1000) {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
$('.hints').popover("show");
|
||||
}
|
||||
webSocket.on('update_server_details', function (data) {
|
||||
dates.push(data.created);
|
||||
players.push(data.online);
|
||||
cpu.push(data.cpu)
|
||||
ram.push(data.mem_percent)
|
||||
data = {
|
||||
labels: dates,
|
||||
datasets: [{
|
||||
label: "Players",
|
||||
data: players,
|
||||
borderColor: [
|
||||
'rgba(136, 98, 224, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
{
|
||||
label: "MEM",
|
||||
data: ram,
|
||||
borderColor: [
|
||||
'rgba(33, 150, 243, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
{
|
||||
label: "CPU",
|
||||
data: cpu,
|
||||
borderColor: [
|
||||
'rgba(255, 175, 0, .5)',
|
||||
],
|
||||
borderWidth: 2,
|
||||
lineTension: 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
if (!zoomed) {
|
||||
hist_chart.options.scales.x.min = dates.length - 200;
|
||||
}
|
||||
hist_chart.update(data)
|
||||
});
|
||||
|
||||
$(".reset-button").click(function () {
|
||||
console.log("resetting zoom");
|
||||
zoomed = false;
|
||||
hist_chart.resetZoom();
|
||||
document.getElementById("reset-button").style.visibility = "hidden";
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% end %}
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user