diff --git a/deploy/oke/load-test/loadgen/loadtest.js b/deploy/oke/load-test/loadgen/loadtest.js index ab214b27..72a16936 100644 --- a/deploy/oke/load-test/loadgen/loadtest.js +++ b/deploy/oke/load-test/loadgen/loadtest.js @@ -3,30 +3,65 @@ import { check, sleep } from 'k6'; import exec from 'k6/execution'; import { Trend, Counter } from 'k6/metrics'; -const target = __ENV.LOADTEST_TARGET || 'http://agent-template-backend.agent-load-test.svc.cluster.local:8000'; -const agentId = __ENV.LOADTEST_AGENT_ID || 'telecom_contas'; -const tenantId = __ENV.LOADTEST_TENANT_ID || 'loadtest'; -const scenario = __ENV.LOADTEST_SCENARIO || 'unique_sessions'; -const message = __ENV.LOADTEST_MESSAGE || 'Explique em uma frase o que é uma fatura de telecom.'; -const rps = Number(__ENV.LOADTEST_RPS || 100); -const duration = __ENV.LOADTEST_DURATION || '10m'; -const maxVUs = Number(__ENV.LOADTEST_MAX_VUS || 1000); +const target = + __ENV.LOADTEST_TARGET || + 'http://agent-template-backend.agent-load-test.svc.cluster.local:8000'; -const backendLatency = new Trend('agent_backend_latency', true); -const errors = new Counter('agent_backend_errors'); +const agentId = + __ENV.LOADTEST_AGENT_ID || 'telecom_contas'; + +const tenantId = + __ENV.LOADTEST_TENANT_ID || 'loadtest'; + +const scenario = + __ENV.LOADTEST_SCENARIO || 'unique_sessions'; + +const message = + __ENV.LOADTEST_MESSAGE || + 'Explique em uma frase o que é uma fatura de telecom.'; + +const duration = + __ENV.LOADTEST_DURATION || '10m'; + +const maxVUs = + Number(__ENV.LOADTEST_MAX_VUS || 300); + +const startVUs = + Number(__ENV.LOADTEST_START_VUS || 30); + +const thinkTime = + Number(__ENV.LOADTEST_THINK_TIME || 0); + +const httpTimeout = + __ENV.LOADTEST_HTTP_TIMEOUT || '180s'; + +const backendLatency = + new Trend('agent_backend_latency', true); + +const errors = + new Counter('agent_backend_errors'); export const options = { discardResponseBodies: false, + scenarios: { requests: { - executor: 'constant-arrival-rate', - rate: rps, - timeUnit: '1s', - duration, - preAllocatedVUs: Math.min(maxVUs, Math.max(50, rps * 2)), - maxVUs, + executor: 'ramping-vus', + + startVUs, + + stages: [ + { duration: '1m', target: 100 }, + { duration: '2m', target: 200 }, + { duration: '2m', target: maxVUs }, + { duration: '4m', target: maxVUs }, + { duration: '1m', target: 0 }, + ], + + gracefulRampDown: '30s', }, }, + thresholds: { http_req_failed: ['rate<0.05'], checks: ['rate>0.95'], @@ -37,39 +72,80 @@ function sessionId() { if (scenario === 'shared_sessions') { return `shared-${exec.vu.idInTest % 100}`; } - return `load-${exec.scenario.iterationInTest}-${exec.vu.idInTest}`; + + /* + * Para unique_sessions, mantenha uma sessão por VU. + * + * Isso representa melhor um usuário conversando continuamente + * com o agente durante o teste. + */ + return `load-${exec.vu.idInTest}`; } export default function () { const sid = sessionId(); - const mid = `msg-${exec.scenario.iterationInTest}-${Date.now()}`; + + const mid = + `msg-${exec.vu.idInTest}-${exec.scenario.iterationInTest}-${Date.now()}`; + const payload = JSON.stringify({ channel: 'web', agent_id: agentId, tenant_id: tenantId, + payload: { text: message, session_id: sid, + user_id: `user-${exec.vu.idInTest}`, customer_id: `cust-${exec.vu.idInTest}`, message_id: mid, - metadata: { load_test: true, scenario }, + + metadata: { + load_test: true, + scenario, + }, }, }); + const started = Date.now(); - const res = http.post(`${target}/gateway/message`, payload, { - headers: { - 'Content-Type': 'application/json', - 'X-Request-ID': mid, - 'X-Load-Test': 'true', - }, - timeout: __ENV.LOADTEST_HTTP_TIMEOUT || '180s', - }); + + const res = http.post( + `${target}/gateway/message`, + payload, + { + headers: { + 'Content-Type': 'application/json', + 'X-Request-ID': mid, + 'X-Load-Test': 'true', + }, + + timeout: httpTimeout, + } + ); + backendLatency.add(Date.now() - started); + const ok = check(res, { 'status is 200': (r) => r.status === 200, - 'response has body': (r) => !!r.body && r.body.length > 0, + + 'response has body': (r) => + !!r.body && r.body.length > 0, }); - if (!ok) errors.add(1); - sleep(Number(__ENV.LOADTEST_THINK_TIME || 0)); -} + + if (!ok) { + errors.add(1); + } + + /* + * Se LOADTEST_THINK_TIME=0: + * + * usuário envia a próxima mensagem assim que recebe a resposta. + * + * Se quiser simular tempo humano entre mensagens: + * LOADTEST_THINK_TIME=5, 10 etc. + */ + if (thinkTime > 0) { + sleep(thinkTime); + } +} \ No newline at end of file