@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,605 @@
1
+ /**
2
+ * Resource Monitor
3
+ * Real-time resource tracking with cost calculation
4
+ * Sealed namespace for immutability
5
+ */
6
+ import { Env, Logger, NodeSingletons } from '@zintrust/core';
7
+ const getOsModule = () => NodeSingletons?.os ?? null;
8
+ const safeTotalMemory = () => {
9
+ const os = getOsModule();
10
+ if (!os?.totalmem)
11
+ return 0;
12
+ try {
13
+ return os.totalmem();
14
+ }
15
+ catch {
16
+ return 0;
17
+ }
18
+ };
19
+ const safeFreeMemory = () => {
20
+ const os = getOsModule();
21
+ if (!os?.freemem)
22
+ return 0;
23
+ try {
24
+ return os.freemem();
25
+ }
26
+ catch {
27
+ return 0;
28
+ }
29
+ };
30
+ const safeLoadAverage = () => {
31
+ const os = getOsModule();
32
+ if (!os?.loadavg)
33
+ return [0, 0, 0];
34
+ try {
35
+ return os.loadavg();
36
+ }
37
+ catch {
38
+ return [0, 0, 0];
39
+ }
40
+ };
41
+ const safeCpuCount = () => {
42
+ const os = getOsModule();
43
+ if (!os?.cpus)
44
+ return 1;
45
+ try {
46
+ return Math.max(1, os.cpus().length);
47
+ }
48
+ catch {
49
+ return 1;
50
+ }
51
+ };
52
+ const safePlatform = () => {
53
+ const os = getOsModule();
54
+ if (!os?.platform)
55
+ return 'unknown';
56
+ try {
57
+ return os.platform();
58
+ }
59
+ catch {
60
+ return 'unknown';
61
+ }
62
+ };
63
+ const safeArch = () => {
64
+ const os = getOsModule();
65
+ if (!os?.arch)
66
+ return 'unknown';
67
+ try {
68
+ return os.arch();
69
+ }
70
+ catch {
71
+ return 'unknown';
72
+ }
73
+ };
74
+ const safeHostname = () => {
75
+ const os = getOsModule();
76
+ if (!os?.hostname)
77
+ return 'unknown';
78
+ try {
79
+ return os.hostname();
80
+ }
81
+ catch {
82
+ return 'unknown';
83
+ }
84
+ };
85
+ const safeUptime = () => {
86
+ const os = getOsModule();
87
+ if (!os?.uptime)
88
+ return 0;
89
+ try {
90
+ return os.uptime();
91
+ }
92
+ catch {
93
+ return 0;
94
+ }
95
+ };
96
+ // Default cost configuration (AWS-like pricing)
97
+ const DEFAULT_COST_CONFIG = {
98
+ computeCostPerCoreHour: 0.0416, // ~$0.0416 per vCPU hour (t3.medium equivalent)
99
+ memoryCostPerGBHour: 0.0052, // ~$0.0052 per GB hour
100
+ networkCostPerGB: 0.09, // $0.09 per GB transferred
101
+ diskCostPerGB: 0.1, // $0.10 per GB/month
102
+ spotInstanceDiscount: 70, // 70% discount for spot instances
103
+ };
104
+ // Internal state
105
+ let costConfig = { ...DEFAULT_COST_CONFIG };
106
+ let monitoringInterval = null;
107
+ const resourceHistory = new Map();
108
+ const alertHistory = new Map();
109
+ // Resource thresholds
110
+ const THRESHOLDS = {
111
+ cpu: { warning: 70, critical: 90 },
112
+ memory: { warning: 75, critical: 85 },
113
+ disk: { warning: 80, critical: 90 },
114
+ costPerHour: { warning: 10, critical: 50 },
115
+ };
116
+ // Previous CPU usage for delta calculation
117
+ let previousCpuUsage = null;
118
+ let previousCpuTimestamp = null;
119
+ /**
120
+ * Helper: Calculate CPU usage percentage
121
+ */
122
+ const calculateCpuUsage = () => {
123
+ const currentCpuUsage = process.cpuUsage();
124
+ const currentTimestamp = Date.now();
125
+ if (previousCpuUsage === null || previousCpuTimestamp === null) {
126
+ previousCpuUsage = currentCpuUsage;
127
+ previousCpuTimestamp = currentTimestamp;
128
+ return 0;
129
+ }
130
+ const userDelta = currentCpuUsage.user - previousCpuUsage.user;
131
+ const systemDelta = currentCpuUsage.system - previousCpuUsage.system;
132
+ const timeDelta = (currentTimestamp - previousCpuTimestamp) * 1000; // Convert ms to microseconds
133
+ previousCpuUsage = currentCpuUsage;
134
+ previousCpuTimestamp = currentTimestamp;
135
+ if (timeDelta === 0)
136
+ return 0;
137
+ const totalCpuDelta = userDelta + systemDelta;
138
+ const cpuPercentage = (totalCpuDelta / timeDelta) * 100;
139
+ return Math.min(100, Math.max(0, cpuPercentage));
140
+ };
141
+ /**
142
+ * Helper: Get memory usage
143
+ */
144
+ const getMemoryUsage = () => {
145
+ const totalMemory = safeTotalMemory();
146
+ const freeMemory = safeFreeMemory();
147
+ const usedMemory = totalMemory - freeMemory;
148
+ const usage = totalMemory > 0 ? (usedMemory / totalMemory) * 100 : 0;
149
+ return {
150
+ total: totalMemory,
151
+ used: usedMemory,
152
+ free: freeMemory,
153
+ usage,
154
+ };
155
+ };
156
+ /**
157
+ * Helper: Capture resource snapshot
158
+ */
159
+ const captureSnapshot = () => {
160
+ const cpuUsage = calculateCpuUsage();
161
+ const memoryUsage = getMemoryUsage();
162
+ const loadAverage = safeLoadAverage();
163
+ const cpuCores = safeCpuCount();
164
+ return {
165
+ timestamp: new Date(),
166
+ cpu: {
167
+ usage: cpuUsage,
168
+ loadAverage,
169
+ cores: cpuCores,
170
+ },
171
+ memory: memoryUsage,
172
+ disk: {
173
+ read: 0, // Would need platform-specific implementation
174
+ write: 0,
175
+ },
176
+ network: {
177
+ received: 0, // Would need platform-specific implementation
178
+ transmitted: 0,
179
+ },
180
+ process: {
181
+ pid: process.pid,
182
+ uptime: process.uptime(),
183
+ memoryUsage: process.memoryUsage(),
184
+ cpuUsage: process.cpuUsage(),
185
+ },
186
+ };
187
+ };
188
+ /**
189
+ * Helper: Calculate cost based on resource usage
190
+ */
191
+ const calculateCost = (snapshot, useSpotDiscount = false) => {
192
+ const { cpu, memory } = snapshot;
193
+ // CPU cost (based on cores and usage)
194
+ const cpuCostPerHour = cpu.cores * (cpu.usage / 100) * costConfig.computeCostPerCoreHour;
195
+ // Memory cost (based on GB used)
196
+ const memoryGB = memory.used / (1024 * 1024 * 1024);
197
+ const memoryCostPerHour = memoryGB * costConfig.memoryCostPerGBHour;
198
+ // Total compute cost
199
+ let totalCostPerHour = cpuCostPerHour + memoryCostPerHour;
200
+ // Apply spot instance discount if applicable
201
+ if (useSpotDiscount) {
202
+ totalCostPerHour *= 1 - costConfig.spotInstanceDiscount / 100;
203
+ }
204
+ return {
205
+ perHour: totalCostPerHour,
206
+ perDay: totalCostPerHour * 24,
207
+ perMonth: totalCostPerHour * 24 * 30,
208
+ };
209
+ };
210
+ /**
211
+ * Helper: Calculate efficiency score
212
+ */
213
+ const calculateEfficiency = (snapshot) => {
214
+ const { cpu, memory } = snapshot;
215
+ // CPU efficiency: 50-80% usage is ideal
216
+ let cpuEfficiency;
217
+ if (cpu.usage < 30) {
218
+ cpuEfficiency = cpu.usage * 2; // Under-utilized
219
+ }
220
+ else if (cpu.usage > 80) {
221
+ cpuEfficiency = 100 - (cpu.usage - 80) * 2; // Over-utilized
222
+ }
223
+ else {
224
+ cpuEfficiency = 100; // Ideal range
225
+ }
226
+ // Memory efficiency: 50-75% usage is ideal
227
+ let memoryEfficiency;
228
+ if (memory.usage < 40) {
229
+ memoryEfficiency = memory.usage * 1.5; // Under-utilized
230
+ }
231
+ else if (memory.usage > 75) {
232
+ memoryEfficiency = 100 - (memory.usage - 75) * 2; // Over-utilized
233
+ }
234
+ else {
235
+ memoryEfficiency = 100; // Ideal range
236
+ }
237
+ const overallScore = cpuEfficiency * 0.6 + memoryEfficiency * 0.4;
238
+ return {
239
+ cpuEfficiency: Math.round(cpuEfficiency),
240
+ memoryEfficiency: Math.round(memoryEfficiency),
241
+ overallScore: Math.round(overallScore),
242
+ };
243
+ };
244
+ /**
245
+ * Helper: Check thresholds and create alerts
246
+ */
247
+ const checkThresholds = (workerName, snapshot, cost) => {
248
+ const alerts = [];
249
+ // CPU alerts
250
+ if (snapshot.cpu.usage >= THRESHOLDS.cpu.critical) {
251
+ alerts.push({
252
+ timestamp: new Date(),
253
+ workerName,
254
+ alertType: 'cpu-high',
255
+ severity: 'critical',
256
+ message: `Critical CPU usage: ${snapshot.cpu.usage.toFixed(1)}%`,
257
+ currentValue: snapshot.cpu.usage,
258
+ threshold: THRESHOLDS.cpu.critical,
259
+ recommendation: 'Consider scaling up or optimizing worker code',
260
+ });
261
+ }
262
+ else if (snapshot.cpu.usage >= THRESHOLDS.cpu.warning) {
263
+ alerts.push({
264
+ timestamp: new Date(),
265
+ workerName,
266
+ alertType: 'cpu-high',
267
+ severity: 'warning',
268
+ message: `High CPU usage: ${snapshot.cpu.usage.toFixed(1)}%`,
269
+ currentValue: snapshot.cpu.usage,
270
+ threshold: THRESHOLDS.cpu.warning,
271
+ recommendation: 'Monitor closely and consider scaling',
272
+ });
273
+ }
274
+ // Memory alerts
275
+ if (snapshot.memory.usage >= THRESHOLDS.memory.critical) {
276
+ alerts.push({
277
+ timestamp: new Date(),
278
+ workerName,
279
+ alertType: 'memory-high',
280
+ severity: 'critical',
281
+ message: `Critical memory usage: ${snapshot.memory.usage.toFixed(1)}%`,
282
+ currentValue: snapshot.memory.usage,
283
+ threshold: THRESHOLDS.memory.critical,
284
+ recommendation: 'Increase memory allocation or optimize memory usage',
285
+ });
286
+ }
287
+ else if (snapshot.memory.usage >= THRESHOLDS.memory.warning) {
288
+ alerts.push({
289
+ timestamp: new Date(),
290
+ workerName,
291
+ alertType: 'memory-high',
292
+ severity: 'warning',
293
+ message: `High memory usage: ${snapshot.memory.usage.toFixed(1)}%`,
294
+ currentValue: snapshot.memory.usage,
295
+ threshold: THRESHOLDS.memory.warning,
296
+ recommendation: 'Monitor memory consumption',
297
+ });
298
+ }
299
+ // Cost alerts
300
+ if (cost.perHour >= THRESHOLDS.costPerHour.critical) {
301
+ alerts.push({
302
+ timestamp: new Date(),
303
+ workerName,
304
+ alertType: 'cost-high',
305
+ severity: 'critical',
306
+ message: `Critical hourly cost: $${cost.perHour.toFixed(2)}/hr`,
307
+ currentValue: cost.perHour,
308
+ threshold: THRESHOLDS.costPerHour.critical,
309
+ recommendation: 'Review resource allocation and consider cost optimization',
310
+ });
311
+ }
312
+ else if (cost.perHour >= THRESHOLDS.costPerHour.warning) {
313
+ alerts.push({
314
+ timestamp: new Date(),
315
+ workerName,
316
+ alertType: 'cost-high',
317
+ severity: 'warning',
318
+ message: `High hourly cost: $${cost.perHour.toFixed(2)}/hr`,
319
+ currentValue: cost.perHour,
320
+ threshold: THRESHOLDS.costPerHour.warning,
321
+ recommendation: 'Consider using spot instances or reducing concurrency',
322
+ });
323
+ }
324
+ return alerts;
325
+ };
326
+ /**
327
+ * Helper: Store alert
328
+ */
329
+ const storeAlert = (alert) => {
330
+ let history = alertHistory.get(alert.workerName);
331
+ if (!history) {
332
+ history = [];
333
+ alertHistory.set(alert.workerName, history);
334
+ }
335
+ history.push(alert);
336
+ // Keep only last 1000 alerts
337
+ if (history.length > 1000) {
338
+ history.shift();
339
+ }
340
+ Logger.warn(`Resource alert: ${alert.workerName}`, {
341
+ type: alert.alertType,
342
+ severity: alert.severity,
343
+ message: alert.message,
344
+ recommendation: alert.recommendation,
345
+ });
346
+ };
347
+ /**
348
+ * Helper: Calculate trend
349
+ */
350
+ const calculateTrend = (workerName, metric, period) => {
351
+ const history = resourceHistory.get(workerName);
352
+ if (!history || history.length < 2)
353
+ return null;
354
+ const now = Date.now();
355
+ let periodMs;
356
+ switch (period) {
357
+ case 'hour':
358
+ periodMs = 60 * 60 * 1000;
359
+ break;
360
+ case 'day':
361
+ periodMs = 24 * 60 * 60 * 1000;
362
+ break;
363
+ case 'week':
364
+ periodMs = 7 * 24 * 60 * 60 * 1000;
365
+ break;
366
+ }
367
+ // Filter snapshots within period
368
+ const periodSnapshots = history.filter((s) => now - s.timestamp.getTime() <= periodMs);
369
+ if (periodSnapshots.length < 2)
370
+ return null;
371
+ // Get metric values
372
+ const values = periodSnapshots.map((s) => {
373
+ switch (metric) {
374
+ case 'cpu':
375
+ return s.cpu.usage;
376
+ case 'memory':
377
+ return s.memory.usage;
378
+ case 'disk':
379
+ return s.disk.read + s.disk.write;
380
+ case 'network':
381
+ return s.network.received + s.network.transmitted;
382
+ case 'cost':
383
+ return calculateCost(s).perHour;
384
+ }
385
+ });
386
+ // Simple linear regression for trend
387
+ const firstValue = values[0];
388
+ const lastValue = values.at(-1) ?? values[0];
389
+ const changePercentage = ((lastValue - firstValue) / firstValue) * 100;
390
+ let trend;
391
+ if (Math.abs(changePercentage) < 5) {
392
+ trend = 'stable';
393
+ }
394
+ else if (changePercentage > 0) {
395
+ trend = 'increasing';
396
+ }
397
+ else {
398
+ trend = 'decreasing';
399
+ }
400
+ // Simple predictions (linear extrapolation)
401
+ const avgChange = (lastValue - firstValue) / periodSnapshots.length;
402
+ const predictions = {
403
+ nextHour: lastValue + avgChange * 12, // Assuming 5-min intervals
404
+ nextDay: lastValue + avgChange * 288,
405
+ nextWeek: lastValue + avgChange * 2016,
406
+ };
407
+ return {
408
+ workerName,
409
+ metric,
410
+ period,
411
+ trend,
412
+ changePercentage,
413
+ predictions,
414
+ };
415
+ };
416
+ /**
417
+ * Resource Monitor - Sealed namespace
418
+ */
419
+ export const ResourceMonitor = Object.freeze({
420
+ /**
421
+ * Initialize resource monitor
422
+ */
423
+ initialize(config) {
424
+ if (config) {
425
+ costConfig = { ...DEFAULT_COST_CONFIG, ...config };
426
+ }
427
+ Logger.info('ResourceMonitor initialized', { costConfig });
428
+ },
429
+ /**
430
+ * Check whether monitoring is running
431
+ */
432
+ isRunning() {
433
+ return monitoringInterval !== null;
434
+ },
435
+ /**
436
+ * Start monitoring
437
+ */
438
+ start(intervalSeconds = 30) {
439
+ const globalResourceMonitoring = Env.getBool('WORKER_RESOURCE_MONITORING', false);
440
+ if (!globalResourceMonitoring) {
441
+ Logger.warn('ResourceMonitor disabled (WORKER_RESOURCE_MONITORING=false)');
442
+ return;
443
+ }
444
+ if (monitoringInterval) {
445
+ Logger.warn('ResourceMonitor already running');
446
+ return;
447
+ }
448
+ // Initial snapshot
449
+ previousCpuUsage = process.cpuUsage();
450
+ previousCpuTimestamp = Date.now();
451
+ monitoringInterval = setInterval(() => {
452
+ const snapshot = captureSnapshot();
453
+ // Store snapshot for later analysis
454
+ // This would typically be saved to a time-series database
455
+ Logger.debug('Resource snapshot captured', {
456
+ cpu: snapshot.cpu.usage.toFixed(1) + '%',
457
+ memory: snapshot.memory.usage.toFixed(1) + '%',
458
+ });
459
+ }, intervalSeconds * 1000);
460
+ Logger.info('ResourceMonitor started', { intervalSeconds });
461
+ },
462
+ /**
463
+ * Stop monitoring
464
+ */
465
+ stop() {
466
+ if (monitoringInterval) {
467
+ clearInterval(monitoringInterval);
468
+ monitoringInterval = null;
469
+ Logger.info('ResourceMonitor stopped');
470
+ }
471
+ },
472
+ /**
473
+ * Get current resource usage
474
+ */
475
+ getCurrentUsage(workerName, useSpotDiscount = false) {
476
+ const snapshot = captureSnapshot();
477
+ const cost = calculateCost(snapshot, useSpotDiscount);
478
+ const efficiency = calculateEfficiency(snapshot);
479
+ // Store in history
480
+ let history = resourceHistory.get(workerName);
481
+ if (!history) {
482
+ history = [];
483
+ resourceHistory.set(workerName, history);
484
+ }
485
+ history.push(snapshot);
486
+ // Keep only last 1000 snapshots
487
+ if (history.length > 1000) {
488
+ history.shift();
489
+ }
490
+ // Check thresholds
491
+ const alerts = checkThresholds(workerName, snapshot, cost);
492
+ alerts.forEach(storeAlert);
493
+ return {
494
+ workerName,
495
+ cpu: snapshot.cpu.usage,
496
+ memory: {
497
+ number: snapshot.memory.total,
498
+ percent: snapshot.memory.usage,
499
+ used: snapshot.memory.used,
500
+ free: snapshot.memory.free,
501
+ },
502
+ cost: {
503
+ hourly: cost.perHour,
504
+ daily: cost.perDay,
505
+ },
506
+ resourceSnapshot: snapshot,
507
+ estimatedCost: cost,
508
+ efficiency,
509
+ };
510
+ },
511
+ /**
512
+ * Get resource history
513
+ */
514
+ getHistory(workerName, limit = 100) {
515
+ const history = resourceHistory.get(workerName) ?? [];
516
+ return history.slice(-limit).map((s) => ({ ...s }));
517
+ },
518
+ /**
519
+ * Get alerts
520
+ */
521
+ getAlerts(workerName, limit = 100) {
522
+ const history = alertHistory.get(workerName) ?? [];
523
+ return history.slice(-limit).map((a) => ({ ...a }));
524
+ },
525
+ /**
526
+ * Get trend analysis
527
+ */
528
+ getTrend(workerName, metric, period) {
529
+ return calculateTrend(workerName, metric, period);
530
+ },
531
+ /**
532
+ * Get all trends
533
+ */
534
+ getAllTrends(workerName, period) {
535
+ return {
536
+ cpu: calculateTrend(workerName, 'cpu', period),
537
+ memory: calculateTrend(workerName, 'memory', period),
538
+ disk: calculateTrend(workerName, 'disk', period),
539
+ network: calculateTrend(workerName, 'network', period),
540
+ cost: calculateTrend(workerName, 'cost', period),
541
+ };
542
+ },
543
+ /**
544
+ * Update cost configuration
545
+ */
546
+ updateCostConfig(config) {
547
+ costConfig = { ...costConfig, ...config };
548
+ Logger.info('Resource monitor cost config updated', { costConfig });
549
+ },
550
+ /**
551
+ * Get cost configuration
552
+ */
553
+ getCostConfig() {
554
+ return { ...costConfig };
555
+ },
556
+ /**
557
+ * Calculate projected cost
558
+ */
559
+ calculateProjectedCost(cpuUsagePercent, memoryGB, hoursPerDay, useSpotDiscount = false) {
560
+ const cpuCores = safeCpuCount();
561
+ const cpuCostPerHour = cpuCores * (cpuUsagePercent / 100) * costConfig.computeCostPerCoreHour;
562
+ const memoryCostPerHour = memoryGB * costConfig.memoryCostPerGBHour;
563
+ let totalCostPerHour = cpuCostPerHour + memoryCostPerHour;
564
+ if (useSpotDiscount) {
565
+ totalCostPerHour *= 1 - costConfig.spotInstanceDiscount / 100;
566
+ }
567
+ return {
568
+ daily: totalCostPerHour * hoursPerDay,
569
+ monthly: totalCostPerHour * hoursPerDay * 30,
570
+ yearly: totalCostPerHour * hoursPerDay * 365,
571
+ };
572
+ },
573
+ /**
574
+ * Get system information
575
+ */
576
+ getSystemInfo() {
577
+ return {
578
+ platform: safePlatform(),
579
+ arch: safeArch(),
580
+ hostname: safeHostname(),
581
+ cpus: safeCpuCount(),
582
+ totalMemory: safeTotalMemory(),
583
+ freeMemory: safeFreeMemory(),
584
+ uptime: safeUptime(),
585
+ };
586
+ },
587
+ /**
588
+ * Clear history for a worker
589
+ */
590
+ clearHistory(workerName) {
591
+ resourceHistory.delete(workerName);
592
+ alertHistory.delete(workerName);
593
+ Logger.info(`Cleared resource history for ${workerName}`);
594
+ },
595
+ /**
596
+ * Shutdown
597
+ */
598
+ shutdown() {
599
+ ResourceMonitor.stop();
600
+ resourceHistory.clear();
601
+ alertHistory.clear();
602
+ Logger.info('ResourceMonitor shutdown complete');
603
+ },
604
+ });
605
+ // Graceful shutdown handled by WorkerShutdown
@@ -0,0 +1,110 @@
1
+ /**
2
+ * SLA Monitor
3
+ * SLA compliance checks and violation tracking for workers
4
+ * Sealed namespace for immutability
5
+ */
6
+ export type ITimeRange = {
7
+ start: Date;
8
+ end: Date;
9
+ };
10
+ export interface ISLAConfig {
11
+ workerName: string;
12
+ metrics: {
13
+ maxLatencyP99: number;
14
+ minThroughput: number;
15
+ minAvailability: number;
16
+ maxErrorRate: number;
17
+ maxRecoveryTime: number;
18
+ };
19
+ alerting: {
20
+ channels: string[];
21
+ escalation: boolean;
22
+ cooldown: number;
23
+ };
24
+ reporting: {
25
+ interval: 'daily' | 'weekly' | 'monthly';
26
+ recipients: string[];
27
+ };
28
+ }
29
+ export type ISLAStatus = {
30
+ workerName: string;
31
+ status: 'compliant' | 'warning' | 'breach';
32
+ evaluatedAt: Date;
33
+ checks: {
34
+ latencyP99: {
35
+ value: number;
36
+ threshold: number;
37
+ status: 'pass' | 'warn' | 'fail';
38
+ };
39
+ throughput: {
40
+ value: number;
41
+ threshold: number;
42
+ status: 'pass' | 'warn' | 'fail';
43
+ };
44
+ availability: {
45
+ value: number;
46
+ threshold: number;
47
+ status: 'pass' | 'warn' | 'fail';
48
+ };
49
+ errorRate: {
50
+ value: number;
51
+ threshold: number;
52
+ status: 'pass' | 'warn' | 'fail';
53
+ };
54
+ recoveryTime: {
55
+ value: number;
56
+ threshold: number;
57
+ status: 'pass' | 'warn' | 'fail';
58
+ };
59
+ };
60
+ };
61
+ export type ISLAViolation = {
62
+ id: string;
63
+ workerName: string;
64
+ metric: keyof ISLAStatus['checks'];
65
+ expected: number;
66
+ actual: number;
67
+ timestamp: Date;
68
+ severity: 'warning' | 'critical';
69
+ message: string;
70
+ };
71
+ export type ISLAReport = {
72
+ generatedAt: Date;
73
+ period: ITimeRange;
74
+ totalWorkers: number;
75
+ totalChecks: number;
76
+ totalViolations: number;
77
+ complianceRate: number;
78
+ violations: ReadonlyArray<ISLAViolation>;
79
+ perWorker: Array<{
80
+ workerName: string;
81
+ violations: number;
82
+ complianceRate: number;
83
+ }>;
84
+ };
85
+ /**
86
+ * SLA Monitor - Sealed namespace
87
+ */
88
+ export declare const SLAMonitor: Readonly<{
89
+ /**
90
+ * Define SLA for a worker
91
+ */
92
+ defineSLA(config: ISLAConfig): void;
93
+ /**
94
+ * Check SLA compliance for a worker
95
+ */
96
+ checkCompliance(workerName: string): Promise<ISLAStatus>;
97
+ /**
98
+ * Get SLA violations for a worker
99
+ */
100
+ getViolations(workerName: string, timeRange: ITimeRange): ReadonlyArray<ISLAViolation>;
101
+ /**
102
+ * Get SLA compliance report
103
+ */
104
+ getComplianceReport(timeRange: ITimeRange): ISLAReport;
105
+ /**
106
+ * Alert on SLA violation
107
+ */
108
+ alertOnViolation(violation: ISLAViolation): void;
109
+ }>;
110
+ export default SLAMonitor;