feat: объединить все температурные метрики (temp_*) в один график с разными цветами, вернуть сетевые графики
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
dbd71e3485
commit
ce577c5d51
|
|
@ -123,7 +123,7 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for metricName, metricData in metrics %}
|
{% for metricName, metricData in metrics %}
|
||||||
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" %}
|
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" and not (metricName starts with "temp_") %}
|
||||||
<div class="col-12 mb-4">
|
<div class="col-12 mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
|
@ -160,10 +160,36 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Температуры -->
|
<!-- Графики сетевых интерфейсов -->
|
||||||
{% set has_temps = false %}
|
{% set net_interfaces = [] %}
|
||||||
{% for m in metrics %}{% if m starts with 'temp_' %}{% set has_temps = true %}{% endif %}{% endfor %}
|
{% for metricName in metrics|keys %}
|
||||||
{% if has_temps %}
|
{% if metricName starts with 'net_in_' %}
|
||||||
|
{% set iface = metricName|replace({'net_in_': ''}) %}
|
||||||
|
{% set net_interfaces = net_interfaces|merge([iface]) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for iface in net_interfaces %}
|
||||||
|
{% if metrics['net_in_' ~ iface] is defined and metrics['net_out_' ~ iface] is defined %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h6 class="mb-0"><i class="fas fa-network-wired"></i> Сеть: {{ iface }}</h6>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<canvas id="chart-net-{{ iface }}" width="100%" height="200"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Температуры: один общий график -->
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
@ -171,12 +197,11 @@
|
||||||
<h6 class="mb-0"><i class="fas fa-thermometer-half"></i> Температуры</h6>
|
<h6 class="mb-0"><i class="fas fa-thermometer-half"></i> Температуры</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<canvas id="chart-temperatures" width="100%" height="200"></canvas>
|
<canvas id="chart-temperatures" width="100%" height="300"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Диски: Doughnut графики -->
|
<!-- Диски: Doughnut графики -->
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
|
|
@ -552,7 +577,7 @@ var diskTotalGB = {
|
||||||
|
|
||||||
// Графики метрик
|
// Графики метрик
|
||||||
{% for metricName, metricData in metrics %}
|
{% for metricName, metricData in metrics %}
|
||||||
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" %}
|
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" and not (metricName starts with "temp_") %}
|
||||||
const ctx{{ metricName|replace({'-': '_', '.': '_'}) }} = document.getElementById('chart-{{ metricName }}').getContext('2d');
|
const ctx{{ metricName|replace({'-': '_', '.': '_'}) }} = document.getElementById('chart-{{ metricName }}').getContext('2d');
|
||||||
|
|
||||||
// Подготовка данных для графика
|
// Подготовка данных для графика
|
||||||
|
|
@ -726,7 +751,7 @@ chart{{ metricName|replace({'-': '_', '.': '_'}) }}.canvas.addEventListener('mou
|
||||||
// Глобальный обработчик для скрытия тултипов при уходе курсора за пределы canvas
|
// Глобальный обработчик для скрытия тултипов при уходе курсора за пределы canvas
|
||||||
document.addEventListener('mousemove', function(e) {
|
document.addEventListener('mousemove', function(e) {
|
||||||
{% for metricName, metricData in metrics %}
|
{% for metricName, metricData in metrics %}
|
||||||
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" %}
|
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" and not (metricName starts with "temp_") %}
|
||||||
(function() {
|
(function() {
|
||||||
var canvas = chart{{ metricName|replace({'-': '_', '.': '_'}) }}.canvas;
|
var canvas = chart{{ metricName|replace({'-': '_', '.': '_'}) }}.canvas;
|
||||||
var rect = canvas.getBoundingClientRect();
|
var rect = canvas.getBoundingClientRect();
|
||||||
|
|
@ -748,40 +773,61 @@ document.addEventListener('mousemove', function(e) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// График температур
|
// Графики сетевых интерфейсов (две линии: In зелёная, Out красная)
|
||||||
{% set temp_metrics = [] %}
|
{% set net_interfaces = [] %}
|
||||||
{% for m in metrics %}{% if m starts with 'temp_' %}{% set temp_metrics = temp_metrics|merge([m]) %}{% endif %}{% endfor %}
|
{% for metricName in metrics|keys %}
|
||||||
{% if temp_metrics %}
|
{% if metricName starts with 'net_in_' %}
|
||||||
|
{% set net_interfaces = net_interfaces|merge([metricName|replace({'net_in_': ''})]) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for iface in net_interfaces %}
|
||||||
|
{% if metrics['net_in_' ~ iface] is defined and metrics['net_out_' ~ iface] is defined %}
|
||||||
(function() {
|
(function() {
|
||||||
var ctx = document.getElementById('chart-temperatures');
|
var ctx = document.getElementById('chart-net-{{ iface }}');
|
||||||
if (!ctx) return;
|
if (!ctx) return;
|
||||||
|
|
||||||
var labels = [];
|
var labels = [];
|
||||||
{% if metrics[temp_metrics[0]] is defined %}
|
var inData = [];
|
||||||
{% for p in metrics[temp_metrics[0]]|slice(-100) %}
|
var outData = [];
|
||||||
labels.push('{{ p.time_bucket|default(p.created_at)|date("d.m H:i") }}');
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
var datasets = [];
|
{% for m in metrics['net_in_' ~ iface]|slice(0, 500)|reverse %}
|
||||||
{% for m in temp_metrics %}
|
labels.push('{{ m.created_at|date("d.m H:i") }}');
|
||||||
var data_{{ m }} = {
|
inData.push({{ m.value }});
|
||||||
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 %}
|
{% endfor %}
|
||||||
datasets.push(data_{{ m }});
|
|
||||||
|
{% set outMetrics = metrics['net_out_' ~ iface]|slice(0, 500)|reverse %}
|
||||||
|
{% for m in outMetrics %}
|
||||||
|
outData.push({{ m.value }});
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
new Chart(ctx.getContext('2d'), {
|
new Chart(ctx.getContext('2d'), {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: { labels: labels, datasets: datasets },
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Входящий (In)',
|
||||||
|
data: inData,
|
||||||
|
borderColor: 'rgba(25, 135, 84, 1)',
|
||||||
|
backgroundColor: 'rgba(25, 135, 84, 0.1)',
|
||||||
|
fill: true,
|
||||||
|
tension: 0.1,
|
||||||
|
pointRadius: 0,
|
||||||
|
borderWidth: 1.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Исходящий (Out)',
|
||||||
|
data: outData,
|
||||||
|
borderColor: 'rgba(220, 53, 69, 1)',
|
||||||
|
backgroundColor: 'rgba(220, 53, 69, 0.1)',
|
||||||
|
fill: true,
|
||||||
|
tension: 0.1,
|
||||||
|
pointRadius: 0,
|
||||||
|
borderWidth: 1.5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
options: {
|
options: {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
|
|
@ -789,13 +835,97 @@ document.addEventListener('mousemove', function(e) {
|
||||||
plugins: {
|
plugins: {
|
||||||
legend: { display: true, position: 'top' },
|
legend: { display: true, position: 'top' },
|
||||||
tooltip: { enabled: true, mode: 'index', intersect: false },
|
tooltip: { enabled: true, mode: 'index', intersect: false },
|
||||||
zoom: { zoom: { wheel: { enabled: true }, pinch: { enabled: true }, mode: 'x' }, pan: { enabled: true, mode: 'x' } }
|
zoom: {
|
||||||
|
zoom: { wheel: { enabled: true }, pinch: { enabled: true }, mode: 'x' },
|
||||||
|
pan: { enabled: true, mode: 'x' }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scales: { y: { beginAtZero: false, ticks: { callback: v => v + '°C' } } }
|
scales: {
|
||||||
|
y: { beginAtZero: true, ticks: { callback: function(v) { return v + '%'; } } }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
// График температур — ВСЕ temp_* на одном графике
|
||||||
|
(function() {
|
||||||
|
var ctx = document.getElementById('chart-temperatures');
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
var tempColors = [
|
||||||
|
{ border: 'rgba(255, 99, 132, 1)', bg: 'rgba(255, 99, 132, 0.1)' },
|
||||||
|
{ border: 'rgba(75, 192, 192, 1)', bg: 'rgba(75, 192, 192, 0.1)' },
|
||||||
|
{ border: 'rgba(255, 159, 64, 1)', bg: 'rgba(255, 159, 64, 0.1)' },
|
||||||
|
{ border: 'rgba(255, 205, 86, 1)', bg: 'rgba(255, 205, 86, 0.1)' },
|
||||||
|
{ border: 'rgba(201, 203, 207, 1)', bg: 'rgba(201, 203, 207, 0.1)' },
|
||||||
|
{ border: 'rgba(54, 162, 235, 1)', bg: 'rgba(54, 162, 235, 0.1)' },
|
||||||
|
{ border: 'rgba(153, 102, 255, 1)', bg: 'rgba(153, 102, 255, 0.1)' },
|
||||||
|
{ border: 'rgba(255, 99, 255, 1)', bg: 'rgba(255, 99, 255, 0.1)' },
|
||||||
|
{ border: 'rgba(100, 200, 100, 1)', bg: 'rgba(100, 200, 100, 0.1)' },
|
||||||
|
{ border: 'rgba(200, 150, 50, 1)', bg: 'rgba(200, 150, 50, 0.1)' }
|
||||||
|
];
|
||||||
|
|
||||||
|
var labels = [];
|
||||||
|
var labelsFilled = false;
|
||||||
|
var datasets = [];
|
||||||
|
var colorIdx = 0;
|
||||||
|
|
||||||
|
{% for mn, md in metrics %}
|
||||||
|
{% if mn starts with 'temp_' %}
|
||||||
|
if (!labelsFilled) {
|
||||||
|
{% for p in md|slice(-1000) %}
|
||||||
|
labels.push('{{ p.time_bucket|default(p.created_at)|date("d.m H:i") }}');
|
||||||
|
{% endfor %}
|
||||||
|
labelsFilled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var data = [];
|
||||||
|
{% for p in md|slice(-1000) %}
|
||||||
|
data.push({{ p.value }});
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
var color = tempColors[colorIdx % tempColors.length];
|
||||||
|
colorIdx++;
|
||||||
|
|
||||||
|
datasets.push({
|
||||||
|
label: '{{ mn|replace({'temp_': '', '_': ' '})|title }}',
|
||||||
|
data: data,
|
||||||
|
borderColor: color.border,
|
||||||
|
backgroundColor: color.bg,
|
||||||
|
fill: false,
|
||||||
|
tension: 0.1,
|
||||||
|
pointRadius: 1,
|
||||||
|
borderWidth: 2
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
var chart = 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', labels: { boxWidth: 12, font: { size: 11 } } },
|
||||||
|
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: function(v) { return v + '°C'; } } } }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.chartTemperatures = chart;
|
||||||
|
})();
|
||||||
|
|
||||||
// Doughnut графики для разделов дисков
|
// Doughnut графики для разделов дисков
|
||||||
{% for metricName, metricData in metrics %}
|
{% for metricName, metricData in metrics %}
|
||||||
|
|
@ -842,12 +972,15 @@ document.addEventListener('mousemove', function(e) {
|
||||||
// Сбросить зум на всех графиках
|
// Сбросить зум на всех графиках
|
||||||
function resetAllZoom() {
|
function resetAllZoom() {
|
||||||
{% for metricName, metricData in metrics %}
|
{% for metricName, metricData in metrics %}
|
||||||
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" %}
|
{% if metricName!="top_cpu_proc" and metricName!="top_ram_proc" and metricName!="disk_used" and not (metricName starts with "disk_used_") and not (metricName starts with "disk_total_gb_") and metricName!="ram_total_gb" and not (metricName starts with "net_in_") and not (metricName starts with "net_out_") and metricName!="network_rx" and metricName!="network_tx" and not (metricName starts with "temp_") %}
|
||||||
if (typeof chart{{ metricName|replace({'-': '_', '.': '_'}) }} !== 'undefined') {
|
if (typeof chart{{ metricName|replace({'-': '_', '.': '_'}) }} !== 'undefined') {
|
||||||
chart{{ metricName|replace({'-': '_', '.': '_'}) }}.resetZoom();
|
chart{{ metricName|replace({'-': '_', '.': '_'}) }}.resetZoom();
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
if (typeof window.chartTemperatures !== 'undefined') {
|
||||||
|
window.chartTemperatures.resetZoom();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue