mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
ajout de metrique de sommaire
This commit is contained in:
parent
1e67762b5e
commit
1a7be0ad79
3 changed files with 138 additions and 13 deletions
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
46
test/stressTest/utility/test_metrics.js
Normal file
46
test/stressTest/utility/test_metrics.js
Normal 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])
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue