Skip to content

Commit a62255c

Browse files
feat: load with constant arrival rate (#87)
add env variables - RATE -- iterations per timeunit, default 2000 TIMEUNIT -- start rate iterations per second, default 1s DURATION -- how long the test lasts, default 5m PRE_ALLOCATED_VUS -- pre-allocate vus before starting the test, default 2 MAX_VUS -- spin max vus, default 20
1 parent e8a6b7a commit a62255c

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed

scripts/load_constant_arrival_rate.js

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import http from 'k6/http';
2+
import { check, sleep } from 'k6';
3+
import exec from 'k6/execution';
4+
import encoding from 'k6/encoding';
5+
import { randomString, randomItem, randomIntBetween, uuidv4 } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'
6+
7+
export const options = {
8+
discardResponseBodies: true,
9+
scenarios: {
10+
contacts: {
11+
executor: 'constant-arrival-rate',
12+
13+
// How many iterations per timeUnit
14+
rate: Number(__ENV.RATE) || 2000,
15+
16+
// Start `rate` iterations per second
17+
timeUnit: __ENV.TIMEUNIT || '1s',
18+
19+
// How long the test lasts
20+
duration: __ENV.DURATION || '5m',
21+
22+
// Pre-allocate 2 VUs before starting the test
23+
preAllocatedVUs: Number(__ENV.PRE_ALLOCATED_VUS) || 2,
24+
25+
// Spin up a maximum of 50 VUs to sustain the defined constant arrival rate.
26+
maxVUs: Number(__ENV.MAX_VUS) || 20
27+
},
28+
},
29+
};
30+
31+
function current_time() {
32+
let event = new Date();
33+
event.setMonth(event.getMonth() - 1);
34+
return event.toISOString();
35+
}
36+
37+
function schemas() {
38+
return Number(__ENV.P_SCHEMA_COUNT)
39+
}
40+
41+
const common_schema = [
42+
{ "name": "source_time", "gen": current_time, "arg": null },
43+
{ "name": "level", "gen": randomItem, "arg": ["info", "warn", "error"] },
44+
{ "name": "message", "gen": randomItem, "arg": ["Application started", "Application is failing", "Logging a request"] },
45+
{ "name": "version", "gen": randomItem, "arg": ["1.0.0", "1.1.0", "1.2.0"] },
46+
{ "name": "user_id", "gen": randomIntBetween, "arg": [10000, 100000] },
47+
{ "name": "device_id", "gen": randomIntBetween, "arg": [0, 5000] },
48+
{ "name": "session_id", "gen": randomItem, "arg": ["abc", "pqr", "xyz"] },
49+
{ "name": "os", "gen": randomItem, "arg": ["macOS", "Linux", "Windows"] },
50+
{ "name": "host", "gen": randomItem, "arg": ["192.168.1.100", "112.168.1.110", "172.162.1.120"] },
51+
{ "name": "uuid", "gen": uuidv4, "arg": null },
52+
]
53+
54+
const add_fields = {
55+
"location": { "gen": randomString, "arg": 16 },
56+
"timezone": { "gen": randomString, "arg": 3 },
57+
"user_agent": { "gen": randomItem, "arg": ["Banana", "PineApple", "PearOS", "OrangeOS", "Kiwi"] },
58+
"runtime": { "gen": randomString, "arg": 3 },
59+
"request_body": { "gen": randomString, "arg": 100 },
60+
"status_code": { "gen": randomItem, "arg": [200, 300, 400, 500] },
61+
"response_time": { "gen": randomItem, "arg": [12, 22, 34, 56, 70, 112] },
62+
"process_id": { "gen": randomIntBetween, "arg": [100, 1000] },
63+
"app_meta": { "gen": randomString, "arg": 24 }
64+
}
65+
66+
const addFields_permutation = [
67+
['location', 'request_body', 'status_code', 'app_meta'],
68+
['timezone', 'user_agent', 'runtime', 'app_meta'],
69+
['timezone', 'request_body', 'response_time', 'process_id'],
70+
['timezone', 'user_agent', 'request_body', 'process_id'],
71+
['runtime', 'status_code', 'response_time', 'process_id'],
72+
['location', 'user_agent', 'runtime', 'process_id'],
73+
['location', 'timezone', 'request_body', 'response_time'],
74+
['timezone', 'user_agent', 'status_code', 'process_id'],
75+
['timezone', 'runtime', 'request_body', 'response_time'],
76+
['timezone', 'status_code', 'response_time', 'process_id'],
77+
['timezone', 'runtime', 'status_code', 'response_time'],
78+
['location', 'timezone', 'response_time', 'process_id'],
79+
['location', 'timezone', 'runtime', 'process_id'],
80+
['user_agent', 'runtime', 'status_code', 'process_id'],
81+
['timezone', 'response_time', 'process_id', 'app_meta'],
82+
['location', 'user_agent', 'status_code', 'response_time'],
83+
['timezone', 'user_agent', 'runtime', 'status_code'],
84+
['request_body', 'status_code', 'process_id', 'app_meta'],
85+
['location', 'user_agent', 'runtime', 'request_body'],
86+
['location', 'timezone', 'status_code', 'response_time'],
87+
['location', 'user_agent', 'response_time', 'process_id'],
88+
['timezone', 'runtime', 'response_time', 'process_id'],
89+
['location', 'timezone', 'user_agent', 'runtime'],
90+
['user_agent', 'request_body', 'status_code', 'process_id'],
91+
['runtime', 'request_body', 'response_time', 'process_id'],
92+
['location', 'runtime', 'request_body', 'app_meta'],
93+
['runtime', 'response_time', 'process_id', 'app_meta'],
94+
['location', 'runtime', 'status_code', 'app_meta'],
95+
['location', 'runtime', 'process_id', 'app_meta'],
96+
['location', 'request_body', 'process_id', 'app_meta'],
97+
['location', 'timezone', 'runtime', 'request_body'],
98+
['timezone', 'user_agent', 'response_time', 'app_meta'],
99+
['runtime', 'request_body', 'status_code', 'response_time'],
100+
['location', 'timezone', 'user_agent', 'response_time'],
101+
['location', 'runtime', 'request_body', 'status_code'],
102+
['location', 'user_agent', 'request_body', 'response_time'],
103+
['location', 'status_code', 'process_id', 'app_meta'],
104+
['user_agent', 'status_code', 'response_time', 'app_meta'],
105+
['timezone', 'request_body', 'status_code', 'response_time'],
106+
['user_agent', 'runtime', 'request_body', 'process_id'],
107+
['user_agent', 'runtime', 'response_time', 'app_meta'],
108+
['user_agent', 'request_body', 'response_time', 'app_meta']
109+
];
110+
111+
function generateOverlappingSchemas(number = 5) {
112+
const schemas = [];
113+
addFields_permutation.slice(0, number).forEach((listOfFields) => {
114+
const new_schema = [...common_schema];
115+
listOfFields.forEach((field) => {
116+
let gen_value = add_fields[field];
117+
let obj = { "name": field };
118+
Object.assign(obj, gen_value);
119+
new_schema.push(obj)
120+
})
121+
schemas.push(new_schema)
122+
})
123+
124+
return schemas;
125+
}
126+
127+
function generateJSON(schema) {
128+
let json = {};
129+
schema.forEach(item => {
130+
let { name, gen, arg } = item;
131+
var value;
132+
if ((gen === current_time) || (gen === uuidv4)) {
133+
value = gen();
134+
}
135+
else if (gen === randomIntBetween) {
136+
value = gen(...arg);
137+
}
138+
else {
139+
value = gen(arg)
140+
}
141+
json[name] = value;
142+
});
143+
return json;
144+
}
145+
146+
function generateEvents(num = 5) {
147+
const events = [];
148+
let numberOfSchemas = schemas();
149+
if (!numberOfSchemas) {
150+
numberOfSchemas = 5
151+
}
152+
let listOfSchema = generateOverlappingSchemas(numberOfSchemas);
153+
154+
// generate event of random schema from the list
155+
for (let index = 0; index < num; index++) {
156+
events.push(generateJSON(listOfSchema[Math.floor(Math.random() * listOfSchema.length)]));
157+
}
158+
159+
return events
160+
}
161+
162+
function events_per_call() {
163+
return Number(__ENV.P_EVENTS_COUNT)
164+
}
165+
166+
export default function () {
167+
const url = `${__ENV.P_URL}/api/v1/ingest`;
168+
const credentials = `${__ENV.P_USERNAME}:${__ENV.P_PASSWORD}`;
169+
const encodedCredentials = encoding.b64encode(credentials);
170+
171+
const params = {
172+
headers: {
173+
'Content-Type': 'application/json',
174+
'Authorization': 'Basic ' + `${encodedCredentials}`,
175+
'X-P-STREAM': `${__ENV.P_STREAM}`,
176+
'X-P-META-Source': 'quest-constant-arrival-rate',
177+
'X-P-META-Test': 'Fixed-Logs',
178+
}
179+
}
180+
181+
let events = events_per_call();
182+
183+
if (!events) {
184+
events = 10
185+
}
186+
187+
let batch_requests = JSON.stringify(generateEvents(events));
188+
let response = http.post(url, batch_requests, params);
189+
190+
if (
191+
!check(response, {
192+
'status code MUST be 200': (res) => res.status == 200,
193+
})
194+
) {
195+
exec.test.abort("Failed to send event.. status != 200");
196+
}
197+
}

0 commit comments

Comments
 (0)