EvalueTonSavoir/test/stressTest/utility/metrics_generator.js
MathieuSevignyLavallee fff5830afd Add README, implementation de l'api Docker sur le quizroom, Fonctionnel
remove docker group

graph generator remake

Docker API implementation
2024-12-07 22:01:55 -05:00

253 lines
No EOL
7.6 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
async function saveMetricsSummary(metrics, baseOutputDir) {
const metricsData = metrics.getSummary();
// Save as JSON
fs.writeFileSync(
path.join(baseOutputDir, 'metrics-summary.json'),
JSON.stringify(metricsData, null, 2)
);
// Save as formatted text
const textSummary = `
Load Test Summary
================
Rooms
-----
Created: ${metricsData.rooms.created}
Failed: ${metricsData.rooms.failed}
Total: ${metricsData.rooms.total}
Users
-----
Connected: ${metricsData.users.connected}
Failed: ${metricsData.users.failed}
Total: ${metricsData.users.total}
Messages
--------
Attempted: ${metricsData.messages.attempted}
Sent: ${metricsData.messages.sent}
Received: ${metricsData.messages.received}
Errors by Category
----------------
${Object.entries(metricsData.errors)
.map(([category, count]) => `${category}: ${count}`)
.join('\n')}
`;
fs.writeFileSync(
path.join(baseOutputDir, 'metrics-summary.txt'),
textSummary.trim()
);
}
// Common chart configurations
const CHART_CONFIG = {
width: 800,
height: 400,
chartStyles: {
memory: {
borderColor: 'blue',
backgroundColor: 'rgba(54, 162, 235, 0.2)'
},
memoryPercent: {
borderColor: 'green',
backgroundColor: 'rgba(75, 192, 192, 0.2)'
},
cpu: {
borderColor: 'red',
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}
}
};
const createBaseChartConfig = (labels, dataset, xLabel, yLabel) => ({
type: 'line',
data: {
labels,
datasets: [dataset]
},
options: {
scales: {
x: { title: { display: true, text: xLabel }},
y: { title: { display: true, text: yLabel }}
},
plugins: {
legend: { display: true, position: 'top' }
}
}
});
function ensureDirectoryExists(directory) {
!fs.existsSync(directory) && fs.mkdirSync(directory, { recursive: true });
}
async function generateMetricsChart(chartJSNodeCanvas, data, style, label, timeLabels, metric, outputPath) {
const dataset = {
label,
data: data.map(m => m[metric] || 0),
...CHART_CONFIG.chartStyles[style],
fill: true,
tension: 0.4
};
const buffer = await chartJSNodeCanvas.renderToBuffer(
createBaseChartConfig(timeLabels, dataset, 'Time', label)
);
return fs.promises.writeFile(outputPath, buffer);
}
async function generateContainerCharts(chartJSNodeCanvas, containerData, outputDir) {
const timeLabels = containerData.metrics.map(m =>
new Date(m.timestamp).toLocaleTimeString()
);
const chartPromises = [
generateMetricsChart(
chartJSNodeCanvas,
containerData.metrics,
'memory',
`${containerData.containerName} Memory (MB)`,
timeLabels,
'memoryUsedMB',
path.join(outputDir, 'memory-usage-mb.png')
),
generateMetricsChart(
chartJSNodeCanvas,
containerData.metrics,
'memoryPercent',
`${containerData.containerName} Memory %`,
timeLabels,
'memoryUsedPercentage',
path.join(outputDir, 'memory-usage-percent.png')
),
generateMetricsChart(
chartJSNodeCanvas,
containerData.metrics,
'cpu',
`${containerData.containerName} CPU %`,
timeLabels,
'cpuUsedPercentage',
path.join(outputDir, 'cpu-usage.png')
)
];
await Promise.all(chartPromises);
}
async function processSummaryMetrics(containers, timeLabels) {
return timeLabels.map((_, timeIndex) => ({
memoryUsedMB: containers.reduce((sum, container) =>
sum + (container.metrics[timeIndex]?.memoryUsedMB || 0), 0),
memoryUsedPercentage: containers.reduce((sum, container) =>
sum + (container.metrics[timeIndex]?.memoryUsedPercentage || 0), 0),
cpuUsedPercentage: containers.reduce((sum, container) =>
sum + (container.metrics[timeIndex]?.cpuUsedPercentage || 0), 0)
}));
}
export default async function generateMetricsReport(allRoomsData, testMetrics) {
try {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const baseOutputDir = `./output/${timestamp}`;
const dirs = [
baseOutputDir,
path.join(baseOutputDir, 'all-containers'),
path.join(baseOutputDir, 'all-rooms')
];
dirs.forEach(ensureDirectoryExists);
if (testMetrics) {
await saveMetricsSummary(testMetrics, baseOutputDir);
}
const chartJSNodeCanvas = new ChartJSNodeCanvas(CHART_CONFIG);
const allContainers = Object.values(allRoomsData).flat();
const roomContainers = allContainers.filter(c =>
c.containerName.startsWith('room_')
);
if (allContainers.length > 0) {
const timeLabels = allContainers[0].metrics.map(m =>
new Date(m.timestamp).toLocaleTimeString()
);
const summedMetrics = await processSummaryMetrics(allContainers, timeLabels);
await generateContainerSummaryCharts(
chartJSNodeCanvas,
summedMetrics,
timeLabels,
path.join(baseOutputDir, 'all-containers')
);
}
if (roomContainers.length > 0) {
const timeLabels = roomContainers[0].metrics.map(m =>
new Date(m.timestamp).toLocaleTimeString()
);
const summedMetrics = await processSummaryMetrics(roomContainers, timeLabels);
await generateContainerSummaryCharts(
chartJSNodeCanvas,
summedMetrics,
timeLabels,
path.join(baseOutputDir, 'all-rooms')
);
}
// Process individual containers
const containerPromises = Object.values(allRoomsData)
.flat()
.filter(container => !container.containerName.startsWith('room_'))
.map(async containerData => {
const containerDir = path.join(baseOutputDir, containerData.containerName);
ensureDirectoryExists(containerDir);
await generateContainerCharts(chartJSNodeCanvas, containerData, containerDir);
});
await Promise.all(containerPromises);
return { outputDir: baseOutputDir };
} catch (error) {
console.error('Error generating metrics report:', error);
throw error;
}
}
async function generateContainerSummaryCharts(chartJSNodeCanvas, metrics, timeLabels, outputDir) {
await Promise.all([
generateMetricsChart(
chartJSNodeCanvas,
metrics,
'memory',
'Total Memory (MB)',
timeLabels,
'memoryUsedMB',
path.join(outputDir, 'total-memory-usage-mb.png')
),
generateMetricsChart(
chartJSNodeCanvas,
metrics,
'memoryPercent',
'Total Memory %',
timeLabels,
'memoryUsedPercentage',
path.join(outputDir, 'total-memory-usage-percent.png')
),
generateMetricsChart(
chartJSNodeCanvas,
metrics,
'cpu',
'Total CPU %',
timeLabels,
'cpuUsedPercentage',
path.join(outputDir, 'total-cpu-usage.png')
)
]);
}