@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.
- package/.turbo/turbo-build.log +3 -0
- package/README.md +568 -0
- package/dist/detectors/__tests__/cold-start-threshold.test.d.ts +2 -0
- package/dist/detectors/__tests__/cold-start-threshold.test.d.ts.map +1 -0
- package/dist/detectors/__tests__/cold-start-threshold.test.js +156 -0
- package/dist/detectors/__tests__/cold-start-threshold.test.js.map +1 -0
- package/dist/detectors/__tests__/dynamic-route-candidate.test.d.ts +2 -0
- package/dist/detectors/__tests__/dynamic-route-candidate.test.d.ts.map +1 -0
- package/dist/detectors/__tests__/dynamic-route-candidate.test.js +318 -0
- package/dist/detectors/__tests__/dynamic-route-candidate.test.js.map +1 -0
- package/dist/detectors/__tests__/fetch-no-cache.test.d.ts +2 -0
- package/dist/detectors/__tests__/fetch-no-cache.test.d.ts.map +1 -0
- package/dist/detectors/__tests__/fetch-no-cache.test.js +199 -0
- package/dist/detectors/__tests__/fetch-no-cache.test.js.map +1 -0
- package/dist/detectors/base-detector.d.ts +17 -0
- package/dist/detectors/base-detector.d.ts.map +1 -0
- package/dist/detectors/base-detector.js +50 -0
- package/dist/detectors/base-detector.js.map +1 -0
- package/dist/detectors/cold-start-threshold.detector.d.ts +11 -0
- package/dist/detectors/cold-start-threshold.detector.d.ts.map +1 -0
- package/dist/detectors/cold-start-threshold.detector.js +87 -0
- package/dist/detectors/cold-start-threshold.detector.js.map +1 -0
- package/dist/detectors/dynamic-route-candidate.detector.d.ts +23 -0
- package/dist/detectors/dynamic-route-candidate.detector.d.ts.map +1 -0
- package/dist/detectors/dynamic-route-candidate.detector.js +96 -0
- package/dist/detectors/dynamic-route-candidate.detector.js.map +1 -0
- package/dist/detectors/fetch-no-cache.detector.d.ts +12 -0
- package/dist/detectors/fetch-no-cache.detector.d.ts.map +1 -0
- package/dist/detectors/fetch-no-cache.detector.js +178 -0
- package/dist/detectors/fetch-no-cache.detector.js.map +1 -0
- package/dist/detectors/index.d.ts +28 -0
- package/dist/detectors/index.d.ts.map +1 -0
- package/dist/detectors/index.js +97 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/types.d.ts +32 -0
- package/dist/detectors/types.d.ts.map +1 -0
- package/dist/detectors/types.js +2 -0
- package/dist/detectors/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +133 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +363 -0
- package/dist/init.js.map +1 -0
- package/dist/middleware.d.ts +10 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +61 -0
- package/dist/middleware.js.map +1 -0
- package/dist/optimization.d.ts +43 -0
- package/dist/optimization.d.ts.map +1 -0
- package/dist/optimization.js +139 -0
- package/dist/optimization.js.map +1 -0
- package/dist/system-monitor.d.ts +124 -0
- package/dist/system-monitor.d.ts.map +1 -0
- package/dist/system-monitor.js +221 -0
- package/dist/system-monitor.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/src/detectors/__tests__/cold-start-threshold.test.ts +183 -0
- package/src/detectors/__tests__/dynamic-route-candidate.test.ts +365 -0
- package/src/detectors/__tests__/fetch-no-cache.test.ts +239 -0
- package/src/detectors/base-detector.ts +69 -0
- package/src/detectors/cold-start-threshold.detector.ts +95 -0
- package/src/detectors/dynamic-route-candidate.detector.ts +107 -0
- package/src/detectors/fetch-no-cache.detector.ts +204 -0
- package/src/detectors/index.ts +127 -0
- package/src/detectors/types.ts +38 -0
- package/src/index.ts +60 -0
- package/src/init.ts +424 -0
- package/src/middleware.ts +75 -0
- package/src/optimization.ts +164 -0
- package/src/system-monitor.ts +295 -0
- package/src/types.ts +66 -0
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { BaseDetector } from './base-detector.js';
|
|
2
|
+
export class FetchNoCacheDetector extends BaseDetector {
|
|
3
|
+
id = 'FETCH_NO_CACHE';
|
|
4
|
+
name = 'Fetch Without Cache Detector';
|
|
5
|
+
minDurationMs = 50;
|
|
6
|
+
nPlus1Threshold = 3;
|
|
7
|
+
detect(spans, context) {
|
|
8
|
+
const issues = [];
|
|
9
|
+
// Find fetch spans without cache directive
|
|
10
|
+
const fetchSpans = spans.filter(span => {
|
|
11
|
+
const name = span.name.toLowerCase();
|
|
12
|
+
return name.includes('fetch') || name.includes('http.client');
|
|
13
|
+
});
|
|
14
|
+
const noCacheFetches = [];
|
|
15
|
+
const urlCounts = new Map();
|
|
16
|
+
fetchSpans.forEach(span => {
|
|
17
|
+
const method = this.getSpanMethod(span);
|
|
18
|
+
const url = this.getSpanUrl(span);
|
|
19
|
+
// Ignore non-GET and non-POST (POST/PUT/DELETE shouldn't be cached anyway)
|
|
20
|
+
if (!method || !['GET', 'HEAD'].includes(method.toUpperCase())) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!url) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// Ignore internal URLs
|
|
27
|
+
if (this.isInternalUrl(url)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Check cache directive
|
|
31
|
+
const cacheAttr = this.getStringAttribute(span, 'fetch.cache');
|
|
32
|
+
const nextRevalidate = this.getNumberAttribute(span, 'next.revalidate');
|
|
33
|
+
// Has cache if:
|
|
34
|
+
// - has fetch.cache='force-cache' or 'force-revalidate'
|
|
35
|
+
// - has next.revalidate > 0
|
|
36
|
+
const hasCache = cacheAttr === 'force-cache' ||
|
|
37
|
+
cacheAttr === 'force-revalidate' ||
|
|
38
|
+
(nextRevalidate !== undefined && nextRevalidate > 0);
|
|
39
|
+
if (hasCache) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const duration = this.getSpanDurationMs(span);
|
|
43
|
+
if (duration < this.minDurationMs) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const fetchInfo = {
|
|
47
|
+
url,
|
|
48
|
+
duration,
|
|
49
|
+
spanId: span.spanContext().spanId,
|
|
50
|
+
};
|
|
51
|
+
noCacheFetches.push(fetchInfo);
|
|
52
|
+
// Track for N+1 detection
|
|
53
|
+
const existing = urlCounts.get(url);
|
|
54
|
+
if (existing) {
|
|
55
|
+
existing.push(fetchInfo);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
urlCounts.set(url, [fetchInfo]);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Report individual fetches and group N+1s
|
|
62
|
+
urlCounts.forEach((fetches, url) => {
|
|
63
|
+
if (fetches.length >= this.nPlus1Threshold) {
|
|
64
|
+
// N+1 detected
|
|
65
|
+
issues.push({
|
|
66
|
+
id: this.id,
|
|
67
|
+
severity: 'critical',
|
|
68
|
+
message: `Fetch "${url}" called ${fetches.length}x with no cache → likely fetch N+1 pattern`,
|
|
69
|
+
suggestion: `This endpoint is being called multiple times without caching. Add a cache directive:
|
|
70
|
+
|
|
71
|
+
// Option 1: Force cache (recommended for static data)
|
|
72
|
+
fetch("${url}", { cache: 'force-cache' })
|
|
73
|
+
|
|
74
|
+
// Option 2: Revalidate after time (recommended for semi-dynamic data)
|
|
75
|
+
fetch("${url}", {
|
|
76
|
+
next: { revalidate: 3600 } // revalidate every hour
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// Option 3: Use server-side data fetching instead
|
|
80
|
+
// Move to a parent Server Component or Route Handler
|
|
81
|
+
|
|
82
|
+
// Option 4: Use unstable_cache wrapper (experimental)
|
|
83
|
+
import { unstable_cache } from 'next/cache';
|
|
84
|
+
const cachedFetch = unstable_cache(
|
|
85
|
+
async () => fetch("${url}").then(r => r.json()),
|
|
86
|
+
[${JSON.stringify(url)}],
|
|
87
|
+
{ revalidate: 3600 }
|
|
88
|
+
);`,
|
|
89
|
+
route: context.route,
|
|
90
|
+
spanId: fetches[0]?.spanId,
|
|
91
|
+
attributes: {
|
|
92
|
+
url,
|
|
93
|
+
callCount: fetches.length,
|
|
94
|
+
totalDuration: Math.round(fetches.reduce((sum, f) => sum + f.duration, 0)),
|
|
95
|
+
avgDuration: Math.round(fetches.reduce((sum, f) => sum + f.duration, 0) / fetches.length),
|
|
96
|
+
},
|
|
97
|
+
detectedAt: Date.now(),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else if (fetches.length === 1) {
|
|
101
|
+
// Single slow fetch without cache
|
|
102
|
+
const fetch = fetches[0];
|
|
103
|
+
issues.push({
|
|
104
|
+
id: this.id,
|
|
105
|
+
severity: 'high',
|
|
106
|
+
message: `Fetch "${url}" has no cache → +${Math.round(fetch.duration)}ms per request`,
|
|
107
|
+
suggestion: `Add a cache directive to this fetch:
|
|
108
|
+
|
|
109
|
+
// Option 1: Force cache (best for static APIs)
|
|
110
|
+
fetch("${url}", { cache: 'force-cache' })
|
|
111
|
+
|
|
112
|
+
// Option 2: Revalidate after time (better for semi-dynamic data)
|
|
113
|
+
fetch("${url}", {
|
|
114
|
+
next: { revalidate: 3600 } // revalidate every hour
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// Option 3: Combine with other optimizations
|
|
118
|
+
const data = await fetch("${url}", {
|
|
119
|
+
cache: 'force-cache',
|
|
120
|
+
headers: {
|
|
121
|
+
'User-Agent': 'NextDoctor-Agent/1.0'
|
|
122
|
+
}
|
|
123
|
+
});`,
|
|
124
|
+
route: context.route,
|
|
125
|
+
spanId: fetch.spanId,
|
|
126
|
+
attributes: {
|
|
127
|
+
url,
|
|
128
|
+
duration: Math.round(fetch.duration),
|
|
129
|
+
},
|
|
130
|
+
detectedAt: Date.now(),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// 2 to nPlus1Threshold-1 calls: still suspicious
|
|
135
|
+
const totalDuration = Math.round(fetches.reduce((sum, f) => sum + f.duration, 0));
|
|
136
|
+
issues.push({
|
|
137
|
+
id: this.id,
|
|
138
|
+
severity: 'high',
|
|
139
|
+
message: `Fetch "${url}" called ${fetches.length}x with no cache → ${totalDuration}ms wasted per request`,
|
|
140
|
+
suggestion: `This endpoint is being called multiple times without caching. Consider adding a cache directive or deduplicating the request:
|
|
141
|
+
|
|
142
|
+
// Option 1: Force cache
|
|
143
|
+
fetch("${url}", { cache: 'force-cache' })
|
|
144
|
+
|
|
145
|
+
// Option 2: Revalidate after time
|
|
146
|
+
fetch("${url}", { next: { revalidate: 3600 } })`,
|
|
147
|
+
route: context.route,
|
|
148
|
+
spanId: fetches[0]?.spanId,
|
|
149
|
+
attributes: {
|
|
150
|
+
url,
|
|
151
|
+
callCount: fetches.length,
|
|
152
|
+
totalDuration,
|
|
153
|
+
avgDuration: Math.round(totalDuration / fetches.length),
|
|
154
|
+
},
|
|
155
|
+
detectedAt: Date.now(),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return issues;
|
|
160
|
+
}
|
|
161
|
+
isInternalUrl(url) {
|
|
162
|
+
try {
|
|
163
|
+
const parsed = new URL(url);
|
|
164
|
+
const hostname = parsed.hostname;
|
|
165
|
+
return (hostname === 'localhost' ||
|
|
166
|
+
hostname === '127.0.0.1' ||
|
|
167
|
+
hostname === '::1' ||
|
|
168
|
+
hostname.endsWith('.local') ||
|
|
169
|
+
hostname.endsWith('.test') ||
|
|
170
|
+
hostname.startsWith('192.168.') ||
|
|
171
|
+
hostname.startsWith('10.'));
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=fetch-no-cache.detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-no-cache.detector.js","sourceRoot":"","sources":["../../src/detectors/fetch-no-cache.detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base';
|
|
2
|
+
import { BaseDetector } from './base-detector.js';
|
|
3
|
+
import type { DetectedIssue, DetectorContext } from './types.js';
|
|
4
|
+
export declare class DetectionEngine {
|
|
5
|
+
private detectors;
|
|
6
|
+
private issueCache;
|
|
7
|
+
private readonly dedupWindowMs;
|
|
8
|
+
constructor(config?: {
|
|
9
|
+
disabledDetectors?: string[];
|
|
10
|
+
});
|
|
11
|
+
analyzeSpans(spans: ReadableSpan[], context: DetectorContext): DetectedIssue[];
|
|
12
|
+
private deduplicateIssues;
|
|
13
|
+
private getDeduplicationKey;
|
|
14
|
+
getDetectorById(id: string): BaseDetector | undefined;
|
|
15
|
+
listDetectors(): Array<{
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
}>;
|
|
19
|
+
clearCache(): void;
|
|
20
|
+
getCacheSize(): number;
|
|
21
|
+
}
|
|
22
|
+
export declare const detectionEngine: DetectionEngine;
|
|
23
|
+
export type { DetectedIssue, DetectorContext, DetectorResult } from './types.js';
|
|
24
|
+
export { BaseDetector } from './base-detector.js';
|
|
25
|
+
export { ColdStartThresholdDetector } from './cold-start-threshold.detector.js';
|
|
26
|
+
export { FetchNoCacheDetector } from './fetch-no-cache.detector.js';
|
|
27
|
+
export { DynamicRouteCandidateDetector } from './dynamic-route-candidate.detector.js';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIlD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAuC,MAAM,YAAY,CAAC;AAEtG,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;gBAE5B,MAAM,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAarD,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,eAAe,GAAG,aAAa,EAAE;IAuB9E,OAAO,CAAC,iBAAiB;IAuCzB,OAAO,CAAC,mBAAmB;IAQ3B,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIrD,aAAa,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAOpD,UAAU,IAAI,IAAI;IAIlB,YAAY,IAAI,MAAM;CAGvB;AAMD,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAGrD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { ColdStartThresholdDetector } from './cold-start-threshold.detector.js';
|
|
2
|
+
import { FetchNoCacheDetector } from './fetch-no-cache.detector.js';
|
|
3
|
+
import { DynamicRouteCandidateDetector } from './dynamic-route-candidate.detector.js';
|
|
4
|
+
export class DetectionEngine {
|
|
5
|
+
detectors;
|
|
6
|
+
issueCache = new Map();
|
|
7
|
+
dedupWindowMs = 60_000; // 60 seconds
|
|
8
|
+
constructor(config) {
|
|
9
|
+
const disabledSet = new Set(config?.disabledDetectors || []);
|
|
10
|
+
// Instantiate all detectors
|
|
11
|
+
const allDetectors = [
|
|
12
|
+
new ColdStartThresholdDetector(),
|
|
13
|
+
new FetchNoCacheDetector(),
|
|
14
|
+
new DynamicRouteCandidateDetector(),
|
|
15
|
+
];
|
|
16
|
+
this.detectors = allDetectors.filter(d => !disabledSet.has(d.id));
|
|
17
|
+
}
|
|
18
|
+
analyzeSpans(spans, context) {
|
|
19
|
+
const allIssues = [];
|
|
20
|
+
// Run all detectors
|
|
21
|
+
for (const detector of this.detectors) {
|
|
22
|
+
const result = detector.run(spans, context);
|
|
23
|
+
allIssues.push(...result.issues);
|
|
24
|
+
}
|
|
25
|
+
// Deduplicate within the window
|
|
26
|
+
const deduped = this.deduplicateIssues(allIssues);
|
|
27
|
+
// Sort by severity: critical > high > warning > info
|
|
28
|
+
const severityOrder = { critical: 0, high: 1, warning: 2, info: 3 };
|
|
29
|
+
deduped.sort((a, b) => severityOrder[a.severity] -
|
|
30
|
+
severityOrder[b.severity]);
|
|
31
|
+
return deduped;
|
|
32
|
+
}
|
|
33
|
+
deduplicateIssues(issues) {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const dedupedMap = new Map();
|
|
36
|
+
// Clean old entries from cache
|
|
37
|
+
for (const [key, cached] of this.issueCache.entries()) {
|
|
38
|
+
if (now - cached.lastDetectedAt > this.dedupWindowMs) {
|
|
39
|
+
this.issueCache.delete(key);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Process new issues
|
|
43
|
+
for (const issue of issues) {
|
|
44
|
+
const key = this.getDeduplicationKey(issue);
|
|
45
|
+
const existingCached = this.issueCache.get(key);
|
|
46
|
+
if (existingCached) {
|
|
47
|
+
// Update cache
|
|
48
|
+
existingCached.lastDetectedAt = now;
|
|
49
|
+
existingCached.count++;
|
|
50
|
+
// Don't duplicate in output if already reported recently
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// New issue - add to cache and output
|
|
54
|
+
const dedupedIssue = {
|
|
55
|
+
...issue,
|
|
56
|
+
firstDetectedAt: now,
|
|
57
|
+
lastDetectedAt: now,
|
|
58
|
+
count: 1,
|
|
59
|
+
};
|
|
60
|
+
this.issueCache.set(key, dedupedIssue);
|
|
61
|
+
dedupedMap.set(key, dedupedIssue);
|
|
62
|
+
}
|
|
63
|
+
return Array.from(dedupedMap.values());
|
|
64
|
+
}
|
|
65
|
+
getDeduplicationKey(issue) {
|
|
66
|
+
const key = {
|
|
67
|
+
id: issue.id,
|
|
68
|
+
route: issue.route,
|
|
69
|
+
};
|
|
70
|
+
return JSON.stringify(key);
|
|
71
|
+
}
|
|
72
|
+
getDetectorById(id) {
|
|
73
|
+
return this.detectors.find(d => d.id === id);
|
|
74
|
+
}
|
|
75
|
+
listDetectors() {
|
|
76
|
+
return this.detectors.map(d => ({
|
|
77
|
+
id: d.id,
|
|
78
|
+
name: d.name,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
clearCache() {
|
|
82
|
+
this.issueCache.clear();
|
|
83
|
+
}
|
|
84
|
+
getCacheSize() {
|
|
85
|
+
return this.issueCache.size;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Singleton instance
|
|
89
|
+
// MVP LIMITATION: In persistent Node.js environments (self-hosted), this cache
|
|
90
|
+
// is shared globally. Deduplication keys include 'id' and 'route', but lack
|
|
91
|
+
// project-level scope, which could cause cache collisions in multi-tenant usages.
|
|
92
|
+
export const detectionEngine = new DetectionEngine();
|
|
93
|
+
export { BaseDetector } from './base-detector.js';
|
|
94
|
+
export { ColdStartThresholdDetector } from './cold-start-threshold.detector.js';
|
|
95
|
+
export { FetchNoCacheDetector } from './fetch-no-cache.detector.js';
|
|
96
|
+
export { DynamicRouteCandidateDetector } from './dynamic-route-candidate.detector.js';
|
|
97
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detectors/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type IssueSeverity = 'info' | 'warning' | 'high' | 'critical';
|
|
2
|
+
export interface DetectedIssue {
|
|
3
|
+
id: string;
|
|
4
|
+
severity: IssueSeverity;
|
|
5
|
+
message: string;
|
|
6
|
+
suggestion: string;
|
|
7
|
+
route?: string;
|
|
8
|
+
spanId?: string;
|
|
9
|
+
attributes?: Record<string, unknown>;
|
|
10
|
+
detectedAt: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DetectorResult {
|
|
13
|
+
issues: DetectedIssue[];
|
|
14
|
+
detectorId: string;
|
|
15
|
+
analyzedSpans: number;
|
|
16
|
+
durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
export interface DetectorContext {
|
|
19
|
+
route?: string;
|
|
20
|
+
runtime: 'nodejs' | 'edge';
|
|
21
|
+
startupTimeMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface IssueDeduplicationKey {
|
|
24
|
+
id: string;
|
|
25
|
+
route?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DedupedIssue extends DetectedIssue {
|
|
28
|
+
firstDetectedAt: number;
|
|
29
|
+
lastDetectedAt: number;
|
|
30
|
+
count: number;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/detectors/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/detectors/types.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { initNextDoctor, shutdownNextDoctor, getNextDoctorAgent, reportMetric, getHealthStatus, getDetectedIssues, getSystemMetrics, getSystemHealth, getSystemSummary, } from './init.js';
|
|
2
|
+
export type { NextDoctorConfig, DetectedIssue, AgentHealth, RetryPolicy, ExporterConfig, } from './types.js';
|
|
3
|
+
export { LogLevel, ExporterType, } from './types.js';
|
|
4
|
+
export { withNextDoctorMonitoring, withNextDoctorTiming, } from './middleware.js';
|
|
5
|
+
export { IntelligentSampler, BatchProcessor, CircuitBreaker, } from './optimization.js';
|
|
6
|
+
export { SystemMonitor, CPUMonitor, MemoryMonitor, } from './system-monitor.js';
|
|
7
|
+
export type { CPUMetrics, MemoryMetrics, SystemMetrics, } from './system-monitor.js';
|
|
8
|
+
export { detectionEngine, ColdStartThresholdDetector, FetchNoCacheDetector, DynamicRouteCandidateDetector, } from './detectors/index.js';
|
|
9
|
+
export type { DetectorContext, DetectorResult, IssueSeverity, } from './detectors/types.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,QAAQ,EACR,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,UAAU,EACV,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,UAAU,EACV,aAAa,EACb,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { initNextDoctor, shutdownNextDoctor, getNextDoctorAgent, reportMetric, getHealthStatus, getDetectedIssues, getSystemMetrics, getSystemHealth, getSystemSummary, } from './init.js';
|
|
2
|
+
export { LogLevel, ExporterType, } from './types.js';
|
|
3
|
+
export { withNextDoctorMonitoring, withNextDoctorTiming, } from './middleware.js';
|
|
4
|
+
export { IntelligentSampler, BatchProcessor, CircuitBreaker, } from './optimization.js';
|
|
5
|
+
export { SystemMonitor, CPUMonitor, MemoryMonitor, } from './system-monitor.js';
|
|
6
|
+
export { detectionEngine, ColdStartThresholdDetector, FetchNoCacheDetector, DynamicRouteCandidateDetector, } from './detectors/index.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAUnB,OAAO,EACL,QAAQ,EACR,YAAY,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,UAAU,EACV,aAAa,GACd,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EACL,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,EACpB,6BAA6B,GAC9B,MAAM,sBAAsB,CAAC"}
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { NextDoctorConfig, AgentHealth, DetectedIssue } from './types.js';
|
|
2
|
+
import { type SystemMetrics } from './system-monitor.js';
|
|
3
|
+
declare class NextDoctorAgent {
|
|
4
|
+
private sdk;
|
|
5
|
+
private config;
|
|
6
|
+
private systemMonitor;
|
|
7
|
+
private health;
|
|
8
|
+
private retryPolicy;
|
|
9
|
+
private logLevel;
|
|
10
|
+
private initialized;
|
|
11
|
+
private detectedIssues;
|
|
12
|
+
private spansBuffer;
|
|
13
|
+
private lastAnalysisTime;
|
|
14
|
+
private readonly analysisIntervalMs;
|
|
15
|
+
private startTime;
|
|
16
|
+
constructor(config: NextDoctorConfig);
|
|
17
|
+
private validateConfig;
|
|
18
|
+
private log;
|
|
19
|
+
private createTraceExporter;
|
|
20
|
+
private createResource;
|
|
21
|
+
private generateInstanceId;
|
|
22
|
+
private isVercelEnvironment;
|
|
23
|
+
initialize(): Promise<void>;
|
|
24
|
+
private analyzeSpan;
|
|
25
|
+
private runDetectionEngine;
|
|
26
|
+
shutdown(): Promise<void>;
|
|
27
|
+
getHealth(): AgentHealth;
|
|
28
|
+
getDetectedIssues(): DetectedIssue[];
|
|
29
|
+
clearDetectedIssues(): void;
|
|
30
|
+
reportCustomMetric(name: string, value: number, attributes?: Record<string, any>): void;
|
|
31
|
+
private getUptime;
|
|
32
|
+
getSystemMetrics(): SystemMetrics;
|
|
33
|
+
getSystemHealth(cpuThreshold?: number, memThreshold?: number): {
|
|
34
|
+
healthy: boolean;
|
|
35
|
+
warnings: string[];
|
|
36
|
+
metrics: SystemMetrics;
|
|
37
|
+
};
|
|
38
|
+
getSystemSummary(): {
|
|
39
|
+
status: string;
|
|
40
|
+
cpu: {
|
|
41
|
+
usage: string;
|
|
42
|
+
cores: number;
|
|
43
|
+
load: {
|
|
44
|
+
oneMinute: number;
|
|
45
|
+
fiveMinutes: number;
|
|
46
|
+
fifteenMinutes: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
memory: {
|
|
50
|
+
heap: {
|
|
51
|
+
used: string;
|
|
52
|
+
total: string;
|
|
53
|
+
usage: string;
|
|
54
|
+
};
|
|
55
|
+
system: {
|
|
56
|
+
used: string;
|
|
57
|
+
total: string;
|
|
58
|
+
usage: string;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
warnings: string[];
|
|
62
|
+
};
|
|
63
|
+
getStats(): {
|
|
64
|
+
uptime: number;
|
|
65
|
+
initialized: boolean;
|
|
66
|
+
health: AgentHealth;
|
|
67
|
+
detectedIssues: DetectedIssue[];
|
|
68
|
+
system: {
|
|
69
|
+
status: string;
|
|
70
|
+
cpu: {
|
|
71
|
+
usage: string;
|
|
72
|
+
cores: number;
|
|
73
|
+
load: {
|
|
74
|
+
oneMinute: number;
|
|
75
|
+
fiveMinutes: number;
|
|
76
|
+
fifteenMinutes: number;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
memory: {
|
|
80
|
+
heap: {
|
|
81
|
+
used: string;
|
|
82
|
+
total: string;
|
|
83
|
+
usage: string;
|
|
84
|
+
};
|
|
85
|
+
system: {
|
|
86
|
+
used: string;
|
|
87
|
+
total: string;
|
|
88
|
+
usage: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
warnings: string[];
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export declare function initNextDoctor(config: NextDoctorConfig): Promise<void>;
|
|
96
|
+
export declare function shutdownNextDoctor(): Promise<void>;
|
|
97
|
+
export declare function getNextDoctorAgent(): NextDoctorAgent | null;
|
|
98
|
+
export declare function reportMetric(name: string, value: number, attributes?: Record<string, any>): void;
|
|
99
|
+
export declare function getHealthStatus(): AgentHealth | null;
|
|
100
|
+
export declare function getDetectedIssues(): DetectedIssue[];
|
|
101
|
+
export declare function getSystemMetrics(): SystemMetrics | null;
|
|
102
|
+
export declare function getSystemHealth(cpuThreshold?: number, memThreshold?: number): {
|
|
103
|
+
healthy: boolean;
|
|
104
|
+
warnings: string[];
|
|
105
|
+
metrics: SystemMetrics;
|
|
106
|
+
} | null;
|
|
107
|
+
export declare function getSystemSummary(): {
|
|
108
|
+
status: string;
|
|
109
|
+
cpu: {
|
|
110
|
+
usage: string;
|
|
111
|
+
cores: number;
|
|
112
|
+
load: {
|
|
113
|
+
oneMinute: number;
|
|
114
|
+
fiveMinutes: number;
|
|
115
|
+
fifteenMinutes: number;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
memory: {
|
|
119
|
+
heap: {
|
|
120
|
+
used: string;
|
|
121
|
+
total: string;
|
|
122
|
+
usage: string;
|
|
123
|
+
};
|
|
124
|
+
system: {
|
|
125
|
+
used: string;
|
|
126
|
+
total: string;
|
|
127
|
+
usage: string;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
warnings: string[];
|
|
131
|
+
} | null;
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAGhB,WAAW,EACX,aAAa,EAEd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGxE,cAAM,eAAe;IACnB,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAMZ;IACF,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,gBAAgB,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAC3C,OAAO,CAAC,SAAS,CAAc;gBAEnB,MAAM,EAAE,gBAAgB;IA0BpC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,GAAG;IAaX,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,mBAAmB;IAOrB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsEjC,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,kBAAkB;IA2CpB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB/B,SAAS,IAAI,WAAW;IAOxB,iBAAiB,IAAI,aAAa,EAAE;IAIpC,mBAAmB,IAAI,IAAI;IAI3B,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAkBvF,OAAO,CAAC,SAAS;IAIjB,gBAAgB,IAAI,aAAa;IAIjC,eAAe,CAAC,YAAY,GAAE,MAAW,EAAE,YAAY,GAAE,MAAW;;;;;IAIpE,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;IAIhB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAST;AAKD,wBAAsB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5E;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQxD;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,IAAI,CAE3D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAOhG;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAEpD;AAED,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CAEnD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAEvD;AAED,wBAAgB,eAAe,CAAC,YAAY,GAAE,MAAW,EAAE,YAAY,GAAE,MAAW;;;;SAOnF;AAED,wBAAgB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;SAO/B"}
|