ajout de metrique de sommaire

This commit is contained in:
MathieuSevignyLavallee 2024-12-06 19:31:48 -05:00
parent 1e67762b5e
commit 1a7be0ad79
3 changed files with 138 additions and 13 deletions

View file

@ -2,6 +2,7 @@ import { attemptLoginOrRegister, createRoomContainer } from './utility/apiServic
import { Student } from './class/student.js'; import { Student } from './class/student.js';
import { Teacher } from './class/teacher.js'; import { Teacher } from './class/teacher.js';
import { Watcher } from './class/watcher.js'; import { Watcher } from './class/watcher.js';
import { TestMetrics } from './utility/test_metrics.js';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import generateMetricsReport from './utility/metrics_generator.js'; import generateMetricsReport from './utility/metrics_generator.js';
@ -27,19 +28,32 @@ const config = {
}; };
const rooms = new Map(); const rooms = new Map();
const metrics = new TestMetrics();
async function setupRoom(token, index) { async function setupRoom(token, index) {
try { try {
const room = await createRoomContainer(config.baseUrl, token); const room = await createRoomContainer(config.baseUrl, token);
if (!room?.id) throw new Error('Room creation failed'); if (!room?.id) throw new Error('Room creation failed');
metrics.roomsCreated++;
const teacher = new Teacher(`teacher_${index}`, room.id); const teacher = new Teacher(`teacher_${index}`, room.id);
const watcher = new Watcher(`watcher_${index}`, room.id); const watcher = new Watcher(`watcher_${index}`, room.id);
await Promise.all([ await Promise.all([
teacher.connectToRoom(config.baseUrl) teacher.connectToRoom(config.baseUrl)
.catch(err => console.warn(`Teacher ${index} connection failed:`, err.message)), .then(() => metrics.usersConnected++)
.catch(err => {
metrics.userConnectionsFailed++;
metrics.logError('teacherConnection', err);
console.warn(`Teacher ${index} connection failed:`, err.message);
}),
watcher.connectToRoom(config.baseUrl) watcher.connectToRoom(config.baseUrl)
.catch(err => console.warn(`Watcher ${index} connection failed:`, err.message)) .then(() => metrics.usersConnected++)
.catch(err => {
metrics.userConnectionsFailed++;
metrics.logError('watcherConnection', err);
console.warn(`Watcher ${index} connection failed:`, err.message);
})
]); ]);
const students = Array.from({ length: config.rooms.usersPerRoom - 2 }, const students = Array.from({ length: config.rooms.usersPerRoom - 2 },
@ -48,6 +62,8 @@ async function setupRoom(token, index) {
rooms.set(room.id, { teacher, watcher, students }); rooms.set(room.id, { teacher, watcher, students });
return room.id; return room.id;
} catch (err) { } catch (err) {
metrics.roomsFailed++;
metrics.logError('roomSetup', err);
console.warn(`Room ${index} setup failed:`, err.message); console.warn(`Room ${index} setup failed:`, err.message);
return null; return null;
} }
@ -61,9 +77,15 @@ async function connectParticipants(roomId) {
const batch = participants.slice(i, i + config.rooms.batchSize); const batch = participants.slice(i, i + config.rooms.batchSize);
await Promise.all(batch.map(p => await Promise.all(batch.map(p =>
Promise.race([ Promise.race([
p.connectToRoom(config.baseUrl), p.connectToRoom(config.baseUrl).then(() => {
metrics.usersConnected++;
}),
new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 10000)) new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 10000))
]).catch(err => console.warn(`Connection failed for ${p.username}:`, err.message)) ]).catch(err => {
metrics.userConnectionsFailed++;
metrics.logError('studentConnection', err);
console.warn(`Connection failed for ${p.username}:`, err.message);
})
)); ));
await new Promise(resolve => setTimeout(resolve, config.rooms.batchDelay)); await new Promise(resolve => setTimeout(resolve, config.rooms.batchDelay));
} }
@ -75,23 +97,30 @@ async function simulate() {
const expectedResponses = connectedStudents.length; const expectedResponses = connectedStudents.length;
for (let i = 0; i < config.simulation.maxMessages; i++) { for (let i = 0; i < config.simulation.maxMessages; i++) {
metrics.messagesAttempted++;
const initialMessages = teacher.nbrMessageReceived; const initialMessages = teacher.nbrMessageReceived;
teacher.broadcastMessage(`Message ${i + 1} from ${teacher.username}`);
try { try {
teacher.broadcastMessage(`Message ${i + 1} from ${teacher.username}`);
metrics.messagesSent++;
await Promise.race([ await Promise.race([
new Promise(resolve => { new Promise(resolve => {
const checkResponses = setInterval(() => { const checkResponses = setInterval(() => {
const receivedResponses = teacher.nbrMessageReceived - initialMessages; const receivedResponses = teacher.nbrMessageReceived - initialMessages;
if (receivedResponses >= expectedResponses) { if (receivedResponses >= expectedResponses) {
metrics.messagesReceived += receivedResponses;
clearInterval(checkResponses); clearInterval(checkResponses);
resolve(); resolve();
} }
}, 100); }, 100);
}) }),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Response timeout')), config.simulation.responseTimeout)
)
]); ]);
} catch (error) { } catch (error) {
metrics.logError('messaging', error);
console.error(`Error in room ${roomId} message ${i + 1}:`, error); console.error(`Error in room ${roomId} message ${i + 1}:`, error);
} }
@ -99,7 +128,6 @@ async function simulate() {
} }
}); });
// Wait for all simulations to complete
await Promise.all(simulations); await Promise.all(simulations);
console.log('All room simulations completed'); console.log('All room simulations completed');
} }
@ -111,7 +139,7 @@ async function generateReport() {
watcher.roomRessourcesData watcher.roomRessourcesData
]) ])
); );
return generateMetricsReport(data); return generateMetricsReport(data,metrics);
} }
function cleanup() { function cleanup() {
@ -134,20 +162,21 @@ async function main() {
await Promise.all(roomIds.filter(Boolean).map(connectParticipants)); await Promise.all(roomIds.filter(Boolean).map(connectParticipants));
console.log('Retrieving baseline metrics...'); console.log('Retrieving baseline metrics...');
await new Promise(resolve => setTimeout(resolve, 10000)); // Baseline metrics await new Promise(resolve => setTimeout(resolve, 10000));
console.log('Starting simulation across all rooms...'); console.log('Starting simulation across all rooms...');
await simulate(); await simulate();
console.log('Simulation complete. Waiting for system stabilization...'); console.log('Simulation complete. Waiting for system stabilization...');
await new Promise(resolve => setTimeout(resolve, 10000)); // System stabilization await new Promise(resolve => setTimeout(resolve, 10000));
console.log('All simulations finished, generating final report...'); console.log('Generating final report...');
const folderName = await generateReport(); const folderName = await generateReport();
console.log(`Metrics report generated in ${folderName.outputDir}`); console.log(`Metrics report generated in ${folderName.outputDir}`);
console.log('All done!'); console.log('All done!');
} catch (error) { } catch (error) {
metrics.logError('main', error);
console.error('Error:', error.message); console.error('Error:', error.message);
} finally { } finally {
cleanup(); cleanup();

View file

@ -122,10 +122,60 @@ async function generateGlobalGraphs(data, chartJSNodeCanvas, globalMetricsDir) {
]); ]);
} }
export default async function generateMetricsReport(allRoomsData) { 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()
);
}
export default async function generateMetricsReport(allRoomsData, testMetrics) {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const baseOutputDir = `./output/${timestamp}`; const baseOutputDir = `./output/${timestamp}`;
ensureDirectoryExists(baseOutputDir); ensureDirectoryExists(baseOutputDir);
if (testMetrics) {
await saveMetricsSummary(testMetrics, baseOutputDir);
}
const globalMetricsDir = path.join(baseOutputDir, 'global'); const globalMetricsDir = path.join(baseOutputDir, 'global');
ensureDirectoryExists(globalMetricsDir); ensureDirectoryExists(globalMetricsDir);

View file

@ -0,0 +1,46 @@
export class TestMetrics {
constructor() {
this.reset();
}
reset() {
this.roomsCreated = 0;
this.roomsFailed = 0;
this.usersConnected = 0;
this.userConnectionsFailed = 0;
this.messagesAttempted = 0;
this.messagesSent = 0;
this.messagesReceived = 0;
this.errors = new Map();
}
logError(category, error) {
if (!this.errors.has(category)) {
this.errors.set(category, []);
}
this.errors.get(category).push(error);
}
getSummary() {
return {
rooms: {
created: this.roomsCreated,
failed: this.roomsFailed,
total: this.roomsCreated + this.roomsFailed
},
users: {
connected: this.usersConnected,
failed: this.userConnectionsFailed,
total: this.usersConnected + this.userConnectionsFailed
},
messages: {
attempted: this.messagesAttempted,
sent: this.messagesSent,
received: this.messagesReceived
},
errors: Object.fromEntries(
Array.from(this.errors.entries()).map(([k, v]) => [k, v.length])
)
};
}
}