@zintrust/workers 0.1.27

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 (178) hide show
  1. package/README.md +861 -0
  2. package/dist/AnomalyDetection.d.ts +102 -0
  3. package/dist/AnomalyDetection.js +321 -0
  4. package/dist/AutoScaler.d.ts +127 -0
  5. package/dist/AutoScaler.js +425 -0
  6. package/dist/BroadcastWorker.d.ts +21 -0
  7. package/dist/BroadcastWorker.js +24 -0
  8. package/dist/CanaryController.d.ts +103 -0
  9. package/dist/CanaryController.js +380 -0
  10. package/dist/ChaosEngineering.d.ts +79 -0
  11. package/dist/ChaosEngineering.js +216 -0
  12. package/dist/CircuitBreaker.d.ts +106 -0
  13. package/dist/CircuitBreaker.js +374 -0
  14. package/dist/ClusterLock.d.ts +90 -0
  15. package/dist/ClusterLock.js +385 -0
  16. package/dist/ComplianceManager.d.ts +177 -0
  17. package/dist/ComplianceManager.js +556 -0
  18. package/dist/DatacenterOrchestrator.d.ts +133 -0
  19. package/dist/DatacenterOrchestrator.js +404 -0
  20. package/dist/DeadLetterQueue.d.ts +122 -0
  21. package/dist/DeadLetterQueue.js +539 -0
  22. package/dist/HealthMonitor.d.ts +42 -0
  23. package/dist/HealthMonitor.js +301 -0
  24. package/dist/MultiQueueWorker.d.ts +89 -0
  25. package/dist/MultiQueueWorker.js +277 -0
  26. package/dist/NotificationWorker.d.ts +21 -0
  27. package/dist/NotificationWorker.js +23 -0
  28. package/dist/Observability.d.ts +153 -0
  29. package/dist/Observability.js +530 -0
  30. package/dist/PluginManager.d.ts +123 -0
  31. package/dist/PluginManager.js +392 -0
  32. package/dist/PriorityQueue.d.ts +117 -0
  33. package/dist/PriorityQueue.js +244 -0
  34. package/dist/ResourceMonitor.d.ts +164 -0
  35. package/dist/ResourceMonitor.js +605 -0
  36. package/dist/SLAMonitor.d.ts +110 -0
  37. package/dist/SLAMonitor.js +274 -0
  38. package/dist/WorkerFactory.d.ts +193 -0
  39. package/dist/WorkerFactory.js +1507 -0
  40. package/dist/WorkerInit.d.ts +85 -0
  41. package/dist/WorkerInit.js +223 -0
  42. package/dist/WorkerMetrics.d.ts +114 -0
  43. package/dist/WorkerMetrics.js +509 -0
  44. package/dist/WorkerRegistry.d.ts +145 -0
  45. package/dist/WorkerRegistry.js +319 -0
  46. package/dist/WorkerShutdown.d.ts +61 -0
  47. package/dist/WorkerShutdown.js +159 -0
  48. package/dist/WorkerVersioning.d.ts +107 -0
  49. package/dist/WorkerVersioning.js +300 -0
  50. package/dist/build-manifest.json +462 -0
  51. package/dist/config/workerConfig.d.ts +3 -0
  52. package/dist/config/workerConfig.js +19 -0
  53. package/dist/createQueueWorker.d.ts +23 -0
  54. package/dist/createQueueWorker.js +113 -0
  55. package/dist/dashboard/index.d.ts +1 -0
  56. package/dist/dashboard/index.js +1 -0
  57. package/dist/dashboard/types.d.ts +117 -0
  58. package/dist/dashboard/types.js +1 -0
  59. package/dist/dashboard/workers-api.d.ts +4 -0
  60. package/dist/dashboard/workers-api.js +638 -0
  61. package/dist/dashboard/workers-dashboard-ui.d.ts +3 -0
  62. package/dist/dashboard/workers-dashboard-ui.js +1026 -0
  63. package/dist/dashboard/workers-dashboard.d.ts +4 -0
  64. package/dist/dashboard/workers-dashboard.js +904 -0
  65. package/dist/helper/index.d.ts +5 -0
  66. package/dist/helper/index.js +10 -0
  67. package/dist/http/WorkerApiController.d.ts +38 -0
  68. package/dist/http/WorkerApiController.js +312 -0
  69. package/dist/http/WorkerController.d.ts +374 -0
  70. package/dist/http/WorkerController.js +1351 -0
  71. package/dist/http/middleware/CustomValidation.d.ts +92 -0
  72. package/dist/http/middleware/CustomValidation.js +270 -0
  73. package/dist/http/middleware/DatacenterValidator.d.ts +3 -0
  74. package/dist/http/middleware/DatacenterValidator.js +94 -0
  75. package/dist/http/middleware/EditWorkerValidation.d.ts +7 -0
  76. package/dist/http/middleware/EditWorkerValidation.js +55 -0
  77. package/dist/http/middleware/FeaturesValidator.d.ts +3 -0
  78. package/dist/http/middleware/FeaturesValidator.js +60 -0
  79. package/dist/http/middleware/InfrastructureValidator.d.ts +31 -0
  80. package/dist/http/middleware/InfrastructureValidator.js +226 -0
  81. package/dist/http/middleware/OptionsValidator.d.ts +3 -0
  82. package/dist/http/middleware/OptionsValidator.js +112 -0
  83. package/dist/http/middleware/PayloadSanitizer.d.ts +7 -0
  84. package/dist/http/middleware/PayloadSanitizer.js +42 -0
  85. package/dist/http/middleware/ProcessorPathSanitizer.d.ts +3 -0
  86. package/dist/http/middleware/ProcessorPathSanitizer.js +74 -0
  87. package/dist/http/middleware/QueueNameSanitizer.d.ts +3 -0
  88. package/dist/http/middleware/QueueNameSanitizer.js +45 -0
  89. package/dist/http/middleware/ValidateDriver.d.ts +7 -0
  90. package/dist/http/middleware/ValidateDriver.js +20 -0
  91. package/dist/http/middleware/VersionSanitizer.d.ts +3 -0
  92. package/dist/http/middleware/VersionSanitizer.js +25 -0
  93. package/dist/http/middleware/WorkerNameSanitizer.d.ts +3 -0
  94. package/dist/http/middleware/WorkerNameSanitizer.js +46 -0
  95. package/dist/http/middleware/WorkerValidationChain.d.ts +27 -0
  96. package/dist/http/middleware/WorkerValidationChain.js +185 -0
  97. package/dist/index.d.ts +46 -0
  98. package/dist/index.js +48 -0
  99. package/dist/routes/workers.d.ts +12 -0
  100. package/dist/routes/workers.js +81 -0
  101. package/dist/storage/WorkerStore.d.ts +45 -0
  102. package/dist/storage/WorkerStore.js +195 -0
  103. package/dist/type.d.ts +76 -0
  104. package/dist/type.js +1 -0
  105. package/dist/ui/router/ui.d.ts +3 -0
  106. package/dist/ui/router/ui.js +83 -0
  107. package/dist/ui/types/worker-ui.d.ts +229 -0
  108. package/dist/ui/types/worker-ui.js +5 -0
  109. package/package.json +53 -0
  110. package/src/AnomalyDetection.ts +434 -0
  111. package/src/AutoScaler.ts +654 -0
  112. package/src/BroadcastWorker.ts +34 -0
  113. package/src/CanaryController.ts +531 -0
  114. package/src/ChaosEngineering.ts +301 -0
  115. package/src/CircuitBreaker.ts +495 -0
  116. package/src/ClusterLock.ts +499 -0
  117. package/src/ComplianceManager.ts +815 -0
  118. package/src/DatacenterOrchestrator.ts +561 -0
  119. package/src/DeadLetterQueue.ts +733 -0
  120. package/src/HealthMonitor.ts +390 -0
  121. package/src/MultiQueueWorker.ts +431 -0
  122. package/src/NotificationWorker.ts +33 -0
  123. package/src/Observability.ts +696 -0
  124. package/src/PluginManager.ts +551 -0
  125. package/src/PriorityQueue.ts +351 -0
  126. package/src/ResourceMonitor.ts +769 -0
  127. package/src/SLAMonitor.ts +408 -0
  128. package/src/WorkerFactory.ts +2108 -0
  129. package/src/WorkerInit.ts +313 -0
  130. package/src/WorkerMetrics.ts +709 -0
  131. package/src/WorkerRegistry.ts +443 -0
  132. package/src/WorkerShutdown.ts +210 -0
  133. package/src/WorkerVersioning.ts +422 -0
  134. package/src/config/workerConfig.ts +25 -0
  135. package/src/createQueueWorker.ts +174 -0
  136. package/src/dashboard/index.ts +6 -0
  137. package/src/dashboard/types.ts +141 -0
  138. package/src/dashboard/workers-api.ts +785 -0
  139. package/src/dashboard/zintrust.svg +30 -0
  140. package/src/helper/index.ts +11 -0
  141. package/src/http/WorkerApiController.ts +369 -0
  142. package/src/http/WorkerController.ts +1512 -0
  143. package/src/http/middleware/CustomValidation.ts +360 -0
  144. package/src/http/middleware/DatacenterValidator.ts +124 -0
  145. package/src/http/middleware/EditWorkerValidation.ts +74 -0
  146. package/src/http/middleware/FeaturesValidator.ts +82 -0
  147. package/src/http/middleware/InfrastructureValidator.ts +295 -0
  148. package/src/http/middleware/OptionsValidator.ts +144 -0
  149. package/src/http/middleware/PayloadSanitizer.ts +52 -0
  150. package/src/http/middleware/ProcessorPathSanitizer.ts +86 -0
  151. package/src/http/middleware/QueueNameSanitizer.ts +55 -0
  152. package/src/http/middleware/ValidateDriver.ts +29 -0
  153. package/src/http/middleware/VersionSanitizer.ts +30 -0
  154. package/src/http/middleware/WorkerNameSanitizer.ts +56 -0
  155. package/src/http/middleware/WorkerValidationChain.ts +230 -0
  156. package/src/index.ts +98 -0
  157. package/src/routes/workers.ts +154 -0
  158. package/src/storage/WorkerStore.ts +240 -0
  159. package/src/type.ts +89 -0
  160. package/src/types/queue-monitor.d.ts +38 -0
  161. package/src/types/queue-redis.d.ts +38 -0
  162. package/src/ui/README.md +13 -0
  163. package/src/ui/components/JsonEditor.js +670 -0
  164. package/src/ui/components/JsonViewer.js +387 -0
  165. package/src/ui/components/WorkerCard.js +178 -0
  166. package/src/ui/components/WorkerExpandPanel.js +257 -0
  167. package/src/ui/components/fetcher.js +42 -0
  168. package/src/ui/components/sla-scorecard.js +32 -0
  169. package/src/ui/components/styles.css +30 -0
  170. package/src/ui/components/table-expander.js +34 -0
  171. package/src/ui/integration/worker-ui-integration.js +565 -0
  172. package/src/ui/router/ui.ts +99 -0
  173. package/src/ui/services/workerApi.js +240 -0
  174. package/src/ui/types/worker-ui.ts +283 -0
  175. package/src/ui/utils/jsonValidator.js +444 -0
  176. package/src/ui/workers/index.html +202 -0
  177. package/src/ui/workers/main.js +1781 -0
  178. package/src/ui/workers/styles.css +1350 -0
@@ -0,0 +1,769 @@
1
+ /**
2
+ * Resource Monitor
3
+ * Real-time resource tracking with cost calculation
4
+ * Sealed namespace for immutability
5
+ */
6
+
7
+ import { Env, Logger, NodeSingletons } from '@zintrust/core';
8
+
9
+ const getOsModule = (): typeof NodeSingletons.os => NodeSingletons?.os ?? null;
10
+
11
+ const safeTotalMemory = (): number => {
12
+ const os = getOsModule();
13
+ if (!os?.totalmem) return 0;
14
+ try {
15
+ return os.totalmem();
16
+ } catch {
17
+ return 0;
18
+ }
19
+ };
20
+
21
+ const safeFreeMemory = (): number => {
22
+ const os = getOsModule();
23
+ if (!os?.freemem) return 0;
24
+ try {
25
+ return os.freemem();
26
+ } catch {
27
+ return 0;
28
+ }
29
+ };
30
+
31
+ const safeLoadAverage = (): number[] => {
32
+ const os = getOsModule();
33
+ if (!os?.loadavg) return [0, 0, 0];
34
+ try {
35
+ return os.loadavg();
36
+ } catch {
37
+ return [0, 0, 0];
38
+ }
39
+ };
40
+
41
+ const safeCpuCount = (): number => {
42
+ const os = getOsModule();
43
+ if (!os?.cpus) return 1;
44
+ try {
45
+ return Math.max(1, os.cpus().length);
46
+ } catch {
47
+ return 1;
48
+ }
49
+ };
50
+
51
+ const safePlatform = (): string => {
52
+ const os = getOsModule();
53
+ if (!os?.platform) return 'unknown';
54
+ try {
55
+ return os.platform();
56
+ } catch {
57
+ return 'unknown';
58
+ }
59
+ };
60
+
61
+ const safeArch = (): string => {
62
+ const os = getOsModule();
63
+ if (!os?.arch) return 'unknown';
64
+ try {
65
+ return os.arch();
66
+ } catch {
67
+ return 'unknown';
68
+ }
69
+ };
70
+
71
+ const safeHostname = (): string => {
72
+ const os = getOsModule();
73
+ if (!os?.hostname) return 'unknown';
74
+ try {
75
+ return os.hostname();
76
+ } catch {
77
+ return 'unknown';
78
+ }
79
+ };
80
+
81
+ const safeUptime = (): number => {
82
+ const os = getOsModule();
83
+ if (!os?.uptime) return 0;
84
+ try {
85
+ return os.uptime();
86
+ } catch {
87
+ return 0;
88
+ }
89
+ };
90
+
91
+ export type ResourceSnapshot = {
92
+ timestamp: Date;
93
+ cpu: {
94
+ usage: number; // Percentage 0-100
95
+ loadAverage: number[];
96
+ cores: number;
97
+ };
98
+ memory: {
99
+ total: number; // Bytes
100
+ used: number; // Bytes
101
+ free: number; // Bytes
102
+ usage: number; // Percentage 0-100
103
+ };
104
+ disk: {
105
+ read: number; // Bytes/sec
106
+ write: number; // Bytes/sec
107
+ };
108
+ network: {
109
+ received: number; // Bytes/sec
110
+ transmitted: number; // Bytes/sec
111
+ };
112
+ process: {
113
+ pid: number;
114
+ uptime: number; // Seconds
115
+ memoryUsage: NodeJS.MemoryUsage;
116
+ cpuUsage: NodeJS.CpuUsage;
117
+ };
118
+ };
119
+
120
+ export type WorkerResourceUsage = {
121
+ cpu: number;
122
+ memory: { number: number; percent: number; used: number; free: number };
123
+ cost: { hourly: number; daily: number };
124
+ workerName: string;
125
+ resourceSnapshot: ResourceSnapshot;
126
+ estimatedCost: {
127
+ perHour: number;
128
+ perDay: number;
129
+ perMonth: number;
130
+ };
131
+ efficiency: {
132
+ cpuEfficiency: number; // 0-100, higher is better
133
+ memoryEfficiency: number; // 0-100, higher is better
134
+ overallScore: number; // 0-100
135
+ };
136
+ };
137
+
138
+ export type CostCalculationConfig = {
139
+ computeCostPerCoreHour: number; // USD per core per hour
140
+ memoryCostPerGBHour: number; // USD per GB per hour
141
+ networkCostPerGB: number; // USD per GB transferred
142
+ diskCostPerGB: number; // USD per GB storage
143
+ spotInstanceDiscount: number; // 0-100 percentage discount
144
+ };
145
+
146
+ export type ResourceAlert = {
147
+ timestamp: Date;
148
+ workerName: string;
149
+ alertType: 'cpu-high' | 'memory-high' | 'disk-high' | 'cost-high';
150
+ severity: 'warning' | 'critical';
151
+ message: string;
152
+ currentValue: number;
153
+ threshold: number;
154
+ recommendation?: string;
155
+ };
156
+
157
+ export type ResourceTrend = {
158
+ workerName: string;
159
+ metric: 'cpu' | 'memory' | 'disk' | 'network' | 'cost';
160
+ period: 'hour' | 'day' | 'week';
161
+ trend: 'increasing' | 'decreasing' | 'stable';
162
+ changePercentage: number;
163
+ predictions: {
164
+ nextHour: number;
165
+ nextDay: number;
166
+ nextWeek: number;
167
+ };
168
+ };
169
+
170
+ // Default cost configuration (AWS-like pricing)
171
+ const DEFAULT_COST_CONFIG: CostCalculationConfig = {
172
+ computeCostPerCoreHour: 0.0416, // ~$0.0416 per vCPU hour (t3.medium equivalent)
173
+ memoryCostPerGBHour: 0.0052, // ~$0.0052 per GB hour
174
+ networkCostPerGB: 0.09, // $0.09 per GB transferred
175
+ diskCostPerGB: 0.1, // $0.10 per GB/month
176
+ spotInstanceDiscount: 70, // 70% discount for spot instances
177
+ };
178
+
179
+ // Internal state
180
+ let costConfig: CostCalculationConfig = { ...DEFAULT_COST_CONFIG };
181
+ let monitoringInterval: NodeJS.Timeout | null = null;
182
+ const resourceHistory = new Map<string, ResourceSnapshot[]>();
183
+ const alertHistory = new Map<string, ResourceAlert[]>();
184
+
185
+ // Resource thresholds
186
+ const THRESHOLDS = {
187
+ cpu: { warning: 70, critical: 90 },
188
+ memory: { warning: 75, critical: 85 },
189
+ disk: { warning: 80, critical: 90 },
190
+ costPerHour: { warning: 10, critical: 50 },
191
+ };
192
+
193
+ // Previous CPU usage for delta calculation
194
+ let previousCpuUsage: NodeJS.CpuUsage | null = null;
195
+ let previousCpuTimestamp: number | null = null;
196
+
197
+ /**
198
+ * Helper: Calculate CPU usage percentage
199
+ */
200
+ const calculateCpuUsage = (): number => {
201
+ const currentCpuUsage = process.cpuUsage();
202
+ const currentTimestamp = Date.now();
203
+
204
+ if (previousCpuUsage === null || previousCpuTimestamp === null) {
205
+ previousCpuUsage = currentCpuUsage;
206
+ previousCpuTimestamp = currentTimestamp;
207
+ return 0;
208
+ }
209
+
210
+ const userDelta = currentCpuUsage.user - previousCpuUsage.user;
211
+ const systemDelta = currentCpuUsage.system - previousCpuUsage.system;
212
+ const timeDelta = (currentTimestamp - previousCpuTimestamp) * 1000; // Convert ms to microseconds
213
+
214
+ previousCpuUsage = currentCpuUsage;
215
+ previousCpuTimestamp = currentTimestamp;
216
+
217
+ if (timeDelta === 0) return 0;
218
+
219
+ const totalCpuDelta = userDelta + systemDelta;
220
+ const cpuPercentage = (totalCpuDelta / timeDelta) * 100;
221
+
222
+ return Math.min(100, Math.max(0, cpuPercentage));
223
+ };
224
+
225
+ /**
226
+ * Helper: Get memory usage
227
+ */
228
+ const getMemoryUsage = (): ResourceSnapshot['memory'] => {
229
+ const totalMemory = safeTotalMemory();
230
+ const freeMemory = safeFreeMemory();
231
+ const usedMemory = totalMemory - freeMemory;
232
+ const usage = totalMemory > 0 ? (usedMemory / totalMemory) * 100 : 0;
233
+
234
+ return {
235
+ total: totalMemory,
236
+ used: usedMemory,
237
+ free: freeMemory,
238
+ usage,
239
+ };
240
+ };
241
+
242
+ /**
243
+ * Helper: Capture resource snapshot
244
+ */
245
+ const captureSnapshot = (): ResourceSnapshot => {
246
+ const cpuUsage = calculateCpuUsage();
247
+ const memoryUsage = getMemoryUsage();
248
+ const loadAverage = safeLoadAverage();
249
+ const cpuCores = safeCpuCount();
250
+
251
+ return {
252
+ timestamp: new Date(),
253
+ cpu: {
254
+ usage: cpuUsage,
255
+ loadAverage,
256
+ cores: cpuCores,
257
+ },
258
+ memory: memoryUsage,
259
+ disk: {
260
+ read: 0, // Would need platform-specific implementation
261
+ write: 0,
262
+ },
263
+ network: {
264
+ received: 0, // Would need platform-specific implementation
265
+ transmitted: 0,
266
+ },
267
+ process: {
268
+ pid: process.pid,
269
+ uptime: process.uptime(),
270
+ memoryUsage: process.memoryUsage(),
271
+ cpuUsage: process.cpuUsage(),
272
+ },
273
+ };
274
+ };
275
+
276
+ /**
277
+ * Helper: Calculate cost based on resource usage
278
+ */
279
+ const calculateCost = (
280
+ snapshot: ResourceSnapshot,
281
+ useSpotDiscount = false
282
+ ): WorkerResourceUsage['estimatedCost'] => {
283
+ const { cpu, memory } = snapshot;
284
+
285
+ // CPU cost (based on cores and usage)
286
+ const cpuCostPerHour = cpu.cores * (cpu.usage / 100) * costConfig.computeCostPerCoreHour;
287
+
288
+ // Memory cost (based on GB used)
289
+ const memoryGB = memory.used / (1024 * 1024 * 1024);
290
+ const memoryCostPerHour = memoryGB * costConfig.memoryCostPerGBHour;
291
+
292
+ // Total compute cost
293
+ let totalCostPerHour = cpuCostPerHour + memoryCostPerHour;
294
+
295
+ // Apply spot instance discount if applicable
296
+ if (useSpotDiscount) {
297
+ totalCostPerHour *= 1 - costConfig.spotInstanceDiscount / 100;
298
+ }
299
+
300
+ return {
301
+ perHour: totalCostPerHour,
302
+ perDay: totalCostPerHour * 24,
303
+ perMonth: totalCostPerHour * 24 * 30,
304
+ };
305
+ };
306
+
307
+ /**
308
+ * Helper: Calculate efficiency score
309
+ */
310
+ const calculateEfficiency = (snapshot: ResourceSnapshot): WorkerResourceUsage['efficiency'] => {
311
+ const { cpu, memory } = snapshot;
312
+
313
+ // CPU efficiency: 50-80% usage is ideal
314
+ let cpuEfficiency: number;
315
+ if (cpu.usage < 30) {
316
+ cpuEfficiency = cpu.usage * 2; // Under-utilized
317
+ } else if (cpu.usage > 80) {
318
+ cpuEfficiency = 100 - (cpu.usage - 80) * 2; // Over-utilized
319
+ } else {
320
+ cpuEfficiency = 100; // Ideal range
321
+ }
322
+
323
+ // Memory efficiency: 50-75% usage is ideal
324
+ let memoryEfficiency: number;
325
+ if (memory.usage < 40) {
326
+ memoryEfficiency = memory.usage * 1.5; // Under-utilized
327
+ } else if (memory.usage > 75) {
328
+ memoryEfficiency = 100 - (memory.usage - 75) * 2; // Over-utilized
329
+ } else {
330
+ memoryEfficiency = 100; // Ideal range
331
+ }
332
+
333
+ const overallScore = cpuEfficiency * 0.6 + memoryEfficiency * 0.4;
334
+
335
+ return {
336
+ cpuEfficiency: Math.round(cpuEfficiency),
337
+ memoryEfficiency: Math.round(memoryEfficiency),
338
+ overallScore: Math.round(overallScore),
339
+ };
340
+ };
341
+
342
+ /**
343
+ * Helper: Check thresholds and create alerts
344
+ */
345
+ const checkThresholds = (
346
+ workerName: string,
347
+ snapshot: ResourceSnapshot,
348
+ cost: WorkerResourceUsage['estimatedCost']
349
+ ): ResourceAlert[] => {
350
+ const alerts: ResourceAlert[] = [];
351
+
352
+ // CPU alerts
353
+ if (snapshot.cpu.usage >= THRESHOLDS.cpu.critical) {
354
+ alerts.push({
355
+ timestamp: new Date(),
356
+ workerName,
357
+ alertType: 'cpu-high',
358
+ severity: 'critical',
359
+ message: `Critical CPU usage: ${snapshot.cpu.usage.toFixed(1)}%`,
360
+ currentValue: snapshot.cpu.usage,
361
+ threshold: THRESHOLDS.cpu.critical,
362
+ recommendation: 'Consider scaling up or optimizing worker code',
363
+ });
364
+ } else if (snapshot.cpu.usage >= THRESHOLDS.cpu.warning) {
365
+ alerts.push({
366
+ timestamp: new Date(),
367
+ workerName,
368
+ alertType: 'cpu-high',
369
+ severity: 'warning',
370
+ message: `High CPU usage: ${snapshot.cpu.usage.toFixed(1)}%`,
371
+ currentValue: snapshot.cpu.usage,
372
+ threshold: THRESHOLDS.cpu.warning,
373
+ recommendation: 'Monitor closely and consider scaling',
374
+ });
375
+ }
376
+
377
+ // Memory alerts
378
+ if (snapshot.memory.usage >= THRESHOLDS.memory.critical) {
379
+ alerts.push({
380
+ timestamp: new Date(),
381
+ workerName,
382
+ alertType: 'memory-high',
383
+ severity: 'critical',
384
+ message: `Critical memory usage: ${snapshot.memory.usage.toFixed(1)}%`,
385
+ currentValue: snapshot.memory.usage,
386
+ threshold: THRESHOLDS.memory.critical,
387
+ recommendation: 'Increase memory allocation or optimize memory usage',
388
+ });
389
+ } else if (snapshot.memory.usage >= THRESHOLDS.memory.warning) {
390
+ alerts.push({
391
+ timestamp: new Date(),
392
+ workerName,
393
+ alertType: 'memory-high',
394
+ severity: 'warning',
395
+ message: `High memory usage: ${snapshot.memory.usage.toFixed(1)}%`,
396
+ currentValue: snapshot.memory.usage,
397
+ threshold: THRESHOLDS.memory.warning,
398
+ recommendation: 'Monitor memory consumption',
399
+ });
400
+ }
401
+
402
+ // Cost alerts
403
+ if (cost.perHour >= THRESHOLDS.costPerHour.critical) {
404
+ alerts.push({
405
+ timestamp: new Date(),
406
+ workerName,
407
+ alertType: 'cost-high',
408
+ severity: 'critical',
409
+ message: `Critical hourly cost: $${cost.perHour.toFixed(2)}/hr`,
410
+ currentValue: cost.perHour,
411
+ threshold: THRESHOLDS.costPerHour.critical,
412
+ recommendation: 'Review resource allocation and consider cost optimization',
413
+ });
414
+ } else if (cost.perHour >= THRESHOLDS.costPerHour.warning) {
415
+ alerts.push({
416
+ timestamp: new Date(),
417
+ workerName,
418
+ alertType: 'cost-high',
419
+ severity: 'warning',
420
+ message: `High hourly cost: $${cost.perHour.toFixed(2)}/hr`,
421
+ currentValue: cost.perHour,
422
+ threshold: THRESHOLDS.costPerHour.warning,
423
+ recommendation: 'Consider using spot instances or reducing concurrency',
424
+ });
425
+ }
426
+
427
+ return alerts;
428
+ };
429
+
430
+ /**
431
+ * Helper: Store alert
432
+ */
433
+ const storeAlert = (alert: ResourceAlert): void => {
434
+ let history = alertHistory.get(alert.workerName);
435
+ if (!history) {
436
+ history = [];
437
+ alertHistory.set(alert.workerName, history);
438
+ }
439
+
440
+ history.push(alert);
441
+
442
+ // Keep only last 1000 alerts
443
+ if (history.length > 1000) {
444
+ history.shift();
445
+ }
446
+
447
+ Logger.warn(`Resource alert: ${alert.workerName}`, {
448
+ type: alert.alertType,
449
+ severity: alert.severity,
450
+ message: alert.message,
451
+ recommendation: alert.recommendation,
452
+ });
453
+ };
454
+
455
+ /**
456
+ * Helper: Calculate trend
457
+ */
458
+ const calculateTrend = (
459
+ workerName: string,
460
+ metric: ResourceTrend['metric'],
461
+ period: ResourceTrend['period']
462
+ ): ResourceTrend | null => {
463
+ const history = resourceHistory.get(workerName);
464
+ if (!history || history.length < 2) return null;
465
+
466
+ const now = Date.now();
467
+ let periodMs: number;
468
+
469
+ switch (period) {
470
+ case 'hour':
471
+ periodMs = 60 * 60 * 1000;
472
+ break;
473
+ case 'day':
474
+ periodMs = 24 * 60 * 60 * 1000;
475
+ break;
476
+ case 'week':
477
+ periodMs = 7 * 24 * 60 * 60 * 1000;
478
+ break;
479
+ }
480
+
481
+ // Filter snapshots within period
482
+ const periodSnapshots = history.filter((s) => now - s.timestamp.getTime() <= periodMs);
483
+ if (periodSnapshots.length < 2) return null;
484
+
485
+ // Get metric values
486
+ const values = periodSnapshots.map((s) => {
487
+ switch (metric) {
488
+ case 'cpu':
489
+ return s.cpu.usage;
490
+ case 'memory':
491
+ return s.memory.usage;
492
+ case 'disk':
493
+ return s.disk.read + s.disk.write;
494
+ case 'network':
495
+ return s.network.received + s.network.transmitted;
496
+ case 'cost':
497
+ return calculateCost(s).perHour;
498
+ }
499
+ });
500
+
501
+ // Simple linear regression for trend
502
+ const firstValue = values[0];
503
+ const lastValue = values.at(-1) ?? values[0];
504
+ const changePercentage = ((lastValue - firstValue) / firstValue) * 100;
505
+
506
+ let trend: ResourceTrend['trend'];
507
+ if (Math.abs(changePercentage) < 5) {
508
+ trend = 'stable';
509
+ } else if (changePercentage > 0) {
510
+ trend = 'increasing';
511
+ } else {
512
+ trend = 'decreasing';
513
+ }
514
+
515
+ // Simple predictions (linear extrapolation)
516
+ const avgChange = (lastValue - firstValue) / periodSnapshots.length;
517
+ const predictions = {
518
+ nextHour: lastValue + avgChange * 12, // Assuming 5-min intervals
519
+ nextDay: lastValue + avgChange * 288,
520
+ nextWeek: lastValue + avgChange * 2016,
521
+ };
522
+
523
+ return {
524
+ workerName,
525
+ metric,
526
+ period,
527
+ trend,
528
+ changePercentage,
529
+ predictions,
530
+ };
531
+ };
532
+
533
+ /**
534
+ * Resource Monitor - Sealed namespace
535
+ */
536
+ export const ResourceMonitor = Object.freeze({
537
+ /**
538
+ * Initialize resource monitor
539
+ */
540
+ initialize(config?: Partial<CostCalculationConfig>): void {
541
+ if (config) {
542
+ costConfig = { ...DEFAULT_COST_CONFIG, ...config };
543
+ }
544
+
545
+ Logger.info('ResourceMonitor initialized', { costConfig });
546
+ },
547
+
548
+ /**
549
+ * Check whether monitoring is running
550
+ */
551
+ isRunning(): boolean {
552
+ return monitoringInterval !== null;
553
+ },
554
+
555
+ /**
556
+ * Start monitoring
557
+ */
558
+ start(intervalSeconds = 30): void {
559
+ const globalResourceMonitoring = Env.getBool('WORKER_RESOURCE_MONITORING', false);
560
+ if (!globalResourceMonitoring) {
561
+ Logger.warn('ResourceMonitor disabled (WORKER_RESOURCE_MONITORING=false)');
562
+ return;
563
+ }
564
+ if (monitoringInterval) {
565
+ Logger.warn('ResourceMonitor already running');
566
+ return;
567
+ }
568
+
569
+ // Initial snapshot
570
+ previousCpuUsage = process.cpuUsage();
571
+ previousCpuTimestamp = Date.now();
572
+
573
+ monitoringInterval = setInterval(() => {
574
+ const snapshot = captureSnapshot();
575
+ // Store snapshot for later analysis
576
+ // This would typically be saved to a time-series database
577
+ Logger.debug('Resource snapshot captured', {
578
+ cpu: snapshot.cpu.usage.toFixed(1) + '%',
579
+ memory: snapshot.memory.usage.toFixed(1) + '%',
580
+ });
581
+ }, intervalSeconds * 1000);
582
+
583
+ Logger.info('ResourceMonitor started', { intervalSeconds });
584
+ },
585
+
586
+ /**
587
+ * Stop monitoring
588
+ */
589
+ stop(): void {
590
+ if (monitoringInterval) {
591
+ clearInterval(monitoringInterval);
592
+ monitoringInterval = null;
593
+ Logger.info('ResourceMonitor stopped');
594
+ }
595
+ },
596
+
597
+ /**
598
+ * Get current resource usage
599
+ */
600
+ getCurrentUsage(workerName: string, useSpotDiscount = false): WorkerResourceUsage {
601
+ const snapshot = captureSnapshot();
602
+ const cost = calculateCost(snapshot, useSpotDiscount);
603
+ const efficiency = calculateEfficiency(snapshot);
604
+
605
+ // Store in history
606
+ let history = resourceHistory.get(workerName);
607
+ if (!history) {
608
+ history = [];
609
+ resourceHistory.set(workerName, history);
610
+ }
611
+
612
+ history.push(snapshot);
613
+
614
+ // Keep only last 1000 snapshots
615
+ if (history.length > 1000) {
616
+ history.shift();
617
+ }
618
+
619
+ // Check thresholds
620
+ const alerts = checkThresholds(workerName, snapshot, cost);
621
+ alerts.forEach(storeAlert);
622
+
623
+ return {
624
+ workerName,
625
+ cpu: snapshot.cpu.usage,
626
+ memory: {
627
+ number: snapshot.memory.total,
628
+ percent: snapshot.memory.usage,
629
+ used: snapshot.memory.used,
630
+ free: snapshot.memory.free,
631
+ },
632
+ cost: {
633
+ hourly: cost.perHour,
634
+ daily: cost.perDay,
635
+ },
636
+ resourceSnapshot: snapshot,
637
+ estimatedCost: cost,
638
+ efficiency,
639
+ };
640
+ },
641
+
642
+ /**
643
+ * Get resource history
644
+ */
645
+ getHistory(workerName: string, limit = 100): ReadonlyArray<ResourceSnapshot> {
646
+ const history = resourceHistory.get(workerName) ?? [];
647
+ return history.slice(-limit).map((s) => ({ ...s }));
648
+ },
649
+
650
+ /**
651
+ * Get alerts
652
+ */
653
+ getAlerts(workerName: string, limit = 100): ReadonlyArray<ResourceAlert> {
654
+ const history = alertHistory.get(workerName) ?? [];
655
+ return history.slice(-limit).map((a) => ({ ...a }));
656
+ },
657
+
658
+ /**
659
+ * Get trend analysis
660
+ */
661
+ getTrend(
662
+ workerName: string,
663
+ metric: ResourceTrend['metric'],
664
+ period: ResourceTrend['period']
665
+ ): ResourceTrend | null {
666
+ return calculateTrend(workerName, metric, period);
667
+ },
668
+
669
+ /**
670
+ * Get all trends
671
+ */
672
+ getAllTrends(
673
+ workerName: string,
674
+ period: ResourceTrend['period']
675
+ ): Record<ResourceTrend['metric'], ResourceTrend | null> {
676
+ return {
677
+ cpu: calculateTrend(workerName, 'cpu', period),
678
+ memory: calculateTrend(workerName, 'memory', period),
679
+ disk: calculateTrend(workerName, 'disk', period),
680
+ network: calculateTrend(workerName, 'network', period),
681
+ cost: calculateTrend(workerName, 'cost', period),
682
+ };
683
+ },
684
+
685
+ /**
686
+ * Update cost configuration
687
+ */
688
+ updateCostConfig(config: Partial<CostCalculationConfig>): void {
689
+ costConfig = { ...costConfig, ...config };
690
+ Logger.info('Resource monitor cost config updated', { costConfig });
691
+ },
692
+
693
+ /**
694
+ * Get cost configuration
695
+ */
696
+ getCostConfig(): CostCalculationConfig {
697
+ return { ...costConfig };
698
+ },
699
+
700
+ /**
701
+ * Calculate projected cost
702
+ */
703
+ calculateProjectedCost(
704
+ cpuUsagePercent: number,
705
+ memoryGB: number,
706
+ hoursPerDay: number,
707
+ useSpotDiscount = false
708
+ ): { daily: number; monthly: number; yearly: number } {
709
+ const cpuCores = safeCpuCount();
710
+ const cpuCostPerHour = cpuCores * (cpuUsagePercent / 100) * costConfig.computeCostPerCoreHour;
711
+ const memoryCostPerHour = memoryGB * costConfig.memoryCostPerGBHour;
712
+
713
+ let totalCostPerHour = cpuCostPerHour + memoryCostPerHour;
714
+
715
+ if (useSpotDiscount) {
716
+ totalCostPerHour *= 1 - costConfig.spotInstanceDiscount / 100;
717
+ }
718
+
719
+ return {
720
+ daily: totalCostPerHour * hoursPerDay,
721
+ monthly: totalCostPerHour * hoursPerDay * 30,
722
+ yearly: totalCostPerHour * hoursPerDay * 365,
723
+ };
724
+ },
725
+
726
+ /**
727
+ * Get system information
728
+ */
729
+ getSystemInfo(): {
730
+ platform: string;
731
+ arch: string;
732
+ hostname: string;
733
+ cpus: number;
734
+ totalMemory: number;
735
+ freeMemory: number;
736
+ uptime: number;
737
+ } {
738
+ return {
739
+ platform: safePlatform(),
740
+ arch: safeArch(),
741
+ hostname: safeHostname(),
742
+ cpus: safeCpuCount(),
743
+ totalMemory: safeTotalMemory(),
744
+ freeMemory: safeFreeMemory(),
745
+ uptime: safeUptime(),
746
+ };
747
+ },
748
+
749
+ /**
750
+ * Clear history for a worker
751
+ */
752
+ clearHistory(workerName: string): void {
753
+ resourceHistory.delete(workerName);
754
+ alertHistory.delete(workerName);
755
+ Logger.info(`Cleared resource history for ${workerName}`);
756
+ },
757
+
758
+ /**
759
+ * Shutdown
760
+ */
761
+ shutdown(): void {
762
+ ResourceMonitor.stop();
763
+ resourceHistory.clear();
764
+ alertHistory.clear();
765
+ Logger.info('ResourceMonitor shutdown complete');
766
+ },
767
+ });
768
+
769
+ // Graceful shutdown handled by WorkerShutdown