mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
253 lines
No EOL
7.6 KiB
JavaScript
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')
|
|
)
|
|
]);
|
|
} |