Files
Sankofa/scripts/k6-load-test.js
defiQUG 9daf1fd378 Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements
- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
2025-12-12 18:01:35 -08:00

162 lines
4.7 KiB
JavaScript

// k6 Load Testing Configuration
// Comprehensive load test for Sankofa Phoenix API
// Usage: k6 run k6-load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend, Counter } from 'k6/metrics';
// Custom metrics
const errorRate = new Rate('errors');
const apiLatency = new Trend('api_latency');
const graphqlLatency = new Trend('graphql_latency');
const requestCount = new Counter('requests_total');
// Configuration
const API_URL = __ENV.API_URL || 'https://api.sankofa.nexus';
const TEST_DURATION = __ENV.TEST_DURATION || '5m';
const VUS = parseInt(__ENV.VUS || '10');
export const options = {
stages: [
// Ramp up to 10 VUs over 1 minute
{ duration: '1m', target: 10 },
// Stay at 10 VUs for 2 minutes
{ duration: '2m', target: 10 },
// Ramp up to 50 VUs over 2 minutes
{ duration: '2m', target: 50 },
// Stay at 50 VUs for 2 minutes
{ duration: '2m', target: 50 },
// Ramp up to 100 VUs over 2 minutes
{ duration: '2m', target: 100 },
// Stay at 100 VUs for 2 minutes
{ duration: '2m', target: 100 },
// Ramp down to 0 VUs over 2 minutes
{ duration: '2m', target: 0 },
],
thresholds: {
// 95% of requests should be below 200ms
'http_req_duration': ['p(95)<200', 'p(99)<500'],
// Error rate should be less than 1%
'http_req_failed': ['rate<0.01'],
'errors': ['rate<0.01'],
// API latency should be below 200ms
'api_latency': ['p(95)<200'],
// GraphQL latency should be below 300ms
'graphql_latency': ['p(95)<300'],
},
};
// Test data
const graphqlQueries = [
{
query: '{ __typename }',
},
{
query: `
query {
me {
id
email
name
}
}
`,
},
{
query: `
query {
sites {
id
name
region
status
}
}
`,
},
];
// Helper function to get random query
function getRandomQuery() {
return graphqlQueries[Math.floor(Math.random() * graphqlQueries.length)];
}
export default function () {
// Test 1: Health endpoint
const healthStart = Date.now();
const healthRes = http.get(`${API_URL}/health`, {
tags: { name: 'HealthCheck' },
});
const healthDuration = Date.now() - healthStart;
const healthCheck = check(healthRes, {
'health status is 200': (r) => r.status === 200,
'health response time < 100ms': (r) => r.timings.duration < 100,
});
errorRate.add(!healthCheck);
apiLatency.add(healthDuration);
requestCount.add(1, { endpoint: 'health' });
sleep(0.5);
// Test 2: GraphQL endpoint
const graphqlQuery = getRandomQuery();
const graphqlStart = Date.now();
const graphqlRes = http.post(
`${API_URL}/graphql`,
JSON.stringify(graphqlQuery),
{
headers: { 'Content-Type': 'application/json' },
tags: { name: 'GraphQL' },
}
);
const graphqlDuration = Date.now() - graphqlStart;
const graphqlCheck = check(graphqlRes, {
'graphql status is 200': (r) => r.status === 200,
'graphql response time < 300ms': (r) => r.timings.duration < 300,
'graphql has data': (r) => {
try {
const body = JSON.parse(r.body);
return body.data !== undefined || body.errors === undefined;
} catch (e) {
return false;
}
},
});
errorRate.add(!graphqlCheck);
graphqlLatency.add(graphqlDuration);
requestCount.add(1, { endpoint: 'graphql' });
sleep(1);
}
export function handleSummary(data) {
return {
'stdout': textSummary(data, { indent: ' ', enableColors: true }),
'summary.json': JSON.stringify(data),
};
}
function textSummary(data, options) {
const indent = options.indent || '';
const enableColors = options.enableColors || false;
let summary = '';
summary += `${indent}Test Summary\n`;
summary += `${indent}============\n\n`;
// Metrics summary
summary += `${indent}Metrics:\n`;
summary += `${indent} - Total Requests: ${data.metrics.requests_total.values.count}\n`;
summary += `${indent} - Failed Requests: ${data.metrics.http_req_failed.values.rate * 100}%\n`;
summary += `${indent} - p95 Latency: ${data.metrics.http_req_duration.values['p(95)']}ms\n`;
summary += `${indent} - p99 Latency: ${data.metrics.http_req_duration.values['p(99)']}ms\n`;
return summary;
}