import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate, Trend, Counter, Gauge } from 'k6/metrics'; // Custom metrics const errorRate = new Rate('errors'); const requestDuration = new Trend('request_duration'); const requestCount = new Counter('requests'); const activeConnections = new Gauge('active_connections'); // Test configuration export const options = { vus: 10, // Virtual users duration: '5m', // Test duration thresholds: { 'http_req_duration': ['p(95)<200', 'p(99)<500'], // p95 <200ms, p99 <500ms 'http_req_failed': ['rate<0.1'], // <0.1% error rate 'errors': ['rate<0.01'], // <1% custom errors }, }; // Test target (update with production domain) const BASE_URL = __ENV.GRAVL_API_URL || 'https://gravl.example.com'; export default function () { // Simulate active connection count activeConnections.add(1); // Test 1: Health check { let response = http.get(`${BASE_URL}/api/health`); check(response, { 'health check status is 200': (r) => r.status === 200, 'health check has status field': (r) => r.body.includes('status'), }); errorRate.add(response.status !== 200); requestDuration.add(response.timings.duration); requestCount.add(1); } sleep(1); // Test 2: List exercises (unauthenticated or with test token) { let response = http.get(`${BASE_URL}/api/exercises`); check(response, { 'exercises endpoint status is 200': (r) => r.status === 200, 'exercises returns array': (r) => r.body.includes('['), }); errorRate.add(response.status !== 200); requestDuration.add(response.timings.duration); requestCount.add(1); } sleep(1); // Test 3: Metrics endpoint (for monitoring) { let response = http.get(`${BASE_URL}:3001/metrics`); check(response, { 'metrics endpoint status is 200': (r) => r.status === 200 || r.status === 404, // Optional endpoint }); requestDuration.add(response.timings.duration); requestCount.add(1); } sleep(1); activeConnections.add(-1); } export function teardown(data) { console.log(`\n=== Load Test Summary ===`); console.log(`Total requests: ${requestCount.value}`); console.log(`Error rate: ${(errorRate.value * 100).toFixed(2)}%`); }