import http from ‘k6/http’;
import { check, sleep } from ‘k6’;
import { Rate } from ‘k6/metrics’;
import { SharedArray } from ‘k6/data’;
import { Trend } from ‘k6/metrics’;
// ---------------- ERROR METRIC ----------------
export let errorRate = new Rate(‘error_rate’);
// ---------------- HELPER: Exponential think time ----------------
function exponentialSleep(mean) {
return -Math.log(1 - Math.random()) * mean;
}
// Optional: track response time per stage
export let responseTime = new Trend(‘response_time’, true);
// ---------------- LOAD TSV FILE ----------------
const csvData = new SharedArray(‘revgeo dataset’, function () {
const file = open(‘./rgc-a.csv’);
return file
.split(‘\n’)
.map((line) => line.trim())
.filter((line) => line.length > 0)
.map((line) => line.split(/\t+/));
});
// ---------------- HELPER: Stage tagging ----------------
function getStageTag() {
if (__ENV.SCENARIO_NAME === ‘baseload’) {
return ‘baseload’;
}
// Time elapsed since ramp start
const elapsed = (__ITER + 1); // seconds passed in this VU; simple approximation
const step = Math.floor(elapsed / RAMP_STEP_DURATION);
const stageIndex = Math.min(step, RAMP_TOTAL_STEPS - 1);
return `ramp${stageIndex}`;
}
// ---------------- BASELOAD PARAMETERS ----------------
export const BASELOAD_DURATION = 1200; // 20 minutes
export const BASELOAD_QPM_PER_THREAD = 600; // QPM per thread
export const BASELOAD_THREADS = 50;
// ---------------- RAMP-UP PARAMETERS ----------------
export const RAMP_MAX_THREADS = 1300; // Max threads (VU)
export const RAMP_QPM_PER_THREAD = 600;
export const RAMP_START_DELAY = 1320; // start after baseload
export const RAMP_STEP_DURATION = 120; // per ramp step (2min)
export const RAMP_THREADS_PER_STEP = 130; // threads added per step
export const RAMP_TOTAL_STEPS = 10;
// ---------------- CSV DISTRIBUTION ----------------
const rowsPerVU = Math.ceil(csvData.length / RAMP_MAX_THREADS);
// ---------------- STAGE TAGGING ----------------
export function tagWithCurrentStageIndex(stageIndex) {
return { stage: ramp${stageIndex} };
}
// ---------------- GLOBAL PERFID ----------------
// Generate a single perfId at script start
const PERF_ID = PT-3beba3cc869d4ba0ba172a02343ec7rg;
console.log(Global perfId: ${PERF_ID});
// ---------------- K6 OPTIONS ----------------
export const options = {
scenarios: {
baseload: {
executor: ‘constant-arrival-rate’,
rate: (BASELOAD_QPM_PER_THREAD / 60) * BASELOAD_THREADS,
timeUnit: ‘1s’,
duration: ${BASELOAD_DURATION}s,
preAllocatedVUs: BASELOAD_THREADS,
maxVUs: BASELOAD_THREADS * 2,
env: { SCENARIO_NAME: “baseload” }
},
rampup: {
executor: ‘ramping-arrival-rate’,
startRate: 0,
timeUnit: ‘1s’,
startTime: ${RAMP_START_DELAY}s,
stages: (() => {
const stages = ;
for (let i = 1; i <= RAMP_TOTAL_STEPS; i++) {
stages.push({
target: i * RAMP_THREADS_PER_STEP * (RAMP_QPM_PER_THREAD / 60),
duration: ${RAMP_STEP_DURATION}s,
});
}
return stages;
})(),
preAllocatedVUs: RAMP_THREADS_PER_STEP,
maxVUs:(RAMP_TOTAL_STEPS * RAMP_THREADS_PER_STEP * (RAMP_QPM_PER_THREAD / 60)) * 2, // make sure maxVUs is enough for final stage
env: { SCENARIO_NAME: “rampup” }
},
},
thresholds: {
‘error_rate’: [‘rate<0.1’],
‘http_req_failed’: [‘rate<0.01’],
‘http_req_duration’: [‘p(95)<500’],
},
};
// ---------------- HELPER: Get CSV row for this VU ----------------
function getRowForVU(vuIndex, iter) {
const start = (vuIndex - 1) * rowsPerVU;
const end = start + rowsPerVU;
const myRows = csvData.slice(start, end).length > 0 ? csvData.slice(start, end) : csvData;
return myRows[iter % myRows.length];
}
// ---------------- DEFAULT FUNCTION ----------------
export default function () {
const BASE_URL = ‘http://internal-ad844a08ac80c44b7ae55cfbdc90e43e-1071003513.eu-west-1.elb.amazonaws.com’;
// Get unique row per VU
const row = getRowForVU(__VU, __ITER);
if (!row || !row[0]) {
console.error(⚠️ Invalid or empty row for VU ${__VU}, iteration ${__ITER});
return;
}
const path = row[0].startsWith(‘/’) ? row[0] : ‘/’ + row[0];
// If the path already contains ?, append with &, otherwise with ?
const separator = path.includes(‘?’) ? ‘&’ : ‘?’;
const url = ${BASE_URL}${path}${separator}perfid=${PERF_ID};
// Optional: log the first request for sanity
if (__ITER < 3 && __VU === 1) {
console.log(Sample URL: ${url});
console.log(Row data: ${JSON.stringify(row)});
}
// Accurate stage tagging based on time
const stage = getStageTag();
// Send GET request
const res = http.get(url, { tags: { stage } });
// Validate response
const ok = check(res, {
‘status is 2xx or 3xx’: (r) => r.status <= 400,
});
// Update error rate
errorRate.add(!ok);
responseTime.add(res.timings.duration, tags);
sleep(exponentialSleep(1.5));
}
is this script fine??