broken! Graph not showing
This commit is contained in:
@@ -215,7 +215,7 @@ public class MonitoringController : Controller
|
|||||||
|
|
||||||
|
|
||||||
// Durchschnittliche Werte Berechnen
|
// Durchschnittliche Werte Berechnen
|
||||||
[HttpGet]
|
[HttpGet("median")]
|
||||||
public async Task<IActionResult> CalculateMedian(string Metric, int HoursToMonitor, int ServerId)
|
public async Task<IActionResult> CalculateMedian(string Metric, int HoursToMonitor, int ServerId)
|
||||||
{
|
{
|
||||||
// Aktuelle Zeit - X Stunden = letzter Wert, der berücksichtigt werden soll
|
// Aktuelle Zeit - X Stunden = letzter Wert, der berücksichtigt werden soll
|
||||||
@@ -230,4 +230,23 @@ public class MonitoringController : Controller
|
|||||||
|
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("cpu-usage")]
|
||||||
|
public async Task<IActionResult> GetCpuUsageData()
|
||||||
|
{
|
||||||
|
var oneDayAgo = DateTime.UtcNow.AddDays(-1);
|
||||||
|
var data = await _context.Metrics
|
||||||
|
.Where(m => m.Timestamp >= oneDayAgo)
|
||||||
|
.OrderBy(m => m.Timestamp)
|
||||||
|
.Select(m => new
|
||||||
|
{
|
||||||
|
// Hier die Formatierung anpassen
|
||||||
|
// 'o' ist der Standard-Formatbezeichner für ISO 8601-Format mit Zeitzone
|
||||||
|
Timestamp = m.Timestamp.ToUniversalTime().ToString("o"), // Wichtig: ToUniversalTime() für Konsistenz
|
||||||
|
CpuUsage = m.CPU_Load
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -166,5 +166,18 @@ public class ServerController : Controller
|
|||||||
return PartialView("_ServerCard", servers);
|
return PartialView("_ServerCard", servers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IActionResult> ServerDetailsPartial()
|
||||||
|
{
|
||||||
|
var servers = _context.Servers.ToList();
|
||||||
|
|
||||||
|
foreach (var server in servers)
|
||||||
|
{
|
||||||
|
server.IsOnline = (DateTime.UtcNow - server.LastSeen).TotalSeconds <= 120;
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PartialView("_ServerDetails", servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,6 @@
|
|||||||
|
|
||||||
// Initial laden und dann alle 30 Sekunden
|
// Initial laden und dann alle 30 Sekunden
|
||||||
loadServerStats();
|
loadServerStats();
|
||||||
setInterval(loadServerCards, 30000);
|
setInterval(loadServerStats, 30000);
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
@@ -53,8 +53,8 @@
|
|||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<h6><i class="bi bi-graph-up me-1"></i>CPU Last</h6>
|
<h6><i class="bi bi-graph-up me-1"></i>CPU Last</h6>
|
||||||
<div class="bg-light border rounded p-4 text-center text-muted" style="height: 250px;">
|
<div class="bg-light border rounded p-4 text-center text-muted" style="height: 250px; width: 100%">
|
||||||
<canvas id="CpuLoadChart"></canvas>
|
<canvas id="cpuUsageChart" style="width: 800px; height: 400px; border: 1px solid red;"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -64,29 +64,11 @@
|
|||||||
<canvas id="RamLoadChart"></canvas>
|
<canvas id="RamLoadChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
|
||||||
<script>
|
<script src="https://cdn.jsdelivr.net/npm/luxon@3.x/build/global/luxon.min.js"></script>
|
||||||
const ctx = document.getElementById('CpuLoadChart');
|
|
||||||
|
|
||||||
new Chart(ctx, {
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.x/dist/chartjs-adapter-luxon.min.js"></script>
|
||||||
type: 'line',
|
|
||||||
data: {
|
<script src="~/js/CpuChart.js"></script>
|
||||||
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
|
||||||
datasets: [{
|
|
||||||
label: 'Auslastung',
|
|
||||||
data: [12, 19, 3, 5, 2, 3],
|
|
||||||
borderWidth: 1
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
Binary file not shown.
Binary file not shown.
118
Watcher/wwwroot/js/CpuChart.js
Normal file
118
Watcher/wwwroot/js/CpuChart.js
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
let cpuChartInstance = null; // This will hold your Chart.js instance globally
|
||||||
|
|
||||||
|
function fetchDataAndRenderChart() {
|
||||||
|
console.log('fetchDataAndRenderChart wird aufgerufen...');
|
||||||
|
fetch('/monitoring/cpu-usage', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
return response.text().then(text => { throw new Error(text || `HTTP error! status: ${response.status}`); });
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Daten erfolgreich geparst:', data);
|
||||||
|
|
||||||
|
// --- Crucial check for empty/invalid data ---
|
||||||
|
if (!data || !Array.isArray(data) || data.length === 0) {
|
||||||
|
console.warn('Keine Datenpunkte vom Server erhalten oder Datenarray ist leer oder nicht im erwarteten Format. Chart wird nicht gezeichnet/aktualisiert.');
|
||||||
|
// If there's an existing chart but no data, destroy it to clear the canvas
|
||||||
|
if (cpuChartInstance) {
|
||||||
|
cpuChartInstance.destroy(); // Destroy the chart instance
|
||||||
|
cpuChartInstance = null; // Reset the reference
|
||||||
|
}
|
||||||
|
return; // Exit the function as there's nothing to plot
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Data preparation ---
|
||||||
|
const timestamps = data.map(item => {
|
||||||
|
// Ensure you're parsing the timestamp string correctly if not ISO 8601 from backend
|
||||||
|
// Example: '2025-07-30 16:19:58' -> luxon.DateTime.fromFormat(item.timestamp, 'yyyy-LL-dd HH:mm:ss')
|
||||||
|
// If backend sends ISO 8601 (e.g., '2025-07-30T16:19:58Z'), Luxon handles it automatically:
|
||||||
|
return item.timestamp; // If already ISO 8601, pass directly
|
||||||
|
});
|
||||||
|
const cpuUsages = data.map(item => parseFloat(item.cpuUsage)); // Always ensure CPU usage is a number
|
||||||
|
|
||||||
|
console.log('Extrahierte Zeitstempel:', timestamps);
|
||||||
|
console.log('Extrahierte CPU-Werte:', cpuUsages);
|
||||||
|
|
||||||
|
const ctx = document.getElementById('cpuUsageChart')?.getContext('2d');
|
||||||
|
if (!ctx) {
|
||||||
|
console.error("Canvas-Element mit ID 'cpuUsageChart' nicht gefunden!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Chart Creation/Update Logic ---
|
||||||
|
if (cpuChartInstance) {
|
||||||
|
// Chart already exists, just update its data and refresh
|
||||||
|
console.log('Bestehender Chart wird aktualisiert...');
|
||||||
|
cpuChartInstance.data.labels = timestamps;
|
||||||
|
cpuChartInstance.data.datasets[0].data = cpuUsages;
|
||||||
|
cpuChartInstance.update(); // Re-render the chart with new data
|
||||||
|
} else {
|
||||||
|
// No chart exists yet, create a new one
|
||||||
|
console.log('Neuer Chart wird erstellt...');
|
||||||
|
cpuChartInstance = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: timestamps,
|
||||||
|
datasets: [{
|
||||||
|
label: 'CPU Auslastung (%)',
|
||||||
|
data: cpuUsages,
|
||||||
|
borderColor: 'rgb(75, 192, 192)',
|
||||||
|
tension: 0.1,
|
||||||
|
fill: false
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'time',
|
||||||
|
time: {
|
||||||
|
unit: 'minute', // Or 'hour', 'day'
|
||||||
|
tooltipFormat: 'HH:mm:ss',
|
||||||
|
displayFormats: {
|
||||||
|
minute: 'HH:mm'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Zeit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'CPU Auslastung (%)'
|
||||||
|
},
|
||||||
|
max: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function (context) {
|
||||||
|
return context.dataset.label + ': ' + context.parsed.y + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Catch-Block ausgelöst:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial call when the DOM is ready
|
||||||
|
document.addEventListener('DOMContentLoaded', fetchDataAndRenderChart);
|
||||||
|
|
||||||
|
// Subsequent calls for real-time updates
|
||||||
|
setInterval(fetchDataAndRenderChart, 20000); // Update every 20 seconds
|
@@ -1,35 +0,0 @@
|
|||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const canvases = document.querySelectorAll("canvas[id^='uptimeChart-']");
|
|
||||||
|
|
||||||
canvases.forEach(canvas => {
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
// Hier kannst du Daten dynamisch anpassen, ggf. mit data-* Attributen
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'line',
|
|
||||||
data: {
|
|
||||||
labels: ['0h', '6h', '12h', '18h', '24h'],
|
|
||||||
datasets: [{
|
|
||||||
label: 'Uptime (%)',
|
|
||||||
data: [100, 90, 80, 100, 95], // Beispielwerte
|
|
||||||
borderColor: '#3b82f6',
|
|
||||||
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
|
||||||
tension: 0.3,
|
|
||||||
fill: true,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
plugins: {
|
|
||||||
legend: { display: false }
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
max: 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,4 +0,0 @@
|
|||||||
// Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
|
||||||
// for details on configuring this project to bundle and minify static web assets.
|
|
||||||
|
|
||||||
// Write your JavaScript code.
|
|
Reference in New Issue
Block a user