vaspera 2.10.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.js +188 -0
- package/dist/__tests__/scanners/ai-code/ai-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js +363 -0
- package/dist/__tests__/scanners/ai-code/confidence-scorer.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js +226 -0
- package/dist/__tests__/scanners/ai-code/hallucination-checker.test.js.map +1 -0
- package/dist/__tests__/scanners/ai-code/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/ai-code/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/ai-code/index.test.js +214 -0
- package/dist/__tests__/scanners/ai-code/index.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.js +67 -0
- package/dist/__tests__/scanners/deploy/health-checker.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/index.test.js +84 -0
- package/dist/__tests__/scanners/deploy/index.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.js +88 -0
- package/dist/__tests__/scanners/deploy/provider-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/deploy/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/deploy/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/deploy/types.test.js +126 -0
- package/dist/__tests__/scanners/deploy/types.test.js.map +1 -0
- package/dist/__tests__/scanners/fp-feedback.test.js +1 -1
- package/dist/__tests__/scanners/fp-feedback.test.js.map +1 -1
- package/dist/__tests__/scanners/fp-tracker.test.js +1 -1
- package/dist/__tests__/scanners/fp-tracker.test.js.map +1 -1
- package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.js +94 -0
- package/dist/__tests__/scanners/runtime/app-launcher.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js +195 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/index.test.js +120 -0
- package/dist/__tests__/scanners/runtime/index.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/runtime/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/runtime/types.test.js +126 -0
- package/dist/__tests__/scanners/runtime/types.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.js +187 -0
- package/dist/__tests__/scanners/scale/bottleneck-detector.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/index.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/index.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/index.test.js +87 -0
- package/dist/__tests__/scanners/scale/index.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.js +122 -0
- package/dist/__tests__/scanners/scale/load-profiler.test.js.map +1 -0
- package/dist/__tests__/scanners/scale/types.test.d.ts +2 -0
- package/dist/__tests__/scanners/scale/types.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/scale/types.test.js +129 -0
- package/dist/__tests__/scanners/scale/types.test.js.map +1 -0
- package/dist/action/pr-comment.test.js +8 -0
- package/dist/action/pr-comment.test.js.map +1 -1
- package/dist/action/sarif-upload.test.js +8 -0
- package/dist/action/sarif-upload.test.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +874 -0
- package/dist/index.js.map +1 -1
- package/dist/install-skills.d.ts +11 -0
- package/dist/install-skills.d.ts.map +1 -0
- package/dist/install-skills.js +81 -0
- package/dist/install-skills.js.map +1 -0
- package/dist/scanners/ai-code/ai-detector.d.ts +25 -0
- package/dist/scanners/ai-code/ai-detector.d.ts.map +1 -0
- package/dist/scanners/ai-code/ai-detector.js +192 -0
- package/dist/scanners/ai-code/ai-detector.js.map +1 -0
- package/dist/scanners/ai-code/confidence-scorer.d.ts +40 -0
- package/dist/scanners/ai-code/confidence-scorer.d.ts.map +1 -0
- package/dist/scanners/ai-code/confidence-scorer.js +148 -0
- package/dist/scanners/ai-code/confidence-scorer.js.map +1 -0
- package/dist/scanners/ai-code/hallucination-checker.d.ts +36 -0
- package/dist/scanners/ai-code/hallucination-checker.d.ts.map +1 -0
- package/dist/scanners/ai-code/hallucination-checker.js +298 -0
- package/dist/scanners/ai-code/hallucination-checker.js.map +1 -0
- package/dist/scanners/ai-code/index.d.ts +30 -0
- package/dist/scanners/ai-code/index.d.ts.map +1 -0
- package/dist/scanners/ai-code/index.js +224 -0
- package/dist/scanners/ai-code/index.js.map +1 -0
- package/dist/scanners/ai-code/types.d.ts +192 -0
- package/dist/scanners/ai-code/types.d.ts.map +1 -0
- package/dist/scanners/ai-code/types.js +37 -0
- package/dist/scanners/ai-code/types.js.map +1 -0
- package/dist/scanners/cache.d.ts.map +1 -1
- package/dist/scanners/cache.js +8 -0
- package/dist/scanners/cache.js.map +1 -1
- package/dist/scanners/dast.d.ts +40 -0
- package/dist/scanners/dast.d.ts.map +1 -0
- package/dist/scanners/dast.js +228 -0
- package/dist/scanners/dast.js.map +1 -0
- package/dist/scanners/deploy/health-checker.d.ts +38 -0
- package/dist/scanners/deploy/health-checker.d.ts.map +1 -0
- package/dist/scanners/deploy/health-checker.js +272 -0
- package/dist/scanners/deploy/health-checker.js.map +1 -0
- package/dist/scanners/deploy/index.d.ts +44 -0
- package/dist/scanners/deploy/index.d.ts.map +1 -0
- package/dist/scanners/deploy/index.js +208 -0
- package/dist/scanners/deploy/index.js.map +1 -0
- package/dist/scanners/deploy/provider-detector.d.ts +25 -0
- package/dist/scanners/deploy/provider-detector.d.ts.map +1 -0
- package/dist/scanners/deploy/provider-detector.js +177 -0
- package/dist/scanners/deploy/provider-detector.js.map +1 -0
- package/dist/scanners/deploy/types.d.ts +406 -0
- package/dist/scanners/deploy/types.d.ts.map +1 -0
- package/dist/scanners/deploy/types.js +58 -0
- package/dist/scanners/deploy/types.js.map +1 -0
- package/dist/scanners/deploy/vercel-integration.d.ts +52 -0
- package/dist/scanners/deploy/vercel-integration.d.ts.map +1 -0
- package/dist/scanners/deploy/vercel-integration.js +280 -0
- package/dist/scanners/deploy/vercel-integration.js.map +1 -0
- package/dist/scanners/index.d.ts +4 -4
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +133 -15
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/index.test.js +6 -6
- package/dist/scanners/index.test.js.map +1 -1
- package/dist/scanners/openapi.d.ts +20 -0
- package/dist/scanners/openapi.d.ts.map +1 -0
- package/dist/scanners/openapi.js +226 -0
- package/dist/scanners/openapi.js.map +1 -0
- package/dist/scanners/runtime/app-launcher.d.ts +33 -0
- package/dist/scanners/runtime/app-launcher.d.ts.map +1 -0
- package/dist/scanners/runtime/app-launcher.js +419 -0
- package/dist/scanners/runtime/app-launcher.js.map +1 -0
- package/dist/scanners/runtime/golden-path-runner.d.ts +48 -0
- package/dist/scanners/runtime/golden-path-runner.d.ts.map +1 -0
- package/dist/scanners/runtime/golden-path-runner.js +373 -0
- package/dist/scanners/runtime/golden-path-runner.js.map +1 -0
- package/dist/scanners/runtime/index.d.ts +41 -0
- package/dist/scanners/runtime/index.d.ts.map +1 -0
- package/dist/scanners/runtime/index.js +164 -0
- package/dist/scanners/runtime/index.js.map +1 -0
- package/dist/scanners/runtime/playwright-executor.d.ts +50 -0
- package/dist/scanners/runtime/playwright-executor.d.ts.map +1 -0
- package/dist/scanners/runtime/playwright-executor.js +387 -0
- package/dist/scanners/runtime/playwright-executor.js.map +1 -0
- package/dist/scanners/runtime/types.d.ts +215 -0
- package/dist/scanners/runtime/types.d.ts.map +1 -0
- package/dist/scanners/runtime/types.js +40 -0
- package/dist/scanners/runtime/types.js.map +1 -0
- package/dist/scanners/rust.d.ts +22 -0
- package/dist/scanners/rust.d.ts.map +1 -0
- package/dist/scanners/rust.js +239 -0
- package/dist/scanners/rust.js.map +1 -0
- package/dist/scanners/scale/bottleneck-detector.d.ts +17 -0
- package/dist/scanners/scale/bottleneck-detector.d.ts.map +1 -0
- package/dist/scanners/scale/bottleneck-detector.js +250 -0
- package/dist/scanners/scale/bottleneck-detector.js.map +1 -0
- package/dist/scanners/scale/capacity-estimator.d.ts +17 -0
- package/dist/scanners/scale/capacity-estimator.d.ts.map +1 -0
- package/dist/scanners/scale/capacity-estimator.js +197 -0
- package/dist/scanners/scale/capacity-estimator.js.map +1 -0
- package/dist/scanners/scale/index.d.ts +37 -0
- package/dist/scanners/scale/index.d.ts.map +1 -0
- package/dist/scanners/scale/index.js +101 -0
- package/dist/scanners/scale/index.js.map +1 -0
- package/dist/scanners/scale/load-profiler.d.ts +48 -0
- package/dist/scanners/scale/load-profiler.d.ts.map +1 -0
- package/dist/scanners/scale/load-profiler.js +377 -0
- package/dist/scanners/scale/load-profiler.js.map +1 -0
- package/dist/scanners/scale/types.d.ts +529 -0
- package/dist/scanners/scale/types.d.ts.map +1 -0
- package/dist/scanners/scale/types.js +57 -0
- package/dist/scanners/scale/types.js.map +1 -0
- package/dist/scanners/secrets.d.ts.map +1 -1
- package/dist/scanners/secrets.js +13 -2
- package/dist/scanners/secrets.js.map +1 -1
- package/dist/scanners/terraform.d.ts +23 -0
- package/dist/scanners/terraform.d.ts.map +1 -0
- package/dist/scanners/terraform.js +207 -0
- package/dist/scanners/terraform.js.map +1 -0
- package/dist/scanners/types.d.ts +1 -1
- package/dist/scanners/types.d.ts.map +1 -1
- package/dist/scanners/types.js +8 -0
- package/dist/scanners/types.js.map +1 -1
- package/package.json +4 -2
- package/skills/vaspera-add-tests/SKILL.md +102 -0
- package/skills/vaspera-ai-verify/SKILL.md +166 -0
- package/skills/vaspera-audit/SKILL.md +67 -0
- package/skills/vaspera-certify/SKILL.md +130 -0
- package/skills/vaspera-deploy/SKILL.md +152 -0
- package/skills/vaspera-fix-critical/SKILL.md +52 -0
- package/skills/vaspera-fix-high/SKILL.md +81 -0
- package/skills/vaspera-fix-medium/SKILL.md +56 -0
- package/skills/vaspera-fix-rls/SKILL.md +85 -0
- package/skills/vaspera-harden/SKILL.md +102 -0
- package/skills/vaspera-help/SKILL.md +61 -0
- package/skills/vaspera-load-test/SKILL.md +167 -0
- package/skills/vaspera-verify/SKILL.md +70 -0
- package/skills/vaspera-verify-e2e/SKILL.md +117 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capacity Estimator
|
|
3
|
+
*
|
|
4
|
+
* Estimates maximum capacity and projects costs based on load test results.
|
|
5
|
+
*
|
|
6
|
+
* @module scanners/scale/capacity-estimator
|
|
7
|
+
*/
|
|
8
|
+
import { logger } from "../../logger.js";
|
|
9
|
+
/**
|
|
10
|
+
* Instance type pricing (approximate monthly costs)
|
|
11
|
+
*/
|
|
12
|
+
const INSTANCE_PRICING = {
|
|
13
|
+
// AWS EC2 (us-east-1)
|
|
14
|
+
"t3.micro": { cpu: 2, memory: 1, price: 8 },
|
|
15
|
+
"t3.small": { cpu: 2, memory: 2, price: 15 },
|
|
16
|
+
"t3.medium": { cpu: 2, memory: 4, price: 30 },
|
|
17
|
+
"t3.large": { cpu: 2, memory: 8, price: 60 },
|
|
18
|
+
"t3.xlarge": { cpu: 4, memory: 16, price: 120 },
|
|
19
|
+
"m5.large": { cpu: 2, memory: 8, price: 70 },
|
|
20
|
+
"m5.xlarge": { cpu: 4, memory: 16, price: 140 },
|
|
21
|
+
"m5.2xlarge": { cpu: 8, memory: 32, price: 280 },
|
|
22
|
+
// Vercel (approximate)
|
|
23
|
+
"vercel-hobby": { cpu: 1, memory: 1, price: 0 },
|
|
24
|
+
"vercel-pro": { cpu: 1, memory: 1, price: 20 },
|
|
25
|
+
"vercel-enterprise": { cpu: 4, memory: 4, price: 500 },
|
|
26
|
+
// Railway
|
|
27
|
+
"railway-starter": { cpu: 1, memory: 0.5, price: 5 },
|
|
28
|
+
"railway-pro": { cpu: 2, memory: 2, price: 20 },
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Estimate breakpoint (where system starts failing)
|
|
32
|
+
*/
|
|
33
|
+
function estimateBreakpoint(loadTestResult) {
|
|
34
|
+
// Use Little's Law and observed metrics
|
|
35
|
+
const avgLatency = loadTestResult.summary.latency.mean;
|
|
36
|
+
const throughput = loadTestResult.summary.avgThroughput;
|
|
37
|
+
const errorRate = loadTestResult.summary.errorRate;
|
|
38
|
+
// Find the scenario with highest VUs
|
|
39
|
+
const maxVus = Math.max(...loadTestResult.scenarios.map((s) => s.vusMax));
|
|
40
|
+
// If error rate is already high, breakpoint is near current load
|
|
41
|
+
if (errorRate > 0.05) {
|
|
42
|
+
return {
|
|
43
|
+
vus: Math.round(maxVus * 0.8),
|
|
44
|
+
confidence: 0.7,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// If latency is degraded but not failing, estimate 50% more capacity
|
|
48
|
+
if (loadTestResult.summary.latency.p95 > 500) {
|
|
49
|
+
return {
|
|
50
|
+
vus: Math.round(maxVus * 1.2),
|
|
51
|
+
confidence: 0.6,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
// System handling load well, estimate 2x capacity
|
|
55
|
+
if (errorRate < 0.01 && avgLatency < 200) {
|
|
56
|
+
return {
|
|
57
|
+
vus: Math.round(maxVus * 2.5),
|
|
58
|
+
confidence: 0.5,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Default conservative estimate
|
|
62
|
+
return {
|
|
63
|
+
vus: Math.round(maxVus * 1.5),
|
|
64
|
+
confidence: 0.4,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculate maximum requests per second
|
|
69
|
+
*/
|
|
70
|
+
function estimateMaxRPS(loadTestResult) {
|
|
71
|
+
const breakpoint = estimateBreakpoint(loadTestResult);
|
|
72
|
+
const currentRPS = loadTestResult.summary.avgThroughput;
|
|
73
|
+
const currentVUs = Math.max(...loadTestResult.scenarios.map((s) => s.vusMax));
|
|
74
|
+
if (currentVUs === 0)
|
|
75
|
+
return 0;
|
|
76
|
+
// Linear extrapolation with degradation factor
|
|
77
|
+
const rpsPerVU = currentRPS / currentVUs;
|
|
78
|
+
const degradationFactor = 0.8; // Assume 20% degradation at scale
|
|
79
|
+
return Math.round(breakpoint.vus * rpsPerVU * degradationFactor);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Generate recommendations based on results
|
|
83
|
+
*/
|
|
84
|
+
function generateRecommendations(loadTestResult, bottlenecks) {
|
|
85
|
+
const recommendations = [];
|
|
86
|
+
// High latency recommendations
|
|
87
|
+
if (loadTestResult.summary.latency.p95 > 500) {
|
|
88
|
+
recommendations.push("Add application-level caching (Redis, Memcached) to reduce database load");
|
|
89
|
+
recommendations.push("Consider using a CDN for static assets and cacheable API responses");
|
|
90
|
+
}
|
|
91
|
+
// High error rate recommendations
|
|
92
|
+
if (loadTestResult.summary.errorRate > 0.01) {
|
|
93
|
+
recommendations.push("Implement circuit breakers to prevent cascade failures");
|
|
94
|
+
recommendations.push("Add rate limiting to protect against traffic spikes");
|
|
95
|
+
}
|
|
96
|
+
// Database bottlenecks
|
|
97
|
+
const dbBottlenecks = bottlenecks.filter((b) => b.type === "database");
|
|
98
|
+
if (dbBottlenecks.length > 0) {
|
|
99
|
+
recommendations.push("Optimize database queries - add indexes and use connection pooling");
|
|
100
|
+
recommendations.push("Consider read replicas for read-heavy workloads");
|
|
101
|
+
}
|
|
102
|
+
// Memory bottlenecks
|
|
103
|
+
const memBottlenecks = bottlenecks.filter((b) => b.type === "memory");
|
|
104
|
+
if (memBottlenecks.length > 0) {
|
|
105
|
+
recommendations.push("Profile memory usage and fix potential leaks");
|
|
106
|
+
recommendations.push("Consider increasing instance memory or using smaller request payloads");
|
|
107
|
+
}
|
|
108
|
+
// General scaling recommendations
|
|
109
|
+
if (loadTestResult.summary.avgThroughput < 100) {
|
|
110
|
+
recommendations.push("Consider horizontal scaling with a load balancer");
|
|
111
|
+
}
|
|
112
|
+
// Add default if no specific recommendations
|
|
113
|
+
if (recommendations.length === 0) {
|
|
114
|
+
recommendations.push("System performing well - monitor for degradation at higher loads");
|
|
115
|
+
}
|
|
116
|
+
return recommendations;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Project infrastructure costs
|
|
120
|
+
*/
|
|
121
|
+
function projectCosts(maxRPS, maxConcurrent) {
|
|
122
|
+
// Simple heuristic: 1000 RPS per m5.large
|
|
123
|
+
const rpsPerInstance = 1000;
|
|
124
|
+
const instancesNeeded = Math.ceil(maxRPS / rpsPerInstance);
|
|
125
|
+
// Choose appropriate instance type
|
|
126
|
+
let instanceType = "t3.medium";
|
|
127
|
+
if (maxConcurrent > 500)
|
|
128
|
+
instanceType = "t3.large";
|
|
129
|
+
if (maxConcurrent > 1000)
|
|
130
|
+
instanceType = "m5.large";
|
|
131
|
+
if (maxConcurrent > 5000)
|
|
132
|
+
instanceType = "m5.xlarge";
|
|
133
|
+
const pricing = INSTANCE_PRICING[instanceType];
|
|
134
|
+
return {
|
|
135
|
+
provider: "AWS",
|
|
136
|
+
instanceType,
|
|
137
|
+
instances: Math.max(2, instancesNeeded), // At least 2 for HA
|
|
138
|
+
monthlyCost: Math.max(2, instancesNeeded) * pricing.price,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Estimate capacity for a project
|
|
143
|
+
*/
|
|
144
|
+
export async function estimateCapacity(loadTestResult, bottlenecks = []) {
|
|
145
|
+
logger.info("scale.capacity_estimation_started");
|
|
146
|
+
// If no load test results, return conservative estimates
|
|
147
|
+
if (!loadTestResult) {
|
|
148
|
+
return {
|
|
149
|
+
maxConcurrentUsers: 100,
|
|
150
|
+
maxRequestsPerSecond: 50,
|
|
151
|
+
estimatedBreakpoint: {
|
|
152
|
+
vus: 200,
|
|
153
|
+
confidence: 0.2,
|
|
154
|
+
},
|
|
155
|
+
recommendations: [
|
|
156
|
+
"Run load tests to get accurate capacity estimates",
|
|
157
|
+
"Start with baseline performance monitoring",
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const breakpoint = estimateBreakpoint(loadTestResult);
|
|
162
|
+
const maxRPS = estimateMaxRPS(loadTestResult);
|
|
163
|
+
const recommendations = generateRecommendations(loadTestResult, bottlenecks);
|
|
164
|
+
const costProjection = projectCosts(maxRPS, breakpoint.vus);
|
|
165
|
+
const estimate = {
|
|
166
|
+
maxConcurrentUsers: breakpoint.vus,
|
|
167
|
+
maxRequestsPerSecond: maxRPS,
|
|
168
|
+
estimatedBreakpoint: breakpoint,
|
|
169
|
+
recommendations,
|
|
170
|
+
costProjection,
|
|
171
|
+
};
|
|
172
|
+
logger.info("scale.capacity_estimation_completed", {
|
|
173
|
+
maxConcurrent: estimate.maxConcurrentUsers,
|
|
174
|
+
maxRPS: estimate.maxRequestsPerSecond,
|
|
175
|
+
confidence: breakpoint.confidence,
|
|
176
|
+
});
|
|
177
|
+
return estimate;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Calculate capacity score (100 = excellent capacity margin)
|
|
181
|
+
*/
|
|
182
|
+
export function calculateCapacityScore(estimate, targetConcurrent = 100) {
|
|
183
|
+
// Score based on how much headroom we have
|
|
184
|
+
const headroom = estimate.maxConcurrentUsers / targetConcurrent;
|
|
185
|
+
if (headroom >= 5)
|
|
186
|
+
return 100; // 5x headroom
|
|
187
|
+
if (headroom >= 3)
|
|
188
|
+
return 90; // 3x headroom
|
|
189
|
+
if (headroom >= 2)
|
|
190
|
+
return 80; // 2x headroom
|
|
191
|
+
if (headroom >= 1.5)
|
|
192
|
+
return 70; // 1.5x headroom
|
|
193
|
+
if (headroom >= 1)
|
|
194
|
+
return 50; // Just meeting target
|
|
195
|
+
return Math.round(headroom * 50); // Below target
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=capacity-estimator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capacity-estimator.js","sourceRoot":"","sources":["../../../src/scanners/scale/capacity-estimator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scale Assessment Scanner
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates load testing, bottleneck detection, and capacity estimation.
|
|
5
|
+
* This is the entry point for M8 scale assessment capabilities.
|
|
6
|
+
*
|
|
7
|
+
* @module scanners/scale
|
|
8
|
+
*/
|
|
9
|
+
import { detectBottlenecks } from "./bottleneck-detector.js";
|
|
10
|
+
import type { ScaleAssessmentResult } from "./types.js";
|
|
11
|
+
export * from "./types.js";
|
|
12
|
+
export { detectLoadTool, discoverProfiles, runK6Test, generateSampleProfile, loadProfile, isK6Available, } from "./load-profiler.js";
|
|
13
|
+
export { detectBottlenecks, calculateBottleneckScore, } from "./bottleneck-detector.js";
|
|
14
|
+
export { estimateCapacity, calculateCapacityScore, } from "./capacity-estimator.js";
|
|
15
|
+
/**
|
|
16
|
+
* Run full scale assessment
|
|
17
|
+
*
|
|
18
|
+
* 1. Detect load testing tool
|
|
19
|
+
* 2. Discover and run load profiles
|
|
20
|
+
* 3. Detect bottlenecks
|
|
21
|
+
* 4. Estimate capacity
|
|
22
|
+
* 5. Calculate scores
|
|
23
|
+
*/
|
|
24
|
+
export declare function runScaleAssessment(projectPath: string, baseUrl: string, options?: {
|
|
25
|
+
timeout?: number;
|
|
26
|
+
profileName?: string;
|
|
27
|
+
skipLoadTest?: boolean;
|
|
28
|
+
targetConcurrent?: number;
|
|
29
|
+
}): Promise<ScaleAssessmentResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Quick bottleneck scan (no load testing)
|
|
32
|
+
*/
|
|
33
|
+
export declare function quickBottleneckScan(projectPath: string): Promise<{
|
|
34
|
+
bottlenecks: Awaited<ReturnType<typeof detectBottlenecks>>;
|
|
35
|
+
score: number;
|
|
36
|
+
}>;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/scanners/scale/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,OAAO,EACL,iBAAiB,EAElB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AAEpB,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,qBAAqB,EACrB,WAAW,EACX,aAAa,GACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACtB,GACL,OAAO,CAAC,qBAAqB,CAAC,CA8EhC;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IACT,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAKD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scale Assessment Scanner
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates load testing, bottleneck detection, and capacity estimation.
|
|
5
|
+
* This is the entry point for M8 scale assessment capabilities.
|
|
6
|
+
*
|
|
7
|
+
* @module scanners/scale
|
|
8
|
+
*/
|
|
9
|
+
import { logger } from "../../logger.js";
|
|
10
|
+
import { detectLoadTool, discoverProfiles, runK6Test, } from "./load-profiler.js";
|
|
11
|
+
import { detectBottlenecks, calculateBottleneckScore, } from "./bottleneck-detector.js";
|
|
12
|
+
import { estimateCapacity, calculateCapacityScore, } from "./capacity-estimator.js";
|
|
13
|
+
export * from "./types.js";
|
|
14
|
+
export { detectLoadTool, discoverProfiles, runK6Test, generateSampleProfile, loadProfile, isK6Available, } from "./load-profiler.js";
|
|
15
|
+
export { detectBottlenecks, calculateBottleneckScore, } from "./bottleneck-detector.js";
|
|
16
|
+
export { estimateCapacity, calculateCapacityScore, } from "./capacity-estimator.js";
|
|
17
|
+
/**
|
|
18
|
+
* Run full scale assessment
|
|
19
|
+
*
|
|
20
|
+
* 1. Detect load testing tool
|
|
21
|
+
* 2. Discover and run load profiles
|
|
22
|
+
* 3. Detect bottlenecks
|
|
23
|
+
* 4. Estimate capacity
|
|
24
|
+
* 5. Calculate scores
|
|
25
|
+
*/
|
|
26
|
+
export async function runScaleAssessment(projectPath, baseUrl, options = {}) {
|
|
27
|
+
const startTime = Date.now();
|
|
28
|
+
const { timeout = 600000, profileName, skipLoadTest = false, targetConcurrent = 100 } = options;
|
|
29
|
+
logger.info("scale.assessment_started", { projectPath, baseUrl });
|
|
30
|
+
let loadTestResult;
|
|
31
|
+
// Step 1: Run load tests if not skipped
|
|
32
|
+
if (!skipLoadTest) {
|
|
33
|
+
// Check for load testing tools
|
|
34
|
+
const tool = await detectLoadTool();
|
|
35
|
+
if (!tool) {
|
|
36
|
+
logger.warn("scale.no_load_tool", {
|
|
37
|
+
message: "No load testing tool found. Install k6 or Artillery.",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Discover profiles
|
|
42
|
+
const profiles = await discoverProfiles(projectPath);
|
|
43
|
+
if (profiles.length === 0) {
|
|
44
|
+
logger.info("scale.no_profiles_found", {
|
|
45
|
+
message: "No load profiles found. Generate one with scale_profile_generate.",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Find matching profile or use first
|
|
50
|
+
const selectedProfile = profileName
|
|
51
|
+
? profiles.find((p) => p.profile.name === profileName)
|
|
52
|
+
: profiles[0];
|
|
53
|
+
if (selectedProfile && tool === "k6") {
|
|
54
|
+
loadTestResult = await runK6Test(selectedProfile.profile, baseUrl, {
|
|
55
|
+
timeout,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Step 2: Detect bottlenecks
|
|
62
|
+
const bottlenecks = await detectBottlenecks(projectPath, loadTestResult);
|
|
63
|
+
const bottleneckScore = calculateBottleneckScore(bottlenecks);
|
|
64
|
+
// Step 3: Estimate capacity
|
|
65
|
+
const capacity = await estimateCapacity(loadTestResult, bottlenecks);
|
|
66
|
+
const capacityScore = calculateCapacityScore(capacity, targetConcurrent);
|
|
67
|
+
// Step 4: Calculate overall score
|
|
68
|
+
const loadTestScore = loadTestResult?.score ?? 50; // Neutral if no test
|
|
69
|
+
const overallScore = Math.round((loadTestScore * 0.4) + (bottleneckScore * 0.35) + (capacityScore * 0.25));
|
|
70
|
+
const result = {
|
|
71
|
+
success: overallScore >= 70,
|
|
72
|
+
loadTest: loadTestResult,
|
|
73
|
+
bottlenecks,
|
|
74
|
+
capacity,
|
|
75
|
+
score: {
|
|
76
|
+
loadTestScore,
|
|
77
|
+
bottleneckScore,
|
|
78
|
+
capacityScore,
|
|
79
|
+
overallScore,
|
|
80
|
+
},
|
|
81
|
+
duration: Date.now() - startTime,
|
|
82
|
+
};
|
|
83
|
+
logger.info("scale.assessment_completed", {
|
|
84
|
+
success: result.success,
|
|
85
|
+
overallScore,
|
|
86
|
+
loadTestScore,
|
|
87
|
+
bottleneckScore,
|
|
88
|
+
capacityScore,
|
|
89
|
+
duration: result.duration,
|
|
90
|
+
});
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Quick bottleneck scan (no load testing)
|
|
95
|
+
*/
|
|
96
|
+
export async function quickBottleneckScan(projectPath) {
|
|
97
|
+
const bottlenecks = await detectBottlenecks(projectPath);
|
|
98
|
+
const score = calculateBottleneckScore(bottlenecks);
|
|
99
|
+
return { bottlenecks, score };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/scanners/scale/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load Profiler
|
|
3
|
+
*
|
|
4
|
+
* Runs load tests using k6, Artillery, or other tools.
|
|
5
|
+
* Generates k6 scripts from YAML profile definitions.
|
|
6
|
+
*
|
|
7
|
+
* @module scanners/scale/load-profiler
|
|
8
|
+
*/
|
|
9
|
+
import { type LoadProfile, type LoadTestResult, type LoadTool } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Check if k6 is installed
|
|
12
|
+
*/
|
|
13
|
+
export declare function isK6Available(): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Check if Artillery is installed
|
|
16
|
+
*/
|
|
17
|
+
export declare function isArtilleryAvailable(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Detect best available load testing tool
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectLoadTool(): Promise<LoadTool | null>;
|
|
22
|
+
/**
|
|
23
|
+
* Generate k6 script from load profile
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateK6Script(profile: LoadProfile, baseUrl: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Load a profile from YAML file
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadProfile(profilePath: string): Promise<LoadProfile>;
|
|
30
|
+
/**
|
|
31
|
+
* Discover all load profiles in a project
|
|
32
|
+
*/
|
|
33
|
+
export declare function discoverProfiles(projectPath: string): Promise<Array<{
|
|
34
|
+
path: string;
|
|
35
|
+
profile: LoadProfile;
|
|
36
|
+
}>>;
|
|
37
|
+
/**
|
|
38
|
+
* Run a load test with k6
|
|
39
|
+
*/
|
|
40
|
+
export declare function runK6Test(profile: LoadProfile, baseUrl: string, options?: {
|
|
41
|
+
timeout?: number;
|
|
42
|
+
outputDir?: string;
|
|
43
|
+
}): Promise<LoadTestResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Generate a sample load profile
|
|
46
|
+
*/
|
|
47
|
+
export declare function generateSampleProfile(projectPath: string, name?: string): Promise<string>;
|
|
48
|
+
//# sourceMappingURL=load-profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-profiler.d.ts","sourceRoot":"","sources":["../../../src/scanners/scale/load-profiler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EAGnB,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AAIpB;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAMtD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAM7D;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAI/D;AAwBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAsD9E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAI3E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAAC,CA0BxD;AAgDD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACf,GACL,OAAO,CAAC,cAAc,CAAC,CAkIzB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,MAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA8DjB"}
|