@buenojs/bueno 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/.env.example +109 -0
  2. package/.github/workflows/ci.yml +31 -0
  3. package/LICENSE +21 -0
  4. package/README.md +892 -0
  5. package/architecture.md +652 -0
  6. package/bun.lock +70 -0
  7. package/dist/cli/index.js +3233 -0
  8. package/dist/index.js +9014 -0
  9. package/package.json +77 -0
  10. package/src/cache/index.ts +795 -0
  11. package/src/cli/ARCHITECTURE.md +837 -0
  12. package/src/cli/bin.ts +10 -0
  13. package/src/cli/commands/build.ts +425 -0
  14. package/src/cli/commands/dev.ts +248 -0
  15. package/src/cli/commands/generate.ts +541 -0
  16. package/src/cli/commands/help.ts +55 -0
  17. package/src/cli/commands/index.ts +112 -0
  18. package/src/cli/commands/migration.ts +355 -0
  19. package/src/cli/commands/new.ts +804 -0
  20. package/src/cli/commands/start.ts +208 -0
  21. package/src/cli/core/args.ts +283 -0
  22. package/src/cli/core/console.ts +349 -0
  23. package/src/cli/core/index.ts +60 -0
  24. package/src/cli/core/prompt.ts +424 -0
  25. package/src/cli/core/spinner.ts +265 -0
  26. package/src/cli/index.ts +135 -0
  27. package/src/cli/templates/deploy.ts +295 -0
  28. package/src/cli/templates/docker.ts +307 -0
  29. package/src/cli/templates/index.ts +24 -0
  30. package/src/cli/utils/fs.ts +428 -0
  31. package/src/cli/utils/index.ts +8 -0
  32. package/src/cli/utils/strings.ts +197 -0
  33. package/src/config/env.ts +408 -0
  34. package/src/config/index.ts +506 -0
  35. package/src/config/loader.ts +329 -0
  36. package/src/config/merge.ts +285 -0
  37. package/src/config/types.ts +320 -0
  38. package/src/config/validation.ts +441 -0
  39. package/src/container/forward-ref.ts +143 -0
  40. package/src/container/index.ts +386 -0
  41. package/src/context/index.ts +360 -0
  42. package/src/database/index.ts +1142 -0
  43. package/src/database/migrations/index.ts +371 -0
  44. package/src/database/schema/index.ts +619 -0
  45. package/src/frontend/api-routes.ts +640 -0
  46. package/src/frontend/bundler.ts +643 -0
  47. package/src/frontend/console-client.ts +419 -0
  48. package/src/frontend/console-stream.ts +587 -0
  49. package/src/frontend/dev-server.ts +846 -0
  50. package/src/frontend/file-router.ts +611 -0
  51. package/src/frontend/frameworks/index.ts +106 -0
  52. package/src/frontend/frameworks/react.ts +85 -0
  53. package/src/frontend/frameworks/solid.ts +104 -0
  54. package/src/frontend/frameworks/svelte.ts +110 -0
  55. package/src/frontend/frameworks/vue.ts +92 -0
  56. package/src/frontend/hmr-client.ts +663 -0
  57. package/src/frontend/hmr.ts +728 -0
  58. package/src/frontend/index.ts +342 -0
  59. package/src/frontend/islands.ts +552 -0
  60. package/src/frontend/isr.ts +555 -0
  61. package/src/frontend/layout.ts +475 -0
  62. package/src/frontend/ssr/react.ts +446 -0
  63. package/src/frontend/ssr/solid.ts +523 -0
  64. package/src/frontend/ssr/svelte.ts +546 -0
  65. package/src/frontend/ssr/vue.ts +504 -0
  66. package/src/frontend/ssr.ts +699 -0
  67. package/src/frontend/types.ts +2274 -0
  68. package/src/health/index.ts +604 -0
  69. package/src/index.ts +410 -0
  70. package/src/lock/index.ts +587 -0
  71. package/src/logger/index.ts +444 -0
  72. package/src/logger/transports/index.ts +969 -0
  73. package/src/metrics/index.ts +494 -0
  74. package/src/middleware/built-in.ts +360 -0
  75. package/src/middleware/index.ts +94 -0
  76. package/src/modules/filters.ts +458 -0
  77. package/src/modules/guards.ts +405 -0
  78. package/src/modules/index.ts +1256 -0
  79. package/src/modules/interceptors.ts +574 -0
  80. package/src/modules/lazy.ts +418 -0
  81. package/src/modules/lifecycle.ts +478 -0
  82. package/src/modules/metadata.ts +90 -0
  83. package/src/modules/pipes.ts +626 -0
  84. package/src/router/index.ts +339 -0
  85. package/src/router/linear.ts +371 -0
  86. package/src/router/regex.ts +292 -0
  87. package/src/router/tree.ts +562 -0
  88. package/src/rpc/index.ts +1263 -0
  89. package/src/security/index.ts +436 -0
  90. package/src/ssg/index.ts +631 -0
  91. package/src/storage/index.ts +456 -0
  92. package/src/telemetry/index.ts +1097 -0
  93. package/src/testing/index.ts +1586 -0
  94. package/src/types/index.ts +236 -0
  95. package/src/types/optional-deps.d.ts +219 -0
  96. package/src/validation/index.ts +276 -0
  97. package/src/websocket/index.ts +1004 -0
  98. package/tests/integration/cli.test.ts +1016 -0
  99. package/tests/integration/fullstack.test.ts +234 -0
  100. package/tests/unit/cache.test.ts +174 -0
  101. package/tests/unit/cli-commands.test.ts +892 -0
  102. package/tests/unit/cli.test.ts +1258 -0
  103. package/tests/unit/container.test.ts +279 -0
  104. package/tests/unit/context.test.ts +221 -0
  105. package/tests/unit/database.test.ts +183 -0
  106. package/tests/unit/linear-router.test.ts +280 -0
  107. package/tests/unit/lock.test.ts +336 -0
  108. package/tests/unit/middleware.test.ts +184 -0
  109. package/tests/unit/modules.test.ts +142 -0
  110. package/tests/unit/pubsub.test.ts +257 -0
  111. package/tests/unit/regex-router.test.ts +265 -0
  112. package/tests/unit/router.test.ts +373 -0
  113. package/tests/unit/rpc.test.ts +1248 -0
  114. package/tests/unit/security.test.ts +174 -0
  115. package/tests/unit/telemetry.test.ts +371 -0
  116. package/tests/unit/test-cache.test.ts +110 -0
  117. package/tests/unit/test-database.test.ts +282 -0
  118. package/tests/unit/tree-router.test.ts +325 -0
  119. package/tests/unit/validation.test.ts +794 -0
  120. package/tsconfig.json +27 -0
@@ -0,0 +1,494 @@
1
+ /**
2
+ * Runtime Metrics Module
3
+ *
4
+ * Provides runtime metrics collection for memory, CPU usage, and other statistics.
5
+ * Part of Layer 7 (Testing & Observability) implementation.
6
+ */
7
+
8
+ // ============= Types =============
9
+
10
+ /**
11
+ * Runtime metrics snapshot
12
+ */
13
+ export interface RuntimeMetrics {
14
+ // Memory
15
+ /** Heap memory used in bytes */
16
+ memoryHeapUsed: number;
17
+ /** Total heap memory in bytes */
18
+ memoryHeapTotal: number;
19
+ /** External memory (C++ objects bound to JS) in bytes */
20
+ memoryExternal: number;
21
+ /** Resident Set Size in bytes */
22
+ memoryRss: number;
23
+
24
+ // CPU
25
+ /** User CPU time in microseconds */
26
+ cpuUser: number;
27
+ /** System CPU time in microseconds */
28
+ cpuSystem: number;
29
+
30
+ // Runtime
31
+ /** Process uptime in seconds */
32
+ uptime: number;
33
+ /** Event loop lag in milliseconds */
34
+ eventLoopLag: number;
35
+
36
+ // Timestamp
37
+ /** ISO 8601 timestamp */
38
+ timestamp: string;
39
+ }
40
+
41
+ /**
42
+ * Human-readable metrics summary
43
+ */
44
+ export interface MetricsSummary {
45
+ memoryHeapUsed: string;
46
+ memoryHeapTotal: string;
47
+ memoryExternal: string;
48
+ memoryRss: string;
49
+ cpuUser: string;
50
+ cpuSystem: string;
51
+ uptime: string;
52
+ eventLoopLag: string;
53
+ timestamp: string;
54
+ }
55
+
56
+ /**
57
+ * Options for MetricsCollector
58
+ */
59
+ export interface MetricsCollectorOptions {
60
+ /** Maximum number of historical snapshots to keep (default: 100) */
61
+ maxHistorySize?: number;
62
+ /** Include event loop lag measurement (default: true) */
63
+ measureEventLoopLag?: boolean;
64
+ }
65
+
66
+ /**
67
+ * Averaged metrics over time
68
+ */
69
+ export interface AveragedMetrics {
70
+ avgMemoryHeapUsed: number;
71
+ avgMemoryHeapTotal: number;
72
+ avgMemoryExternal: number;
73
+ avgMemoryRss: number;
74
+ avgCpuUser: number;
75
+ avgCpuSystem: number;
76
+ avgEventLoopLag: number;
77
+ minMemoryHeapUsed: number;
78
+ maxMemoryHeapUsed: number;
79
+ sampleCount: number;
80
+ timeRange: {
81
+ start: string;
82
+ end: string;
83
+ };
84
+ }
85
+
86
+ // ============= Helper Functions =============
87
+
88
+ /**
89
+ * Format bytes to human-readable string
90
+ */
91
+ export function formatBytes(bytes: number): string {
92
+ if (bytes === 0) return "0 B";
93
+
94
+ const units = ["B", "KB", "MB", "GB", "TB"];
95
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
96
+ const value = bytes / Math.pow(1024, i);
97
+
98
+ // Use appropriate decimal places
99
+ if (i === 0) return `${value} ${units[i]}`;
100
+ if (value >= 100) return `${value.toFixed(1)} ${units[i]}`;
101
+ return `${value.toFixed(2)} ${units[i]}`;
102
+ }
103
+
104
+ /**
105
+ * Format microseconds to human-readable string
106
+ */
107
+ export function formatMicroseconds(microseconds: number): string {
108
+ if (microseconds < 1000) {
109
+ return `${microseconds.toFixed(0)} µs`;
110
+ }
111
+ const ms = microseconds / 1000;
112
+ if (ms < 1000) {
113
+ return `${ms.toFixed(2)} ms`;
114
+ }
115
+ const seconds = ms / 1000;
116
+ return `${seconds.toFixed(2)} s`;
117
+ }
118
+
119
+ /**
120
+ * Format seconds to human-readable uptime string
121
+ */
122
+ export function formatUptime(seconds: number): string {
123
+ const days = Math.floor(seconds / 86400);
124
+ const hours = Math.floor((seconds % 86400) / 3600);
125
+ const minutes = Math.floor((seconds % 3600) / 60);
126
+ const secs = Math.floor(seconds % 60);
127
+
128
+ const parts: string[] = [];
129
+ if (days > 0) parts.push(`${days}d`);
130
+ if (hours > 0) parts.push(`${hours}h`);
131
+ if (minutes > 0) parts.push(`${minutes}m`);
132
+ if (secs > 0 || parts.length === 0) parts.push(`${secs}s`);
133
+
134
+ return parts.join(" ");
135
+ }
136
+
137
+ /**
138
+ * Get human-readable metrics summary
139
+ */
140
+ export function getMetricsSummary(metrics: RuntimeMetrics): MetricsSummary {
141
+ return {
142
+ memoryHeapUsed: formatBytes(metrics.memoryHeapUsed),
143
+ memoryHeapTotal: formatBytes(metrics.memoryHeapTotal),
144
+ memoryExternal: formatBytes(metrics.memoryExternal),
145
+ memoryRss: formatBytes(metrics.memoryRss),
146
+ cpuUser: formatMicroseconds(metrics.cpuUser),
147
+ cpuSystem: formatMicroseconds(metrics.cpuSystem),
148
+ uptime: formatUptime(metrics.uptime),
149
+ eventLoopLag: `${metrics.eventLoopLag.toFixed(2)} ms`,
150
+ timestamp: metrics.timestamp,
151
+ };
152
+ }
153
+
154
+ // ============= Event Loop Lag Measurement =============
155
+
156
+ /**
157
+ * Measure event loop lag using deferred execution timing
158
+ * @returns Promise resolving to lag in milliseconds
159
+ */
160
+ export async function measureEventLoopLag(): Promise<number> {
161
+ const start = Bun.nanoseconds();
162
+ await new Promise((resolve) => setTimeout(resolve, 0));
163
+ const end = Bun.nanoseconds();
164
+ return (end - start) / 1e6; // Convert nanoseconds to milliseconds
165
+ }
166
+
167
+ /**
168
+ * Measure event loop lag multiple times and return average
169
+ */
170
+ export async function measureEventLoopLagAverage(
171
+ samples: number = 5,
172
+ ): Promise<number> {
173
+ const measurements: number[] = [];
174
+
175
+ for (let i = 0; i < samples; i++) {
176
+ measurements.push(await measureEventLoopLag());
177
+ }
178
+
179
+ return measurements.reduce((a, b) => a + b, 0) / measurements.length;
180
+ }
181
+
182
+ // ============= MetricsCollector Class =============
183
+
184
+ /**
185
+ * Collects and manages runtime metrics
186
+ */
187
+ export class MetricsCollector {
188
+ private history: RuntimeMetrics[] = [];
189
+ private maxHistorySize: number;
190
+ private measureEventLoopLagEnabled: boolean;
191
+ private periodicTimer: Timer | null = null;
192
+ private lastCpuUsage: NodeJS.CpuUsage | undefined = undefined;
193
+
194
+ constructor(options: MetricsCollectorOptions = {}) {
195
+ this.maxHistorySize = options.maxHistorySize ?? 100;
196
+ this.measureEventLoopLagEnabled = options.measureEventLoopLag ?? true;
197
+ }
198
+
199
+ /**
200
+ * Collect current runtime metrics
201
+ */
202
+ async collect(): Promise<RuntimeMetrics> {
203
+ // Get memory metrics
204
+ const memUsage = process.memoryUsage();
205
+
206
+ // Get CPU metrics
207
+ const cpuUsage = process.cpuUsage(this.lastCpuUsage);
208
+ this.lastCpuUsage = process.cpuUsage();
209
+
210
+ // Get uptime
211
+ const uptime = process.uptime();
212
+
213
+ // Measure event loop lag if enabled
214
+ let eventLoopLag = 0;
215
+ if (this.measureEventLoopLagEnabled) {
216
+ eventLoopLag = await measureEventLoopLag();
217
+ }
218
+
219
+ const metrics: RuntimeMetrics = {
220
+ memoryHeapUsed: memUsage.heapUsed,
221
+ memoryHeapTotal: memUsage.heapTotal,
222
+ memoryExternal: memUsage.external,
223
+ memoryRss: memUsage.rss,
224
+ cpuUser: cpuUsage.user,
225
+ cpuSystem: cpuUsage.system,
226
+ uptime,
227
+ eventLoopLag,
228
+ timestamp: new Date().toISOString(),
229
+ };
230
+
231
+ // Add to history
232
+ this.history.push(metrics);
233
+
234
+ // Trim history if needed
235
+ if (this.history.length > this.maxHistorySize) {
236
+ this.history.shift();
237
+ }
238
+
239
+ return metrics;
240
+ }
241
+
242
+ /**
243
+ * Start collecting metrics at regular intervals
244
+ * @param intervalMs Interval in milliseconds (default: 5000)
245
+ */
246
+ startPeriodicCollection(intervalMs: number = 5000): void {
247
+ if (this.periodicTimer !== null) {
248
+ throw new Error("Periodic collection is already running");
249
+ }
250
+
251
+ // Collect immediately
252
+ this.collect().catch(() => {
253
+ // Ignore errors in initial collection
254
+ });
255
+
256
+ // Set up periodic collection
257
+ this.periodicTimer = setInterval(() => {
258
+ this.collect().catch(() => {
259
+ // Ignore errors in periodic collection
260
+ });
261
+ }, intervalMs);
262
+ }
263
+
264
+ /**
265
+ * Stop periodic collection
266
+ */
267
+ stopPeriodicCollection(): void {
268
+ if (this.periodicTimer !== null) {
269
+ clearInterval(this.periodicTimer);
270
+ this.periodicTimer = null;
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Check if periodic collection is running
276
+ */
277
+ isCollecting(): boolean {
278
+ return this.periodicTimer !== null;
279
+ }
280
+
281
+ /**
282
+ * Get historical metrics snapshots
283
+ */
284
+ getHistory(): RuntimeMetrics[] {
285
+ return [...this.history];
286
+ }
287
+
288
+ /**
289
+ * Get the most recent metrics
290
+ */
291
+ getLatest(): RuntimeMetrics | null {
292
+ return this.history.length > 0
293
+ ? { ...this.history[this.history.length - 1] }
294
+ : null;
295
+ }
296
+
297
+ /**
298
+ * Get averaged metrics over time
299
+ */
300
+ getAverage(): AveragedMetrics | null {
301
+ if (this.history.length === 0) {
302
+ return null;
303
+ }
304
+
305
+ const count = this.history.length;
306
+ let sumHeapUsed = 0;
307
+ let sumHeapTotal = 0;
308
+ let sumExternal = 0;
309
+ let sumRss = 0;
310
+ let sumCpuUser = 0;
311
+ let sumCpuSystem = 0;
312
+ let sumEventLoopLag = 0;
313
+ let minHeapUsed = Infinity;
314
+ let maxHeapUsed = 0;
315
+
316
+ for (const m of this.history) {
317
+ sumHeapUsed += m.memoryHeapUsed;
318
+ sumHeapTotal += m.memoryHeapTotal;
319
+ sumExternal += m.memoryExternal;
320
+ sumRss += m.memoryRss;
321
+ sumCpuUser += m.cpuUser;
322
+ sumCpuSystem += m.cpuSystem;
323
+ sumEventLoopLag += m.eventLoopLag;
324
+ minHeapUsed = Math.min(minHeapUsed, m.memoryHeapUsed);
325
+ maxHeapUsed = Math.max(maxHeapUsed, m.memoryHeapUsed);
326
+ }
327
+
328
+ return {
329
+ avgMemoryHeapUsed: Math.round(sumHeapUsed / count),
330
+ avgMemoryHeapTotal: Math.round(sumHeapTotal / count),
331
+ avgMemoryExternal: Math.round(sumExternal / count),
332
+ avgMemoryRss: Math.round(sumRss / count),
333
+ avgCpuUser: Math.round(sumCpuUser / count),
334
+ avgCpuSystem: Math.round(sumCpuSystem / count),
335
+ avgEventLoopLag: Math.round((sumEventLoopLag / count) * 100) / 100,
336
+ minMemoryHeapUsed: minHeapUsed === Infinity ? 0 : minHeapUsed,
337
+ maxMemoryHeapUsed: maxHeapUsed,
338
+ sampleCount: count,
339
+ timeRange: {
340
+ start: this.history[0].timestamp,
341
+ end: this.history[count - 1].timestamp,
342
+ },
343
+ };
344
+ }
345
+
346
+ /**
347
+ * Clear history
348
+ */
349
+ reset(): void {
350
+ this.history = [];
351
+ this.lastCpuUsage = undefined;
352
+ }
353
+
354
+ /**
355
+ * Get the number of samples in history
356
+ */
357
+ getHistorySize(): number {
358
+ return this.history.length;
359
+ }
360
+ }
361
+
362
+ // ============= Prometheus Format Export =============
363
+
364
+ /**
365
+ * Export metrics in Prometheus text format
366
+ * @param metrics Runtime metrics to export
367
+ * @returns Prometheus formatted string
368
+ */
369
+ export function toPrometheusFormat(metrics: RuntimeMetrics): string {
370
+ const timestamp = Date.now();
371
+ const lines: string[] = [];
372
+
373
+ // Memory metrics
374
+ lines.push("# HELP process_memory_heap_used_bytes Heap memory used in bytes");
375
+ lines.push("# TYPE process_memory_heap_used_bytes gauge");
376
+ lines.push(
377
+ `process_memory_heap_used_bytes ${metrics.memoryHeapUsed} ${timestamp}`,
378
+ );
379
+
380
+ lines.push("# HELP process_memory_heap_total_bytes Total heap memory in bytes");
381
+ lines.push("# TYPE process_memory_heap_total_bytes gauge");
382
+ lines.push(
383
+ `process_memory_heap_total_bytes ${metrics.memoryHeapTotal} ${timestamp}`,
384
+ );
385
+
386
+ lines.push("# HELP process_memory_external_bytes External memory in bytes");
387
+ lines.push("# TYPE process_memory_external_bytes gauge");
388
+ lines.push(
389
+ `process_memory_external_bytes ${metrics.memoryExternal} ${timestamp}`,
390
+ );
391
+
392
+ lines.push("# HELP process_memory_rss_bytes Resident Set Size in bytes");
393
+ lines.push("# TYPE process_memory_rss_bytes gauge");
394
+ lines.push(`process_memory_rss_bytes ${metrics.memoryRss} ${timestamp}`);
395
+
396
+ // CPU metrics
397
+ lines.push("# HELP process_cpu_user_seconds_total Total user CPU time");
398
+ lines.push("# TYPE process_cpu_user_seconds_total counter");
399
+ lines.push(
400
+ `process_cpu_user_seconds_total ${(metrics.cpuUser / 1e6).toFixed(6)} ${timestamp}`,
401
+ );
402
+
403
+ lines.push("# HELP process_cpu_system_seconds_total Total system CPU time");
404
+ lines.push("# TYPE process_cpu_system_seconds_total counter");
405
+ lines.push(
406
+ `process_cpu_system_seconds_total ${(metrics.cpuSystem / 1e6).toFixed(6)} ${timestamp}`,
407
+ );
408
+
409
+ // Runtime metrics
410
+ lines.push("# HELP process_uptime_seconds Process uptime in seconds");
411
+ lines.push("# TYPE process_uptime_seconds gauge");
412
+ lines.push(`process_uptime_seconds ${metrics.uptime.toFixed(2)} ${timestamp}`);
413
+
414
+ lines.push("# HELP nodejs_eventloop_lag_ms Event loop lag in milliseconds");
415
+ lines.push("# TYPE nodejs_eventloop_lag_ms gauge");
416
+ lines.push(
417
+ `nodejs_eventloop_lag_ms ${metrics.eventLoopLag.toFixed(2)} ${timestamp}`,
418
+ );
419
+
420
+ return lines.join("\n");
421
+ }
422
+
423
+ /**
424
+ * Export averaged metrics in Prometheus format
425
+ */
426
+ export function averagedMetricsToPrometheus(
427
+ averaged: AveragedMetrics,
428
+ ): string {
429
+ const timestamp = Date.now();
430
+ const lines: string[] = [];
431
+
432
+ lines.push("# HELP process_memory_heap_used_avg_bytes Average heap memory used");
433
+ lines.push("# TYPE process_memory_heap_used_avg_bytes gauge");
434
+ lines.push(
435
+ `process_memory_heap_used_avg_bytes ${averaged.avgMemoryHeapUsed} ${timestamp}`,
436
+ );
437
+
438
+ lines.push("# HELP process_memory_heap_used_min_bytes Minimum heap memory used");
439
+ lines.push("# TYPE process_memory_heap_used_min_bytes gauge");
440
+ lines.push(
441
+ `process_memory_heap_used_min_bytes ${averaged.minMemoryHeapUsed} ${timestamp}`,
442
+ );
443
+
444
+ lines.push("# HELP process_memory_heap_used_max_bytes Maximum heap memory used");
445
+ lines.push("# TYPE process_memory_heap_used_max_bytes gauge");
446
+ lines.push(
447
+ `process_memory_heap_used_max_bytes ${averaged.maxMemoryHeapUsed} ${timestamp}`,
448
+ );
449
+
450
+ lines.push("# HELP process_eventloop_lag_avg_ms Average event loop lag");
451
+ lines.push("# TYPE process_eventloop_lag_avg_ms gauge");
452
+ lines.push(
453
+ `process_eventloop_lag_avg_ms ${averaged.avgEventLoopLag.toFixed(2)} ${timestamp}`,
454
+ );
455
+
456
+ lines.push("# HELP process_metrics_sample_count Number of samples collected");
457
+ lines.push("# TYPE process_metrics_sample_count gauge");
458
+ lines.push(`process_metrics_sample_count ${averaged.sampleCount} ${timestamp}`);
459
+
460
+ return lines.join("\n");
461
+ }
462
+
463
+ // ============= Factory Functions =============
464
+
465
+ /**
466
+ * Create a new metrics collector
467
+ */
468
+ export function createMetricsCollector(
469
+ options?: MetricsCollectorOptions,
470
+ ): MetricsCollector {
471
+ return new MetricsCollector(options);
472
+ }
473
+
474
+ /**
475
+ * Collect metrics once without a collector
476
+ */
477
+ export async function collectMetrics(): Promise<RuntimeMetrics> {
478
+ const memUsage = process.memoryUsage();
479
+ const cpuUsage = process.cpuUsage();
480
+ const uptime = process.uptime();
481
+ const eventLoopLag = await measureEventLoopLag();
482
+
483
+ return {
484
+ memoryHeapUsed: memUsage.heapUsed,
485
+ memoryHeapTotal: memUsage.heapTotal,
486
+ memoryExternal: memUsage.external,
487
+ memoryRss: memUsage.rss,
488
+ cpuUser: cpuUsage.user,
489
+ cpuSystem: cpuUsage.system,
490
+ uptime,
491
+ eventLoopLag,
492
+ timestamp: new Date().toISOString(),
493
+ };
494
+ }