From de34962360b2ace8d912afb7ab6f37ebfaf64ecc Mon Sep 17 00:00:00 2001 From: mirivlad Date: Tue, 14 Apr 2026 01:21:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=BC=D0=BE=D0=BD=D0=B8=D1=82=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=20=D1=82=D0=B5=D0=BC=D0=BF=D0=B5=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D1=83=D1=80=20(CPU,=20GPU,=20HDD/SSD)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Обновлен скрипт установки агента (добавлены lm-sensors, smartmontools) - Агент теперь собирает температуры: CPU (через psutil), Диски (smartctl), GPU (nvidia-smi) - Бэкенд автоматически определяет единицу измерения °C для метрик temp_* - Добавлен общий график Температуры на страницу сервера --- src/Controllers/AgentController.php | 2 +- templates/servers/detail.twig | 71 ++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/Controllers/AgentController.php b/src/Controllers/AgentController.php index e13cf09..34292a0 100755 --- a/src/Controllers/AgentController.php +++ b/src/Controllers/AgentController.php @@ -50,7 +50,7 @@ echo 'Установка агента мониторинга...' if ! command -v python3 &> /dev/null; then echo 'Установка Python3...' apt-get update - apt-get install -y python3 python3-pip + apt-get install -y python3 python3-pip lm-sensors smartmontools fi # Устанавливаем psutil diff --git a/templates/servers/detail.twig b/templates/servers/detail.twig index e1a0462..f675ba0 100755 --- a/templates/servers/detail.twig +++ b/templates/servers/detail.twig @@ -188,7 +188,26 @@ - + + + {% set has_temps = false %} + {% for m in metrics %}{% if m starts with 'temp_' %}{% set has_temps = true %}{% endif %}{% endfor %} + {% if has_temps %} +
+
+
+
+
Температуры
+
+
+ +
+
+
+
+ {% endif %} + +
{% for metricName, metricData in metrics %} {% if metricName starts with 'disk_used_' and metricName != 'disk_used' %} @@ -834,6 +853,56 @@ document.addEventListener('mousemove', function(e) { {% endif %} {% endfor %} + +// График температур +{% set temp_metrics = [] %} +{% for m in metrics %}{% if m starts with 'temp_' %}{% set temp_metrics = temp_metrics|merge([m]) %}{% endif %}{% endfor %} +{% if temp_metrics %} +(function() { + var ctx = document.getElementById('chart-temperatures'); + if (!ctx) return; + + var labels = []; + {% if metrics[temp_metrics[0]] is defined %} + {% for p in metrics[temp_metrics[0]]|slice(-100) %} + labels.push('{{ p.time_bucket|default(p.created_at)|date("d.m H:i") }}'); + {% endfor %} + {% endif %} + + var datasets = []; + {% for m in temp_metrics %} + var data_{{ m }} = { + label: '{{ m|replace({'temp_': '', '_': ' '})|title }}', + data: [], + fill: false, + tension: 0.1, + pointRadius: 1, + borderWidth: 1 + }; + {% for p in metrics[m]|slice(-100) %} + data_{{ m }}.data.push({{ p.value }}); + {% endfor %} + datasets.push(data_{{ m }}); + {% endfor %} + + new Chart(ctx.getContext('2d'), { + type: 'line', + data: { labels: labels, datasets: datasets }, + options: { + responsive: true, + maintainAspectRatio: false, + interaction: { mode: 'index', intersect: false }, + plugins: { + legend: { display: true, position: 'top' }, + tooltip: { enabled: true, mode: 'index', intersect: false }, + zoom: { zoom: { wheel: { enabled: true }, pinch: { enabled: true }, mode: 'x' }, pan: { enabled: true, mode: 'x' } } + }, + scales: { y: { beginAtZero: false, ticks: { callback: v => v + '°C' } } } + } + }); +})(); +{% endif %} + // Doughnut графики для разделов дисков {% for metricName, metricData in metrics %} {% if metricName starts with 'disk_used_' and metricName != 'disk_used' %}