perf-skills 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -1
- package/package.json +2 -2
- package/skills/perf/SKILL.md +228 -72
- package/skills/perf/evals/evals.json +149 -0
- package/skills/perf/references/tools/gatling.md +286 -286
- package/skills/perf/references/tools/jmeter.md +251 -251
- package/skills/perf/references/tools/k6.md +269 -269
- package/skills/perf/references/tools/locust.md +133 -133
- package/skills/perf/references/topics/correlation.md +406 -0
- package/skills/perf/references/topics/database-testing.md +8 -8
- package/skills/perf/references/topics/modern-architectures.md +15 -15
- package/skills/perf/references/topics/observability.md +3 -3
- package/skills/perf/references/topics/production-testing.md +13 -13
- package/skills/perf/references/topics/protocol-testing.md +15 -15
- package/skills/perf/references/topics/results-analysis.md +13 -13
- package/skills/perf/references/topics/script-generation.md +9 -9
- package/skills/perf/references/topics/test-data.md +6 -6
- package/skills/perf/references/topics/test-execution.md +5 -5
- package/skills/perf/references/topics/workload-design.md +3 -3
|
@@ -1,269 +1,269 @@
|
|
|
1
|
-
# k6 Reference
|
|
2
|
-
|
|
3
|
-
> Targets: k6 v0.50+, xk6 extensions ecosystem
|
|
4
|
-
|
|
5
|
-
k6 is a developer-centric, open-source load testing tool built by Grafana Labs. Tests are written in JavaScript/TypeScript and executed with a Go runtime
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Core Concepts
|
|
10
|
-
|
|
11
|
-
| Concept | Description |
|
|
12
|
-
|---|---|
|
|
13
|
-
| **Virtual User (VU)** | A single simulated user executing the script |
|
|
14
|
-
| **Iteration** | One full execution of the default function |
|
|
15
|
-
| **Scenario** | Named execution profile with its own executor and config |
|
|
16
|
-
| **Executor** | Controls how VUs and iterations are scheduled |
|
|
17
|
-
| **Metric** | Built-in or custom measurement (counters, gauges, rates, trends) |
|
|
18
|
-
| **Check** | Inline assertion
|
|
19
|
-
| **Threshold** | SLA definition
|
|
20
|
-
| **Group** | Logical grouping of requests for metric aggregation |
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Script Structure
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
import http from 'k6/http';
|
|
28
|
-
import { check, sleep, group } from 'k6';
|
|
29
|
-
import { Counter, Trend } from 'k6/metrics';
|
|
30
|
-
|
|
31
|
-
// Custom metrics
|
|
32
|
-
const loginErrors = new Counter('login_errors');
|
|
33
|
-
const checkoutDuration = new Trend('checkout_duration_ms');
|
|
34
|
-
|
|
35
|
-
// Test configuration
|
|
36
|
-
export const options = {
|
|
37
|
-
scenarios: {
|
|
38
|
-
ramp_up: {
|
|
39
|
-
executor: 'ramping-vus',
|
|
40
|
-
startVUs: 0,
|
|
41
|
-
stages: [
|
|
42
|
-
{ duration: '2m', target: 50 },
|
|
43
|
-
{ duration: '5m', target: 50 },
|
|
44
|
-
{ duration: '2m', target: 0 },
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
thresholds: {
|
|
49
|
-
http_req_duration: ['p(95)<500', 'p(99)<1000'],
|
|
50
|
-
http_req_failed: ['rate<0.01'],
|
|
51
|
-
login_errors: ['count<5'],
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// Setup (runs once before VUs start)
|
|
56
|
-
export function setup() {
|
|
57
|
-
const res = http.post('https://api.example.com/auth/token', {
|
|
58
|
-
client_id: 'perf-test',
|
|
59
|
-
client_secret: __ENV.API_SECRET,
|
|
60
|
-
});
|
|
61
|
-
return { token: res.json('access_token') };
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Default VU function
|
|
65
|
-
export default function (data) {
|
|
66
|
-
group('Login Flow', () => {
|
|
67
|
-
const res = http.post('https://api.example.com/login', JSON.stringify({
|
|
68
|
-
username: `user_${__VU}@example.com`,
|
|
69
|
-
password: 'testpass',
|
|
70
|
-
}), {
|
|
71
|
-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${data.token}` },
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const ok = check(res, {
|
|
75
|
-
'login status 200': (r) => r.status === 200,
|
|
76
|
-
'has userId': (r) => r.json('userId') !== undefined,
|
|
77
|
-
});
|
|
78
|
-
if (!ok) loginErrors.add(1);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
sleep(Math.random() * 3 + 1); // Think time: 1–4 seconds
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Teardown (runs once after all VUs finish)
|
|
85
|
-
export function teardown(data) {
|
|
86
|
-
// Cleanup, invalidate tokens, etc.
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Executors
|
|
93
|
-
|
|
94
|
-
| Executor | Use Case | Key Options |
|
|
95
|
-
|---|---|---|
|
|
96
|
-
| `ramping-vus` | Ramp up/down | `stages: [{duration, target}]` |
|
|
97
|
-
| `constant-vus` | Fixed concurrency | `vus`, `duration` |
|
|
98
|
-
| `per-vu-iterations` | Each VU runs N times | `vus`, `iterations` |
|
|
99
|
-
| `shared-iterations` | Total N iterations split across VUs | `vus`, `iterations` |
|
|
100
|
-
| `constant-arrival-rate` | Fixed RPS (open model) | `rate`, `duration`, `preAllocatedVUs` |
|
|
101
|
-
| `ramping-arrival-rate` | Ramping RPS (open model) | `stages`, `preAllocatedVUs` |
|
|
102
|
-
| `externally-controlled` | Controlled via k6 REST API in real-time |
|
|
103
|
-
|
|
104
|
-
> For closed vs open model guidance and when to use each, see `../topics/workload-design.md`.
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Checks vs Thresholds
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
// Check: logs pass/fail but does NOT fail the test
|
|
112
|
-
check(res, { 'status 200': (r) => r.status === 200 });
|
|
113
|
-
|
|
114
|
-
// Threshold: FAILS the test run (non-zero exit code) if breached
|
|
115
|
-
// Put these in options.thresholds
|
|
116
|
-
thresholds: {
|
|
117
|
-
http_req_duration: ['p(95)<500'], // p95 must be under 500ms
|
|
118
|
-
checks: ['rate>0.99'], // At least 99% of checks must pass
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Use thresholds for SLA enforcement in CI/CD pipelines.
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Parameterization
|
|
127
|
-
|
|
128
|
-
### Environment variables
|
|
129
|
-
```bash
|
|
130
|
-
k6 run -e USERNAME=testuser -e PASSWORD=secret script.js
|
|
131
|
-
```
|
|
132
|
-
```javascript
|
|
133
|
-
const username = __ENV.USERNAME;
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### SharedArray (CSV / JSON data files)
|
|
137
|
-
```javascript
|
|
138
|
-
import { SharedArray } from 'k6/data';
|
|
139
|
-
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
|
|
140
|
-
|
|
141
|
-
const users = new SharedArray('users', function () {
|
|
142
|
-
return papaparse.parse(open('./data/users.csv'), { header: true }).data;
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
export default function () {
|
|
146
|
-
const user = users[__VU % users.length]; // Round-robin by VU
|
|
147
|
-
// use user.username, user.password
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
**SharedArray loads data once and shares it across all VUs**
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Correlation (Session Handling)
|
|
156
|
-
|
|
157
|
-
```javascript
|
|
158
|
-
// Extract value from JSON response
|
|
159
|
-
const token = res.json('data.access_token');
|
|
160
|
-
|
|
161
|
-
// Extract from HTML (regex)
|
|
162
|
-
const csrfToken = res.html().find('input[name="_token"]').attr('value');
|
|
163
|
-
|
|
164
|
-
// Extract from headers
|
|
165
|
-
const sessionId = res.headers['Set-Cookie'].match(/JSESSIONID=([^;]+)/)[1];
|
|
166
|
-
|
|
167
|
-
// Use in next request
|
|
168
|
-
http.get('https://api.example.com/profile', {
|
|
169
|
-
headers: { 'Authorization': `Bearer ${token}` },
|
|
170
|
-
});
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## Custom Metrics
|
|
176
|
-
|
|
177
|
-
```javascript
|
|
178
|
-
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
|
|
179
|
-
|
|
180
|
-
const checkoutErrors = new Counter('checkout_errors'); // cumulative count
|
|
181
|
-
const activeUsers = new Gauge('active_users'); // current value
|
|
182
|
-
const successRate = new Rate('success_rate'); // ratio
|
|
183
|
-
const transactionTime = new Trend('transaction_time_ms'); // distribution (p50/p95/p99)
|
|
184
|
-
|
|
185
|
-
// Usage inside default()
|
|
186
|
-
transactionTime.add(res.timings.duration);
|
|
187
|
-
successRate.add(res.status === 200);
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
## Modules & Extensions
|
|
193
|
-
|
|
194
|
-
### Built-in k6 modules
|
|
195
|
-
- `k6/http`
|
|
196
|
-
- `k6/ws`
|
|
197
|
-
- `k6/grpc`
|
|
198
|
-
- `k6/browser`
|
|
199
|
-
- `k6/experimental/redis`
|
|
200
|
-
- `k6/crypto`
|
|
201
|
-
- `k6/encoding`
|
|
202
|
-
|
|
203
|
-
### Popular xk6 extensions (require custom build)
|
|
204
|
-
- `xk6-kafka`
|
|
205
|
-
- `xk6-sql`
|
|
206
|
-
- `xk6-output-prometheus-remote`
|
|
207
|
-
|
|
208
|
-
Build custom k6: `xk6 build --with github.com/grafana/xk6-kafka`
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## Running k6
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
# Local run
|
|
216
|
-
k6 run script.js
|
|
217
|
-
|
|
218
|
-
# With options override
|
|
219
|
-
k6 run --vus 50 --duration 5m script.js
|
|
220
|
-
|
|
221
|
-
# With env vars
|
|
222
|
-
k6 run -e BASE_URL=https://staging.example.com script.js
|
|
223
|
-
|
|
224
|
-
# Output to multiple sinks
|
|
225
|
-
k6 run --out json=results.json --out influxdb=http://localhost:8086/k6 script.js
|
|
226
|
-
|
|
227
|
-
# Cloud run (Grafana Cloud k6)
|
|
228
|
-
k6 cloud script.js
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Output and Observability
|
|
234
|
-
|
|
235
|
-
| Output | Command |
|
|
236
|
-
|---|---|
|
|
237
|
-
| Terminal summary | Default |
|
|
238
|
-
| JSON | `--out json=results.json` |
|
|
239
|
-
| InfluxDB (Grafana stack) | `--out influxdb=http://influx:8086/k6` |
|
|
240
|
-
| Prometheus | `--out experimental-prometheus-rw` |
|
|
241
|
-
| Grafana Cloud | `k6 cloud` or `--out cloud` |
|
|
242
|
-
| CSV | `--out csv=results.csv` |
|
|
243
|
-
|
|
244
|
-
### InfluxDB + Grafana Dashboard
|
|
245
|
-
The canonical observability stack: k6 → InfluxDB → Grafana with the official k6 Grafana dashboard (ID: 2587).
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
## TypeScript Support
|
|
250
|
-
|
|
251
|
-
```bash
|
|
252
|
-
# Use k6 template with TypeScript
|
|
253
|
-
npx create-k6-app@latest --template typescript my-test
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Benefits: Type safety, IDE autocomplete, better refactoring for large test suites.
|
|
257
|
-
|
|
258
|
-
---
|
|
259
|
-
|
|
260
|
-
## k6-Specific Tips
|
|
261
|
-
|
|
262
|
-
- **Always use `SharedArray`** for data files
|
|
263
|
-
- **Use `for` loops only for sequential steps**, not concurrency
|
|
264
|
-
- **Remove `console.log` from hot paths**
|
|
265
|
-
- **Use `__ENV.BASE_URL`** for environment portability
|
|
266
|
-
- **Prefer thresholds over checks alone**
|
|
267
|
-
|
|
268
|
-
> For CI/CD integration (GitHub Actions, GitLab CI, Jenkins), see `../topics/test-execution.md`.
|
|
269
|
-
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|
|
1
|
+
# k6 Reference
|
|
2
|
+
|
|
3
|
+
> Targets: k6 v0.50+, xk6 extensions ecosystem
|
|
4
|
+
|
|
5
|
+
k6 is a developer-centric, open-source load testing tool built by Grafana Labs. Tests are written in JavaScript/TypeScript and executed with a Go runtime - making it fast, scriptable, and CI/CD-friendly.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
| Concept | Description |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **Virtual User (VU)** | A single simulated user executing the script |
|
|
14
|
+
| **Iteration** | One full execution of the default function |
|
|
15
|
+
| **Scenario** | Named execution profile with its own executor and config |
|
|
16
|
+
| **Executor** | Controls how VUs and iterations are scheduled |
|
|
17
|
+
| **Metric** | Built-in or custom measurement (counters, gauges, rates, trends) |
|
|
18
|
+
| **Check** | Inline assertion - does NOT fail the test; records pass/fail rate |
|
|
19
|
+
| **Threshold** | SLA definition - FAILS the test if breached |
|
|
20
|
+
| **Group** | Logical grouping of requests for metric aggregation |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Script Structure
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
import http from 'k6/http';
|
|
28
|
+
import { check, sleep, group } from 'k6';
|
|
29
|
+
import { Counter, Trend } from 'k6/metrics';
|
|
30
|
+
|
|
31
|
+
// Custom metrics
|
|
32
|
+
const loginErrors = new Counter('login_errors');
|
|
33
|
+
const checkoutDuration = new Trend('checkout_duration_ms');
|
|
34
|
+
|
|
35
|
+
// Test configuration
|
|
36
|
+
export const options = {
|
|
37
|
+
scenarios: {
|
|
38
|
+
ramp_up: {
|
|
39
|
+
executor: 'ramping-vus',
|
|
40
|
+
startVUs: 0,
|
|
41
|
+
stages: [
|
|
42
|
+
{ duration: '2m', target: 50 },
|
|
43
|
+
{ duration: '5m', target: 50 },
|
|
44
|
+
{ duration: '2m', target: 0 },
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
thresholds: {
|
|
49
|
+
http_req_duration: ['p(95)<500', 'p(99)<1000'],
|
|
50
|
+
http_req_failed: ['rate<0.01'],
|
|
51
|
+
login_errors: ['count<5'],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Setup (runs once before VUs start)
|
|
56
|
+
export function setup() {
|
|
57
|
+
const res = http.post('https://api.example.com/auth/token', {
|
|
58
|
+
client_id: 'perf-test',
|
|
59
|
+
client_secret: __ENV.API_SECRET,
|
|
60
|
+
});
|
|
61
|
+
return { token: res.json('access_token') };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Default VU function
|
|
65
|
+
export default function (data) {
|
|
66
|
+
group('Login Flow', () => {
|
|
67
|
+
const res = http.post('https://api.example.com/login', JSON.stringify({
|
|
68
|
+
username: `user_${__VU}@example.com`,
|
|
69
|
+
password: 'testpass',
|
|
70
|
+
}), {
|
|
71
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${data.token}` },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const ok = check(res, {
|
|
75
|
+
'login status 200': (r) => r.status === 200,
|
|
76
|
+
'has userId': (r) => r.json('userId') !== undefined,
|
|
77
|
+
});
|
|
78
|
+
if (!ok) loginErrors.add(1);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
sleep(Math.random() * 3 + 1); // Think time: 1–4 seconds
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Teardown (runs once after all VUs finish)
|
|
85
|
+
export function teardown(data) {
|
|
86
|
+
// Cleanup, invalidate tokens, etc.
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Executors
|
|
93
|
+
|
|
94
|
+
| Executor | Use Case | Key Options |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `ramping-vus` | Ramp up/down | `stages: [{duration, target}]` |
|
|
97
|
+
| `constant-vus` | Fixed concurrency | `vus`, `duration` |
|
|
98
|
+
| `per-vu-iterations` | Each VU runs N times | `vus`, `iterations` |
|
|
99
|
+
| `shared-iterations` | Total N iterations split across VUs | `vus`, `iterations` |
|
|
100
|
+
| `constant-arrival-rate` | Fixed RPS (open model) | `rate`, `duration`, `preAllocatedVUs` |
|
|
101
|
+
| `ramping-arrival-rate` | Ramping RPS (open model) | `stages`, `preAllocatedVUs` |
|
|
102
|
+
| `externally-controlled` | Controlled via k6 REST API in real-time | - |
|
|
103
|
+
|
|
104
|
+
> For closed vs open model guidance and when to use each, see `../topics/workload-design.md`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Checks vs Thresholds
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// Check: logs pass/fail but does NOT fail the test
|
|
112
|
+
check(res, { 'status 200': (r) => r.status === 200 });
|
|
113
|
+
|
|
114
|
+
// Threshold: FAILS the test run (non-zero exit code) if breached
|
|
115
|
+
// Put these in options.thresholds
|
|
116
|
+
thresholds: {
|
|
117
|
+
http_req_duration: ['p(95)<500'], // p95 must be under 500ms
|
|
118
|
+
checks: ['rate>0.99'], // At least 99% of checks must pass
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Use thresholds for SLA enforcement in CI/CD pipelines.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Parameterization
|
|
127
|
+
|
|
128
|
+
### Environment variables
|
|
129
|
+
```bash
|
|
130
|
+
k6 run -e USERNAME=testuser -e PASSWORD=secret script.js
|
|
131
|
+
```
|
|
132
|
+
```javascript
|
|
133
|
+
const username = __ENV.USERNAME;
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### SharedArray (CSV / JSON data files)
|
|
137
|
+
```javascript
|
|
138
|
+
import { SharedArray } from 'k6/data';
|
|
139
|
+
import papaparse from 'https://jslib.k6.io/papaparse/5.1.1/index.js';
|
|
140
|
+
|
|
141
|
+
const users = new SharedArray('users', function () {
|
|
142
|
+
return papaparse.parse(open('./data/users.csv'), { header: true }).data;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
export default function () {
|
|
146
|
+
const user = users[__VU % users.length]; // Round-robin by VU
|
|
147
|
+
// use user.username, user.password
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**SharedArray loads data once and shares it across all VUs** - critical for memory efficiency at high concurrency.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Correlation (Session Handling)
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Extract value from JSON response
|
|
159
|
+
const token = res.json('data.access_token');
|
|
160
|
+
|
|
161
|
+
// Extract from HTML (regex)
|
|
162
|
+
const csrfToken = res.html().find('input[name="_token"]').attr('value');
|
|
163
|
+
|
|
164
|
+
// Extract from headers
|
|
165
|
+
const sessionId = res.headers['Set-Cookie'].match(/JSESSIONID=([^;]+)/)[1];
|
|
166
|
+
|
|
167
|
+
// Use in next request
|
|
168
|
+
http.get('https://api.example.com/profile', {
|
|
169
|
+
headers: { 'Authorization': `Bearer ${token}` },
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Custom Metrics
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
import { Counter, Gauge, Rate, Trend } from 'k6/metrics';
|
|
179
|
+
|
|
180
|
+
const checkoutErrors = new Counter('checkout_errors'); // cumulative count
|
|
181
|
+
const activeUsers = new Gauge('active_users'); // current value
|
|
182
|
+
const successRate = new Rate('success_rate'); // ratio
|
|
183
|
+
const transactionTime = new Trend('transaction_time_ms'); // distribution (p50/p95/p99)
|
|
184
|
+
|
|
185
|
+
// Usage inside default()
|
|
186
|
+
transactionTime.add(res.timings.duration);
|
|
187
|
+
successRate.add(res.status === 200);
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Modules & Extensions
|
|
193
|
+
|
|
194
|
+
### Built-in k6 modules
|
|
195
|
+
- `k6/http` - HTTP/1.1 and HTTP/2
|
|
196
|
+
- `k6/ws` - WebSocket
|
|
197
|
+
- `k6/grpc` - gRPC
|
|
198
|
+
- `k6/browser` - Browser-based testing (Chromium)
|
|
199
|
+
- `k6/experimental/redis` - Redis client
|
|
200
|
+
- `k6/crypto` - Hashing and HMAC
|
|
201
|
+
- `k6/encoding` - Base64
|
|
202
|
+
|
|
203
|
+
### Popular xk6 extensions (require custom build)
|
|
204
|
+
- `xk6-kafka` - Kafka load testing
|
|
205
|
+
- `xk6-sql` - SQL database testing
|
|
206
|
+
- `xk6-output-prometheus-remote` - Push metrics to Prometheus
|
|
207
|
+
|
|
208
|
+
Build custom k6: `xk6 build --with github.com/grafana/xk6-kafka`
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Running k6
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Local run
|
|
216
|
+
k6 run script.js
|
|
217
|
+
|
|
218
|
+
# With options override
|
|
219
|
+
k6 run --vus 50 --duration 5m script.js
|
|
220
|
+
|
|
221
|
+
# With env vars
|
|
222
|
+
k6 run -e BASE_URL=https://staging.example.com script.js
|
|
223
|
+
|
|
224
|
+
# Output to multiple sinks
|
|
225
|
+
k6 run --out json=results.json --out influxdb=http://localhost:8086/k6 script.js
|
|
226
|
+
|
|
227
|
+
# Cloud run (Grafana Cloud k6)
|
|
228
|
+
k6 cloud script.js
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Output and Observability
|
|
234
|
+
|
|
235
|
+
| Output | Command |
|
|
236
|
+
|---|---|
|
|
237
|
+
| Terminal summary | Default |
|
|
238
|
+
| JSON | `--out json=results.json` |
|
|
239
|
+
| InfluxDB (Grafana stack) | `--out influxdb=http://influx:8086/k6` |
|
|
240
|
+
| Prometheus | `--out experimental-prometheus-rw` |
|
|
241
|
+
| Grafana Cloud | `k6 cloud` or `--out cloud` |
|
|
242
|
+
| CSV | `--out csv=results.csv` |
|
|
243
|
+
|
|
244
|
+
### InfluxDB + Grafana Dashboard
|
|
245
|
+
The canonical observability stack: k6 → InfluxDB → Grafana with the official k6 Grafana dashboard (ID: 2587).
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## TypeScript Support
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Use k6 template with TypeScript
|
|
253
|
+
npx create-k6-app@latest --template typescript my-test
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Benefits: Type safety, IDE autocomplete, better refactoring for large test suites.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## k6-Specific Tips
|
|
261
|
+
|
|
262
|
+
- **Always use `SharedArray`** for data files - loading data inside `default()` causes massive per-iteration overhead.
|
|
263
|
+
- **Use `for` loops only for sequential steps**, not concurrency - use VUs and executors for parallel load.
|
|
264
|
+
- **Remove `console.log` from hot paths** - dramatically reduces throughput during load runs.
|
|
265
|
+
- **Use `__ENV.BASE_URL`** for environment portability - never hardcode base URLs.
|
|
266
|
+
- **Prefer thresholds over checks alone** - without thresholds, the test always "passes" in CI/CD.
|
|
267
|
+
|
|
268
|
+
> For CI/CD integration (GitHub Actions, GitLab CI, Jenkins), see `../topics/test-execution.md`.
|
|
269
|
+
> For anti-patterns, assertions, think time, and parameterization principles, see **Key Principles** in `SKILL.md`.
|