@codebaz/nextdoctor-agent 0.1.0-beta.1

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 (80) hide show
  1. package/.turbo/turbo-build.log +3 -0
  2. package/README.md +568 -0
  3. package/dist/detectors/__tests__/cold-start-threshold.test.d.ts +2 -0
  4. package/dist/detectors/__tests__/cold-start-threshold.test.d.ts.map +1 -0
  5. package/dist/detectors/__tests__/cold-start-threshold.test.js +156 -0
  6. package/dist/detectors/__tests__/cold-start-threshold.test.js.map +1 -0
  7. package/dist/detectors/__tests__/dynamic-route-candidate.test.d.ts +2 -0
  8. package/dist/detectors/__tests__/dynamic-route-candidate.test.d.ts.map +1 -0
  9. package/dist/detectors/__tests__/dynamic-route-candidate.test.js +318 -0
  10. package/dist/detectors/__tests__/dynamic-route-candidate.test.js.map +1 -0
  11. package/dist/detectors/__tests__/fetch-no-cache.test.d.ts +2 -0
  12. package/dist/detectors/__tests__/fetch-no-cache.test.d.ts.map +1 -0
  13. package/dist/detectors/__tests__/fetch-no-cache.test.js +199 -0
  14. package/dist/detectors/__tests__/fetch-no-cache.test.js.map +1 -0
  15. package/dist/detectors/base-detector.d.ts +17 -0
  16. package/dist/detectors/base-detector.d.ts.map +1 -0
  17. package/dist/detectors/base-detector.js +50 -0
  18. package/dist/detectors/base-detector.js.map +1 -0
  19. package/dist/detectors/cold-start-threshold.detector.d.ts +11 -0
  20. package/dist/detectors/cold-start-threshold.detector.d.ts.map +1 -0
  21. package/dist/detectors/cold-start-threshold.detector.js +87 -0
  22. package/dist/detectors/cold-start-threshold.detector.js.map +1 -0
  23. package/dist/detectors/dynamic-route-candidate.detector.d.ts +23 -0
  24. package/dist/detectors/dynamic-route-candidate.detector.d.ts.map +1 -0
  25. package/dist/detectors/dynamic-route-candidate.detector.js +96 -0
  26. package/dist/detectors/dynamic-route-candidate.detector.js.map +1 -0
  27. package/dist/detectors/fetch-no-cache.detector.d.ts +12 -0
  28. package/dist/detectors/fetch-no-cache.detector.d.ts.map +1 -0
  29. package/dist/detectors/fetch-no-cache.detector.js +178 -0
  30. package/dist/detectors/fetch-no-cache.detector.js.map +1 -0
  31. package/dist/detectors/index.d.ts +28 -0
  32. package/dist/detectors/index.d.ts.map +1 -0
  33. package/dist/detectors/index.js +97 -0
  34. package/dist/detectors/index.js.map +1 -0
  35. package/dist/detectors/types.d.ts +32 -0
  36. package/dist/detectors/types.d.ts.map +1 -0
  37. package/dist/detectors/types.js +2 -0
  38. package/dist/detectors/types.js.map +1 -0
  39. package/dist/index.d.ts +10 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +7 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/init.d.ts +133 -0
  44. package/dist/init.d.ts.map +1 -0
  45. package/dist/init.js +363 -0
  46. package/dist/init.js.map +1 -0
  47. package/dist/middleware.d.ts +10 -0
  48. package/dist/middleware.d.ts.map +1 -0
  49. package/dist/middleware.js +61 -0
  50. package/dist/middleware.js.map +1 -0
  51. package/dist/optimization.d.ts +43 -0
  52. package/dist/optimization.d.ts.map +1 -0
  53. package/dist/optimization.js +139 -0
  54. package/dist/optimization.js.map +1 -0
  55. package/dist/system-monitor.d.ts +124 -0
  56. package/dist/system-monitor.d.ts.map +1 -0
  57. package/dist/system-monitor.js +221 -0
  58. package/dist/system-monitor.js.map +1 -0
  59. package/dist/types.d.ts +61 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +14 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +55 -0
  64. package/src/detectors/__tests__/cold-start-threshold.test.ts +183 -0
  65. package/src/detectors/__tests__/dynamic-route-candidate.test.ts +365 -0
  66. package/src/detectors/__tests__/fetch-no-cache.test.ts +239 -0
  67. package/src/detectors/base-detector.ts +69 -0
  68. package/src/detectors/cold-start-threshold.detector.ts +95 -0
  69. package/src/detectors/dynamic-route-candidate.detector.ts +107 -0
  70. package/src/detectors/fetch-no-cache.detector.ts +204 -0
  71. package/src/detectors/index.ts +127 -0
  72. package/src/detectors/types.ts +38 -0
  73. package/src/index.ts +60 -0
  74. package/src/init.ts +424 -0
  75. package/src/middleware.ts +75 -0
  76. package/src/optimization.ts +164 -0
  77. package/src/system-monitor.ts +295 -0
  78. package/src/types.ts +66 -0
  79. package/tsconfig.json +11 -0
  80. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,295 @@
1
+ import { cpus, loadavg, totalmem, freemem } from 'os';
2
+ import { performance } from 'perf_hooks';
3
+ import type { LogLevel } from './types.js';
4
+
5
+ export interface CPUMetrics {
6
+ timestamp: number;
7
+ usage: number; // percentage 0-100
8
+ loadAverage: {
9
+ oneMinute: number;
10
+ fiveMinutes: number;
11
+ fifteenMinutes: number;
12
+ };
13
+ coreCount: number;
14
+ systemLoadPerCore: number;
15
+ }
16
+
17
+ export interface MemoryMetrics {
18
+ timestamp: number;
19
+ heapUsed: number; // bytes
20
+ heapTotal: number; // bytes
21
+ external: number; // bytes
22
+ arrayBuffers: number; // bytes
23
+ heapUsagePercent: number;
24
+ systemMemoryUsed: number;
25
+ systemMemoryTotal: number;
26
+ systemMemoryUsagePercent: number;
27
+ }
28
+
29
+ export interface SystemMetrics {
30
+ cpu: CPUMetrics;
31
+ memory: MemoryMetrics;
32
+ uptime: number;
33
+ }
34
+
35
+ /**
36
+ * CPU Monitor - Real-time CPU usage tracking
37
+ */
38
+ export class CPUMonitor {
39
+ private static readonly SAMPLE_INTERVAL = 100; // ms
40
+ private lastCPUTimes: number[] = [];
41
+ private lastSampleTime = performance.now();
42
+ private logFn?: (level: LogLevel, message: string, meta?: any) => void;
43
+
44
+ constructor(logFn?: (level: LogLevel, message: string, meta?: any) => void) {
45
+ this.logFn = logFn;
46
+ this.initializeBaseline();
47
+ }
48
+
49
+ private initializeBaseline(): void {
50
+ const cpus_info = cpus();
51
+ this.lastCPUTimes = cpus_info.map((cpu) => {
52
+ return (
53
+ cpu.times.user +
54
+ cpu.times.sys +
55
+ cpu.times.idle +
56
+ cpu.times.irq
57
+ );
58
+ });
59
+ }
60
+
61
+ /**
62
+ * Calcula o uso de CPU em percentual
63
+ */
64
+ getCPUUsage(): CPUMetrics {
65
+ const cpus_info = cpus();
66
+ const coreCount = cpus_info.length;
67
+ const [one, five, fifteen] = loadavg();
68
+
69
+ // Calculate average CPU usage across all cores
70
+ let totalUsage = 0;
71
+
72
+ cpus_info.forEach((cpu, index) => {
73
+ const currentTime =
74
+ cpu.times.user +
75
+ cpu.times.sys +
76
+ cpu.times.idle +
77
+ cpu.times.irq;
78
+
79
+ const lastTime = this.lastCPUTimes[index] || currentTime;
80
+ const timeDiff = currentTime - lastTime;
81
+
82
+ if (timeDiff > 0) {
83
+ const userTime = cpu.times.user - (this.lastCPUTimes[index] || 0);
84
+ const systemTime = cpu.times.sys - (this.lastCPUTimes[index] || 0);
85
+ const usage = ((userTime + systemTime) / timeDiff) * 100;
86
+ totalUsage += Math.min(100, Math.max(0, usage));
87
+ }
88
+
89
+ this.lastCPUTimes[index] = currentTime;
90
+ });
91
+
92
+ const averageUsage = totalUsage / coreCount;
93
+ const systemLoadPerCore = one! / coreCount;
94
+
95
+ return {
96
+ timestamp: Date.now(),
97
+ usage: Math.round(averageUsage * 100) / 100,
98
+ loadAverage: {
99
+ oneMinute: Math.round(one! * 100) / 100,
100
+ fiveMinutes: Math.round(five! * 100) / 100,
101
+ fifteenMinutes: Math.round(fifteen! * 100) / 100,
102
+ },
103
+ coreCount,
104
+ systemLoadPerCore: Math.round(systemLoadPerCore * 100) / 100,
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Monitora CPU e alerta se exceder threshold
110
+ */
111
+ checkCPUThreshold(threshold: number = 80): { exceeded: boolean; usage: number } {
112
+ const metrics = this.getCPUUsage();
113
+ const exceeded = metrics.usage > threshold;
114
+
115
+ if (exceeded && this.logFn) {
116
+ // @ts-ignore
117
+ this.logFn(2, `CPU usage exceeded threshold: ${metrics.usage}% > ${threshold}%`, {
118
+ usage: metrics.usage,
119
+ threshold,
120
+ cores: metrics.coreCount,
121
+ systemLoad: metrics.loadAverage,
122
+ });
123
+ }
124
+
125
+ return {
126
+ exceeded,
127
+ usage: metrics.usage,
128
+ };
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Memory Monitor - Real-time memory usage tracking
134
+ */
135
+ export class MemoryMonitor {
136
+ private logFn?: (level: LogLevel, message: string, meta?: any) => void;
137
+
138
+ constructor(logFn?: (level: LogLevel, message: string, meta?: any) => void) {
139
+ this.logFn = logFn;
140
+ }
141
+
142
+ /**
143
+ * Obtém métricas de memória
144
+ */
145
+ getMemoryMetrics(): MemoryMetrics {
146
+ const memUsage = process.memoryUsage();
147
+ const systemTotal = totalmem();
148
+ const systemFree = freemem();
149
+ const systemUsed = systemTotal - systemFree;
150
+
151
+ const heapUsagePercent = (memUsage.heapUsed / memUsage.heapTotal) * 100;
152
+ const systemMemoryUsagePercent = (systemUsed / systemTotal) * 100;
153
+
154
+ return {
155
+ timestamp: Date.now(),
156
+ heapUsed: memUsage.heapUsed,
157
+ heapTotal: memUsage.heapTotal,
158
+ external: memUsage.external,
159
+ arrayBuffers: memUsage.arrayBuffers || 0,
160
+ heapUsagePercent: Math.round(heapUsagePercent * 100) / 100,
161
+ systemMemoryUsed: systemUsed,
162
+ systemMemoryTotal: systemTotal,
163
+ systemMemoryUsagePercent: Math.round(systemMemoryUsagePercent * 100) / 100,
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Verifica se memória excedeu threshold
169
+ */
170
+ checkMemoryThreshold(threshold: number = 85): {
171
+ heapExceeded: boolean;
172
+ systemExceeded: boolean;
173
+ metrics: MemoryMetrics;
174
+ } {
175
+ const metrics = this.getMemoryMetrics();
176
+ const heapExceeded = metrics.heapUsagePercent > threshold;
177
+ const systemExceeded = metrics.systemMemoryUsagePercent > threshold;
178
+
179
+ if ((heapExceeded || systemExceeded) && this.logFn) {
180
+ // @ts-ignore
181
+ this.logFn(2, 'Memory threshold exceeded', {
182
+ heap: `${metrics.heapUsagePercent}% (${Math.round(metrics.heapUsed / 1024 / 1024)}MB)`,
183
+ system: `${metrics.systemMemoryUsagePercent}% (${Math.round(metrics.systemMemoryUsed / 1024 / 1024 / 1024)}GB)`,
184
+ threshold,
185
+ });
186
+ }
187
+
188
+ return {
189
+ heapExceeded,
190
+ systemExceeded,
191
+ metrics,
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Formata bytes para string legível
197
+ */
198
+ formatBytes(bytes: number): string {
199
+ if (bytes === 0) return '0 B';
200
+ const k = 1024;
201
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
202
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
203
+ return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
204
+ }
205
+ }
206
+
207
+ /**
208
+ * System Monitor - Unified system metrics collector
209
+ */
210
+ export class SystemMonitor {
211
+ private cpuMonitor: CPUMonitor;
212
+ private memoryMonitor: MemoryMonitor;
213
+ private startTime = Date.now();
214
+ private logFn?: (level: LogLevel, message: string, meta?: any) => void;
215
+
216
+ constructor(logFn?: (level: LogLevel, message: string, meta?: any) => void) {
217
+ this.logFn = logFn;
218
+ this.cpuMonitor = new CPUMonitor(logFn);
219
+ this.memoryMonitor = new MemoryMonitor(logFn);
220
+ }
221
+
222
+ /**
223
+ * Coleta todas as métricas do sistema
224
+ */
225
+ getSystemMetrics(): SystemMetrics {
226
+ return {
227
+ cpu: this.cpuMonitor.getCPUUsage(),
228
+ memory: this.memoryMonitor.getMemoryMetrics(),
229
+ uptime: Date.now() - this.startTime,
230
+ };
231
+ }
232
+
233
+ /**
234
+ * Monitora saúde geral do sistema
235
+ */
236
+ getSystemHealth(cpuThreshold: number = 80, memThreshold: number = 85): {
237
+ healthy: boolean;
238
+ warnings: string[];
239
+ metrics: SystemMetrics;
240
+ } {
241
+ const metrics = this.getSystemMetrics();
242
+ const warnings: string[] = [];
243
+
244
+ const { exceeded: cpuExceeded, usage: cpuUsage } = this.cpuMonitor.checkCPUThreshold(cpuThreshold);
245
+ const { heapExceeded, systemExceeded } = this.memoryMonitor.checkMemoryThreshold(memThreshold);
246
+
247
+ if (cpuExceeded) {
248
+ warnings.push(`High CPU usage: ${cpuUsage}% (threshold: ${cpuThreshold}%)`);
249
+ }
250
+
251
+ if (heapExceeded) {
252
+ warnings.push(`High heap memory: ${metrics.memory.heapUsagePercent}% (threshold: ${memThreshold}%)`);
253
+ }
254
+
255
+ if (systemExceeded) {
256
+ warnings.push(`High system memory: ${metrics.memory.systemMemoryUsagePercent}% (threshold: ${memThreshold}%)`);
257
+ }
258
+
259
+ return {
260
+ healthy: warnings.length === 0,
261
+ warnings,
262
+ metrics,
263
+ };
264
+ }
265
+
266
+ /**
267
+ * Dashboard-friendly summary
268
+ */
269
+ getSummary() {
270
+ const metrics = this.getSystemMetrics();
271
+ const health = this.getSystemHealth();
272
+
273
+ return {
274
+ status: health.healthy ? 'healthy' : 'warning',
275
+ cpu: {
276
+ usage: `${metrics.cpu.usage}%`,
277
+ cores: metrics.cpu.coreCount,
278
+ load: metrics.cpu.loadAverage,
279
+ },
280
+ memory: {
281
+ heap: {
282
+ used: this.memoryMonitor.formatBytes(metrics.memory.heapUsed),
283
+ total: this.memoryMonitor.formatBytes(metrics.memory.heapTotal),
284
+ usage: `${metrics.memory.heapUsagePercent}%`,
285
+ },
286
+ system: {
287
+ used: this.memoryMonitor.formatBytes(metrics.memory.systemMemoryUsed),
288
+ total: this.memoryMonitor.formatBytes(metrics.memory.systemMemoryTotal),
289
+ usage: `${metrics.memory.systemMemoryUsagePercent}%`,
290
+ },
291
+ },
292
+ warnings: health.warnings,
293
+ };
294
+ }
295
+ }
package/src/types.ts ADDED
@@ -0,0 +1,66 @@
1
+ export enum LogLevel {
2
+ DEBUG = 0,
3
+ INFO = 1,
4
+ WARN = 2,
5
+ ERROR = 3,
6
+ }
7
+
8
+ export enum ExporterType {
9
+ OTLP_HTTP = 'otlp-http',
10
+ VERCEL = 'vercel',
11
+ NONE = 'none',
12
+ }
13
+
14
+ export interface RetryPolicy {
15
+ maxRetries: number;
16
+ initialDelayMs: number;
17
+ maxDelayMs: number;
18
+ backoffMultiplier: number;
19
+ randomizationFactor: number;
20
+ }
21
+
22
+ export interface ExporterConfig {
23
+ type: ExporterType;
24
+ url?: string;
25
+ headers?: Record<string, string>;
26
+ batchSize?: number;
27
+ batchTimeoutMs?: number;
28
+ }
29
+
30
+ export interface NextDoctorConfig {
31
+ projectToken: string;
32
+ endpoint: string;
33
+ enabled?: boolean;
34
+ serviceName?: string;
35
+ version?: string;
36
+ environment?: 'development' | 'staging' | 'production';
37
+ logLevel?: LogLevel;
38
+ exporter?: ExporterConfig;
39
+ retryPolicy?: Partial<RetryPolicy>;
40
+ captureLogs?: boolean;
41
+ captureMetrics?: boolean;
42
+ captureExceptions?: boolean;
43
+ samplingRate?: number; // 0.0 to 1.0
44
+ enableDebugLogging?: boolean;
45
+ timeout?: number; // ms
46
+ }
47
+
48
+ export interface DetectedIssue {
49
+ id: string;
50
+ severity: 'info' | 'warning' | 'high' | 'critical';
51
+ message: string;
52
+ suggestion: string;
53
+ route?: string;
54
+ spanId?: string;
55
+ attributes?: Record<string, unknown>;
56
+ detectedAt: number;
57
+ }
58
+
59
+ export interface AgentHealth {
60
+ initialized: boolean;
61
+ isHealthy: boolean;
62
+ lastHealthCheckAt?: number;
63
+ exporterStatus: 'healthy' | 'degraded' | 'unreachable';
64
+ bufferedSpans: number;
65
+ errorCount: number;
66
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "@workspace/typescript-config/base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "declaration": true,
7
+ "sourceMap": true,
8
+ "types": ["node"]
9
+ },
10
+ "include": ["src"]
11
+ }
@@ -0,0 +1 @@
1
+ {"root":["./src/index.ts","./src/init.ts","./src/middleware.ts","./src/optimization.ts","./src/system-monitor.ts","./src/types.ts","./src/detectors/base-detector.ts","./src/detectors/cold-start-threshold.detector.ts","./src/detectors/dynamic-route-candidate.detector.ts","./src/detectors/fetch-no-cache.detector.ts","./src/detectors/index.ts","./src/detectors/types.ts","./src/detectors/__tests__/cold-start-threshold.test.ts","./src/detectors/__tests__/dynamic-route-candidate.test.ts","./src/detectors/__tests__/fetch-no-cache.test.ts"],"version":"5.9.3"}