mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
227 lines
7.6 KiB
JavaScript
227 lines
7.6 KiB
JavaScript
import fs from "fs";
|
|
import path from "path";
|
|
import { ChartJSNodeCanvas } from "chartjs-node-canvas";
|
|
|
|
// Ensure a directory exists, creating it if necessary
|
|
function ensureDirectoryExists(directory) {
|
|
try {
|
|
fs.mkdirSync(directory, { recursive: true });
|
|
} catch (err) {
|
|
console.error(`Error creating directory ${directory}:`, err.message);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// Write metrics to a JSON file
|
|
export function writeMetricsToFile(metrics) {
|
|
if (!metrics.endTime) {
|
|
console.error("Error: metrics.endTime is not defined. Ensure it is set before calling this function.");
|
|
return;
|
|
}
|
|
|
|
const directory = `./metrics/${metrics.startTime.toISOString().replace(/[:.]/g, "-")}`;
|
|
const filename = path.join(directory, "metrics_report.json");
|
|
|
|
// Ensure the directory exists
|
|
ensureDirectoryExists(directory);
|
|
|
|
const metricsData = {
|
|
summary: {
|
|
roomsCreated: metrics.roomsCreated,
|
|
roomsFailed: metrics.roomsFailed,
|
|
teachersConnected: metrics.teachersConnected,
|
|
teachersFailed: metrics.teachersFailed,
|
|
studentsConnected: metrics.studentsConnected,
|
|
studentsFailed: metrics.studentsFailed,
|
|
},
|
|
messages: {
|
|
messagesSent: metrics.messagesSent,
|
|
messagesReceived: metrics.messagesReceived,
|
|
throughput: metrics.throughput.toFixed(2), // Messages per second
|
|
},
|
|
latencies: {
|
|
totalLatency: metrics.totalLatency,
|
|
averageLatency: metrics.teachersConnected + metrics.studentsConnected
|
|
? (metrics.totalLatency / (metrics.teachersConnected + metrics.studentsConnected)).toFixed(2)
|
|
: null,
|
|
maxLatency: metrics.maxLatency,
|
|
minLatency: metrics.minLatency,
|
|
},
|
|
timing: {
|
|
startTime: metrics.startTime?.toISOString(),
|
|
endTime: metrics.endTime?.toISOString(),
|
|
executionTimeInSeconds: metrics.endTime && metrics.startTime
|
|
? (metrics.endTime - metrics.startTime) / 1000
|
|
: null,
|
|
},
|
|
};
|
|
|
|
// Write metrics to a file
|
|
fs.writeFile(filename, JSON.stringify(metricsData, null, 4), (err) => {
|
|
if (err) {
|
|
console.error(`Error writing metrics to file:`, err.message);
|
|
} else {
|
|
console.log(`Metrics saved to file: ${filename}`);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Generate charts for resource data
|
|
export async function generateGraphs(resourceData, metrics) {
|
|
if (!metrics.endTime) {
|
|
console.error("Error: metrics.endTime is not defined. Ensure it is set before calling this function.");
|
|
return;
|
|
}
|
|
|
|
const directory = `./metrics/${metrics.startTime.toISOString().replace(/[:.]/g, "-")}`;
|
|
ensureDirectoryExists(directory);
|
|
|
|
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width: 800, height: 600 });
|
|
|
|
// Aggregated data for all containers
|
|
const aggregatedTimestamps = [];
|
|
const aggregatedMemoryUsage = [];
|
|
const aggregatedCpuUserPercentage = [];
|
|
const aggregatedCpuSystemPercentage = [];
|
|
|
|
// Generate charts for individual containers
|
|
for (const [roomId, data] of Object.entries(resourceData)) {
|
|
if (!data || !data.length) {
|
|
console.warn(`No data available for room ${roomId}. Skipping individual charts.`);
|
|
continue;
|
|
}
|
|
|
|
// Extract data
|
|
const timestamps = data.map((point) => new Date(point.timestamp).toLocaleTimeString());
|
|
const memoryUsage = data.map((point) => (point.memory.rss || 0) / (1024 * 1024)); // MB
|
|
const cpuUserPercentage = data.map((point) => point.cpu.userPercentage || 0);
|
|
const cpuSystemPercentage = data.map((point) => point.cpu.systemPercentage || 0);
|
|
|
|
// Update aggregated data
|
|
data.forEach((point, index) => {
|
|
if (!aggregatedTimestamps[index]) {
|
|
aggregatedTimestamps[index] = timestamps[index];
|
|
aggregatedMemoryUsage[index] = 0;
|
|
aggregatedCpuUserPercentage[index] = 0;
|
|
aggregatedCpuSystemPercentage[index] = 0;
|
|
}
|
|
aggregatedMemoryUsage[index] += memoryUsage[index];
|
|
aggregatedCpuUserPercentage[index] += cpuUserPercentage[index];
|
|
aggregatedCpuSystemPercentage[index] += cpuSystemPercentage[index];
|
|
});
|
|
|
|
// Memory usage chart
|
|
await saveChart(
|
|
chartJSNodeCanvas,
|
|
{
|
|
labels: timestamps,
|
|
datasets: [
|
|
{
|
|
label: "Memory Usage (MB)",
|
|
data: memoryUsage,
|
|
borderColor: "blue",
|
|
fill: false,
|
|
},
|
|
],
|
|
},
|
|
"Time",
|
|
"Memory Usage (MB)",
|
|
path.join(directory, `memory-usage-room-${roomId}.png`)
|
|
);
|
|
|
|
// CPU usage chart
|
|
await saveChart(
|
|
chartJSNodeCanvas,
|
|
{
|
|
labels: timestamps,
|
|
datasets: [
|
|
{
|
|
label: "CPU User Usage (%)",
|
|
data: cpuUserPercentage,
|
|
borderColor: "red",
|
|
fill: false,
|
|
},
|
|
{
|
|
label: "CPU System Usage (%)",
|
|
data: cpuSystemPercentage,
|
|
borderColor: "orange",
|
|
fill: false,
|
|
},
|
|
],
|
|
},
|
|
"Time",
|
|
"CPU Usage (%)",
|
|
path.join(directory, `cpu-usage-room-${roomId}.png`)
|
|
);
|
|
|
|
console.log(`Charts generated for room ${roomId}`);
|
|
}
|
|
|
|
// Ensure aggregated data is not empty
|
|
if (!aggregatedTimestamps.length) {
|
|
console.error("Error: Aggregated data is empty. Verify container data.");
|
|
return;
|
|
}
|
|
|
|
// Aggregated memory usage chart
|
|
await saveChart(
|
|
chartJSNodeCanvas,
|
|
{
|
|
labels: aggregatedTimestamps,
|
|
datasets: [
|
|
{
|
|
label: "Total Memory Usage (MB)",
|
|
data: aggregatedMemoryUsage,
|
|
borderColor: "blue",
|
|
fill: false,
|
|
},
|
|
],
|
|
},
|
|
"Time",
|
|
"Memory Usage (MB)",
|
|
path.join(directory, "aggregated-memory-usage.png")
|
|
);
|
|
|
|
// Aggregated CPU usage chart
|
|
await saveChart(
|
|
chartJSNodeCanvas,
|
|
{
|
|
labels: aggregatedTimestamps,
|
|
datasets: [
|
|
{
|
|
label: "Total CPU User Usage (%)",
|
|
data: aggregatedCpuUserPercentage,
|
|
borderColor: "red",
|
|
fill: false,
|
|
},
|
|
{
|
|
label: "Total CPU System Usage (%)",
|
|
data: aggregatedCpuSystemPercentage,
|
|
borderColor: "orange",
|
|
fill: false,
|
|
},
|
|
],
|
|
},
|
|
"Time",
|
|
"CPU Usage (%)",
|
|
path.join(directory, "aggregated-cpu-usage.png")
|
|
);
|
|
|
|
console.log("Aggregated charts generated.");
|
|
}
|
|
|
|
// Helper function to save a chart
|
|
async function saveChart(chartJSNodeCanvas, data, xLabel, yLabel, outputFile) {
|
|
const chartConfig = {
|
|
type: "line",
|
|
data,
|
|
options: {
|
|
scales: {
|
|
x: { title: { display: true, text: xLabel } },
|
|
y: { title: { display: true, text: yLabel } },
|
|
},
|
|
},
|
|
};
|
|
const chartBuffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
|
|
fs.writeFileSync(outputFile, chartBuffer);
|
|
}
|