- Add constant-arrival-rate scenarios to all 4 service scripts (api,
darkwatch, spamshield, voiceprint) to enforce 500 req/s target
- Fix defaultThresholds() to return { thresholds: {...} } so
http_req_duration and errors thresholds are actually applied
- Rewrite run-all.sh: per-service summary files, proper env var
passing (DURATION, API_TOKEN), fixed threshold aggregation
- Update CI workflow threshold check jq to match new threshold-results
structure (.services.<name>.exitCode)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
91 lines
2.8 KiB
JavaScript
91 lines
2.8 KiB
JavaScript
import http from 'k6/http';
|
|
import { check, group } from 'k6';
|
|
import { Rate, Trend } from 'k6/metrics';
|
|
import { getBaseUrl, defaultThresholds, checkResponse, randomString } from '../lib/common.js';
|
|
|
|
const errorRate = new Rate('errors');
|
|
const smsClassifyP99 = new Trend('sms_classify_p99');
|
|
const numberReputationP99 = new Trend('number_reputation_p99');
|
|
const callAnalyzeP99 = new Trend('call_analyze_p99');
|
|
|
|
const TARGET_RPS = getTargetRps();
|
|
const DURATION = getDuration();
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
sustained_load: {
|
|
executor: 'constant-arrival-rate',
|
|
duration: DURATION,
|
|
rate: TARGET_RPS,
|
|
preAllocatedVUs: 20,
|
|
maxVUs: 100,
|
|
startTime: '0s',
|
|
exec: 'default',
|
|
tags: { scenario: 'sustained_load' },
|
|
},
|
|
},
|
|
thresholds: {
|
|
...defaultThresholds(400).thresholds,
|
|
sms_classify_p99: ['p(99)<150'],
|
|
number_reputation_p99: ['p(99)<300'],
|
|
call_analyze_p99: ['p(99)<400'],
|
|
},
|
|
};
|
|
|
|
const BASE_URL = getBaseUrl();
|
|
const AUTH_TOKEN = __ENV.API_TOKEN || 'test-token';
|
|
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${AUTH_TOKEN}`,
|
|
};
|
|
|
|
export default function () {
|
|
group('SMS Text Classification', function () {
|
|
const payload = JSON.stringify({
|
|
text: `Is this message a spam attempt? ${randomString(16)}`,
|
|
});
|
|
const res = http.post(`${BASE_URL}/spamshield/sms/classify`, payload, { headers });
|
|
checkResponse(res, 200);
|
|
smsClassifyP99.add(res.timings.duration);
|
|
});
|
|
|
|
group('Number Reputation Check', function () {
|
|
const payload = JSON.stringify({
|
|
phoneNumber: `+1555${String(Math.floor(1000000 + Math.random() * 9000000))}`,
|
|
});
|
|
const res = http.post(`${BASE_URL}/spamshield/number/reputation`, payload, { headers });
|
|
checkResponse(res, 200);
|
|
numberReputationP99.add(res.timings.duration);
|
|
});
|
|
|
|
group('Call Analysis', function () {
|
|
const payload = JSON.stringify({
|
|
phoneNumber: `+1555${String(Math.floor(1000000 + Math.random() * 9000000))}`,
|
|
callTime: new Date().toISOString(),
|
|
});
|
|
const res = http.post(`${BASE_URL}/spamshield/call/analyze`, payload, { headers });
|
|
checkResponse(res, 200);
|
|
callAnalyzeP99.add(res.timings.duration);
|
|
});
|
|
|
|
group('Spam Feedback', function () {
|
|
const payload = JSON.stringify({
|
|
phoneNumber: `+1555${String(Math.floor(1000000 + Math.random() * 9000000))}`,
|
|
isSpam: false,
|
|
});
|
|
const res = http.post(`${BASE_URL}/spamshield/feedback`, payload, { headers });
|
|
check(res, { 'feedback status is 201': (r) => r.status === 201 });
|
|
});
|
|
|
|
group('Spam History', function () {
|
|
const res = http.get(`${BASE_URL}/spamshield/history?limit=10`, { headers });
|
|
checkResponse(res, 200);
|
|
});
|
|
|
|
group('Spam Statistics', function () {
|
|
const res = http.get(`${BASE_URL}/spamshield/statistics`, { headers });
|
|
checkResponse(res, 200);
|
|
});
|
|
}
|