/** * EN: k6 load test — Ads tracking event ingestion (POST /api/v1/tracking/events). * VI: k6 load test — nhập event tracking quảng cáo (POST /api/v1/tracking/events). * * EN: Ads tracking is a high-throughput, fire-and-forget endpoint. * VI: Tracking là endpoint thông lượng cao, fire-and-forget. * * Usage: * k6 run tests/load/k6/ads-tracking.js * k6 run --env BASE_URL=http://api.staging.goodgo.vn tests/load/k6/ads-tracking.js * * Thresholds: * - 95th-percentile response time < 100ms * - Error rate < 0.1% * - Throughput > 500 req/s */ import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate, Trend, Counter } from 'k6/metrics'; // --------------------------------------------------------------------------- // Custom metrics // --------------------------------------------------------------------------- const trackingErrors = new Rate('tracking_errors'); const trackingDuration = new Trend('tracking_duration', true); const eventsIngested = new Counter('events_ingested'); // --------------------------------------------------------------------------- // Test options — simulate high-frequency event stream // --------------------------------------------------------------------------- export const options = { stages: [ { duration: '20s', target: 100 }, { duration: '1m', target: 300 }, { duration: '30s', target: 500 }, // EN: Peak throughput / VI: Đỉnh thông lượng { duration: '20s', target: 0 }, ], thresholds: { // EN: Tracking must be very fast — p95 < 100ms / VI: Tracking phải rất nhanh http_req_duration: ['p(95)<100', 'p(99)<200'], tracking_errors: ['rate<0.001'], tracking_duration: ['p(95)<100'], }, }; // --------------------------------------------------------------------------- // Config // --------------------------------------------------------------------------- const BASE_URL = __ENV.BASE_URL || 'http://localhost:5080'; const API_KEY = __ENV.TRACKING_API_KEY || 'test-tracking-key'; const headers = { 'Content-Type': 'application/json', 'X-Api-Key': API_KEY, }; // --------------------------------------------------------------------------- // Event types // --------------------------------------------------------------------------- const EVENT_TYPES = ['impression', 'click', 'view', 'conversion', 'engagement']; const AD_IDS = [ '00000000-0000-0000-0000-000000000011', '00000000-0000-0000-0000-000000000012', '00000000-0000-0000-0000-000000000013', ]; const CAMPAIGN_IDS = [ '00000000-0000-0000-0000-000000000021', '00000000-0000-0000-0000-000000000022', ]; // --------------------------------------------------------------------------- // Helper — build a tracking event payload // --------------------------------------------------------------------------- function buildTrackingEvent() { const eventType = EVENT_TYPES[Math.floor(Math.random() * EVENT_TYPES.length)]; const adId = AD_IDS[Math.floor(Math.random() * AD_IDS.length)]; const campaignId = CAMPAIGN_IDS[Math.floor(Math.random() * CAMPAIGN_IDS.length)]; return JSON.stringify({ eventType, adId, campaignId, sessionId: `sess-${Math.random().toString(36).substring(2, 10)}`, userId: Math.random() > 0.3 ? `user-${Math.floor(Math.random() * 10000)}` : null, deviceType: ['mobile', 'desktop', 'tablet'][Math.floor(Math.random() * 3)], platform: ['ios', 'android', 'web'][Math.floor(Math.random() * 3)], timestamp: new Date().toISOString(), metadata: { pageUrl: '/pos/menu', referrer: 'organic', duration: eventType === 'view' ? Math.floor(Math.random() * 10000) : null, }, }); } // --------------------------------------------------------------------------- // Default function // --------------------------------------------------------------------------- export default function () { const payload = buildTrackingEvent(); const res = http.post(`${BASE_URL}/api/v1/tracking/events`, payload, { headers }); trackingDuration.add(res.timings.duration); const ok = check(res, { // EN: 202 Accepted or 200 OK / VI: 202 Accepted hoặc 200 OK 'status 200 or 202': (r) => r.status === 200 || r.status === 202, 'response < 100ms': (r) => r.timings.duration < 100, }); if (ok) { eventsIngested.add(1); trackingErrors.add(0); } else { trackingErrors.add(1); } // EN: No sleep — fire-and-forget high throughput / VI: Không sleep — thông lượng cao sleep(0.01); }