| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| import {Runnable} from '../../../../src/index.js';
|
| import {BaseCallback} from '../../../../src/utils/callbacks.js';
|
|
|
| class MetricsTrackerCallback extends BaseCallback {
|
| constructor() {
|
| super();
|
|
|
|
|
| this.startTimes = new Map();
|
|
|
|
|
| this.metrics = {};
|
| }
|
|
|
| async onStart(runnable, input, config) {
|
| const key = `${runnable.constructor.name}_${Date.now()}_${Math.random()}`;
|
| this.startTimes.set(key, Date.now());
|
|
|
| const userId = config?.metadata?.userId;
|
|
|
| const runnableName = runnable.constructor.name;
|
| if (!this.metrics[runnableName]) {
|
| this.metrics[runnableName] = {
|
| totalCalls: 0,
|
| totalTime: 0,
|
| users: new Set()
|
| };
|
| }
|
|
|
| this.metrics[runnableName].totalCalls++;
|
| if (userId) {
|
| this.metrics[runnableName].users.add(userId);
|
| }
|
|
|
|
|
| config._metricsKey = key;
|
| }
|
|
|
| async onEnd(runnable, output, config) {
|
| const key = config._metricsKey;
|
| const startTime = this.startTimes.get(key);
|
|
|
| if (startTime) {
|
| const duration = Date.now() - startTime;
|
| const runnableName = runnable.constructor.name;
|
|
|
| if (this.metrics[runnableName]) {
|
| this.metrics[runnableName].totalTime += duration;
|
| }
|
|
|
| this.startTimes.delete(key);
|
| }
|
| }
|
|
|
| async onError(runnable, error, config) {
|
| const key = config._metricsKey;
|
| if (key) {
|
| this.startTimes.delete(key);
|
| }
|
| }
|
|
|
| getReport() {
|
| const report = {};
|
|
|
| for (const [name, data] of Object.entries(this.metrics)) {
|
| report[name] = {
|
| calls: data.totalCalls,
|
| totalTime: data.totalTime,
|
| avgTime: data.totalCalls > 0 ? Math.round(data.totalTime / data.totalCalls) : 0,
|
| users: Array.from(data.users)
|
| };
|
| }
|
|
|
| return report;
|
| }
|
|
|
| printReport() {
|
| console.log('\nπ Metrics Report:');
|
| console.log('β'.repeat(60));
|
|
|
| const report = this.getReport();
|
|
|
| for (const [name, data] of Object.entries(report)) {
|
| console.log(`${name}:`);
|
| console.log(` Calls: ${data.calls}`);
|
| console.log(` Total Time: ${data.totalTime}ms`);
|
| console.log(` Avg Time: ${data.avgTime}ms`);
|
| console.log(` Users: ${data.users.join(', ')}`);
|
| console.log('');
|
| }
|
| }
|
| }
|
|
|
|
|
| class FastRunnable extends Runnable {
|
| async _call(input, config) {
|
| await new Promise(resolve => setTimeout(resolve, 100));
|
| return `Fast: ${input}`;
|
| }
|
| }
|
|
|
| class SlowRunnable extends Runnable {
|
| async _call(input, config) {
|
| await new Promise(resolve => setTimeout(resolve, 500));
|
| return `Slow: ${input}`;
|
| }
|
| }
|
|
|
| class MediumRunnable extends Runnable {
|
| async _call(input, config) {
|
| await new Promise(resolve => setTimeout(resolve, 250));
|
| return `Medium: ${input}`;
|
| }
|
| }
|
|
|
| async function exercise() {
|
| console.log('=== Exercise 14: Metrics Tracker with Metadata ===\n');
|
|
|
| const metrics = new MetricsTrackerCallback();
|
|
|
| const fast = new FastRunnable();
|
| const medium = new MediumRunnable();
|
| const slow = new SlowRunnable();
|
|
|
|
|
| console.log('--- User 1 making calls ---');
|
| await fast.invoke('test1', { callbacks: [metrics], metadata: { userId: "user_123" } });
|
| await medium.invoke('test2', { callbacks: [metrics], metadata: { userId: "user_123" } });
|
| await fast.invoke('test3', { callbacks: [metrics], metadata: { userId: "user_123" } });
|
|
|
|
|
| console.log('--- User 2 making calls ---');
|
| await slow.invoke('test4', { callbacks: [metrics], metadata: { userId: "user_456" } });
|
| await fast.invoke('test5', { callbacks: [metrics], metadata: { userId: "user_456" } });
|
|
|
|
|
| console.log('--- User 3 making calls ---');
|
| await medium.invoke('test6', { callbacks: [metrics], metadata: { userId: "user_789" } });
|
| await slow.invoke('test7', { callbacks: [metrics], metadata: { userId: "user_789" } });
|
| await medium.invoke('test8', { callbacks: [metrics], metadata: { userId: "user_789" } });
|
|
|
| metrics.printReport();
|
|
|
| console.log('\nβ Exercise 2 complete!');
|
| }
|
|
|
|
|
| exercise().catch(console.error);
|
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |