Skip to content

Commit 50f41d0

Browse files
authored
Load tests: Improve scripts (#633)
* Load tests: Upgrade code and add SA token support * fix simple docker env * fix custom config docker env * improve doc
1 parent 21323e4 commit 50f41d0

File tree

6 files changed

+77
-67
lines changed

6 files changed

+77
-67
lines changed

devenv/docker/custom-config/docker-compose.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
version: '2'
2-
31
services:
42
grafana:
53
image: grafana/grafana:latest
64
ports:
7-
- 3000
5+
- 3000:3000
86
environment:
97
GF_RENDERING_SERVER_URL: http://renderer:8081/render
108
GF_RENDERING_CALLBACK_URL: http://grafana:3000/

devenv/docker/simple/docker-compose.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
version: '2'
2-
31
services:
42
grafana:
53
image: grafana/grafana:latest
64
ports:
7-
- 3000
5+
- 3000:3000
86
environment:
97
GF_RENDERING_SERVER_URL: http://renderer:8081/render
108
GF_RENDERING_CALLBACK_URL: http://grafana:3000/

devenv/loadtest/README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ Runs load tests and checks using [k6](https://k6.io/).
44

55
## Prerequisites
66

7-
Docker
7+
- Docker
8+
- Grafana instance running (you can use the environment in `devenv/docker/simple`)
89

910
## Run
1011

@@ -20,11 +21,6 @@ Run load test for custom duration:
2021
$ ./run.sh -d 10s
2122
```
2223

23-
Run only 1 iteration of the load test (useful for testing):
24-
25-
```bash
26-
$ ./run.sh -i 1
27-
2824
Run load test for custom target url:
2925

3026
```bash
@@ -37,6 +33,18 @@ Run load test for 10 virtual users:
3733
$ ./run.sh -v 10
3834
```
3935

36+
Run only 1 iteration of the load test (useful for testing), note that the number of iterations can't be less than the number of virtual users:
37+
38+
```bash
39+
$ ./run.sh -i 1 -v 1
40+
```
41+
42+
Run load test using a service account token instead of default username/password:
43+
44+
```bash
45+
$ ./run.sh -a glsa_xxxx
46+
```
47+
4048
Example output:
4149

4250
```bash

devenv/loadtest/modules/client.js

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import http from "k6/http";
1+
import http from 'k6/http';
22

33
export const DatasourcesEndpoint = class DatasourcesEndpoint {
44
constructor(httpClient) {
@@ -68,31 +68,34 @@ export const UIEndpoint = class UIEndpoint {
6868

6969
login(username, pwd) {
7070
const payload = { user: username, password: pwd };
71-
return this.httpClient.formPost('/login', payload);
71+
return this.httpClient.post('/login', JSON.stringify(payload));
7272
}
7373

7474
renderPanel(orgId, dashboardUid, panelId) {
75-
return this.httpClient.get(
76-
`/render/d-solo/${dashboardUid}/graph-panel`,
77-
{
78-
orgId,
79-
panelId,
80-
width: 1000,
81-
height: 500,
82-
tz: 'Europe/Stockholm',
83-
}
84-
);
75+
return this.httpClient.get(`/render/d-solo/${dashboardUid}/graph-panel`, {
76+
orgId,
77+
panelId: `panel-${panelId}`,
78+
width: 1000,
79+
height: 500,
80+
tz: 'Europe/Stockholm',
81+
timeout: '10',
82+
});
8583
}
86-
}
84+
};
8785

8886
export const GrafanaClient = class GrafanaClient {
8987
constructor(httpClient) {
9088
httpClient.onBeforeRequest = (params) => {
89+
params.headers = params.headers || {};
90+
9191
if (this.orgId && this.orgId > 0) {
92-
params.headers = params.headers || {};
93-
params.headers["X-Grafana-Org-Id"] = this.orgId;
92+
params.headers['X-Grafana-Org-Id'] = this.orgId;
9493
}
95-
}
94+
95+
if (this.authToken) {
96+
params.headers['Authorization'] = `Bearer ${this.authToken}`;
97+
}
98+
};
9699

97100
this.raw = httpClient;
98101
this.dashboards = new DashboardsEndpoint(httpClient.withUrl('/api'));
@@ -118,7 +121,11 @@ export const GrafanaClient = class GrafanaClient {
118121
withOrgId(orgId) {
119122
this.orgId = orgId;
120123
}
121-
}
124+
125+
withAuthToken(authToken) {
126+
this.authToken = authToken;
127+
}
128+
};
122129

123130
export const BaseClient = class BaseClient {
124131
constructor(url, subUrl) {
@@ -135,35 +142,28 @@ export const BaseClient = class BaseClient {
135142
}
136143

137144
withUrl(subUrl) {
138-
let c = new BaseClient(this.url, subUrl);
145+
let c = new BaseClient(this.url, subUrl);
139146
c.onBeforeRequest = this.onBeforeRequest;
140147
return c;
141148
}
142149

143-
beforeRequest(params) {
144-
145-
}
150+
beforeRequest(params) {}
146151

147152
get(url, queryParams, params) {
148153
params = params || {};
149154
this.onBeforeRequest(params);
150155

151156
if (queryParams) {
152-
url += '?' + Array.from(Object.entries(queryParams)).map(([key, value]) =>
153-
`${key}=${encodeURIComponent(value)}`
154-
).join('&');
157+
url +=
158+
'?' +
159+
Array.from(Object.entries(queryParams))
160+
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
161+
.join('&');
155162
}
156163

157164
return http.get(this.url + url, params);
158165
}
159166

160-
formPost(url, body, params) {
161-
params = params || {};
162-
this.beforeRequest(params);
163-
this.onBeforeRequest(params);
164-
return http.post(this.url + url, body, params);
165-
}
166-
167167
post(url, body, params) {
168168
params = params || {};
169169
params.headers = params.headers || {};
@@ -206,8 +206,8 @@ export const BaseClient = class BaseClient {
206206

207207
return http.batch(requests);
208208
}
209-
}
209+
};
210210

211211
export const createClient = (url) => {
212212
return new GrafanaClient(new BaseClient(url, ''));
213-
}
213+
};

devenv/loadtest/render_test.js

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
import { check, group } from 'k6';
22
import { createClient } from './modules/client.js';
3-
import {
4-
createTestOrgIfNotExists,
5-
upsertTestdataDatasource,
6-
upsertDashboard,
7-
} from './modules/util.js';
3+
import { createTestOrgIfNotExists, upsertTestdataDatasource, upsertDashboard } from './modules/util.js';
84

95
export let options = {
106
noCookiesReset: true,
11-
thresholds: { checks: [ { threshold: 'rate=1', abortOnFail: true } ] },
127
};
138

149
let endpoint = __ENV.URL || 'http://localhost:3000';
10+
let authToken = __ENV.AUTH_TOKEN || '';
11+
1512
const client = createClient(endpoint);
1613
const dashboard = JSON.parse(open('fixtures/graph_panel.json'));
1714

1815
export const setup = () => {
19-
group("user authenticates thru ui with username and password", () => {
20-
let res = client.ui.login('admin', 'admin');
16+
if (!authToken) {
17+
group('user authenticates thru ui with username and password', () => {
18+
let res = client.ui.login('admin', 'admin');
2119

22-
check(res, {
23-
'response status is 200': (r) => r.status === 200,
20+
check(res, {
21+
'response status is 200': (r) => r.status === 200,
22+
});
2423
});
25-
});
24+
} else {
25+
client.withAuthToken(authToken);
26+
}
2627

2728
const orgId = createTestOrgIfNotExists(client);
2829
client.withOrgId(orgId);
@@ -39,19 +40,19 @@ export default (data) => {
3940
client.loadCookies(data.cookies);
4041
client.withOrgId(data.orgId);
4142

42-
group("render test", () => {
43-
group("render graph panel", () => {
44-
const response = client.ui.renderPanel(
45-
data.orgId,
46-
dashboard.uid,
47-
dashboard.panels[0].id,
48-
);
43+
if (authToken) {
44+
client.withAuthToken(authToken);
45+
}
46+
47+
group('render test', () => {
48+
group('render graph panel', () => {
49+
const response = client.ui.renderPanel(data.orgId, dashboard.uid, dashboard.panels[0].id);
4950
check(response, {
5051
'response status is 200': (r) => r.status === 200,
5152
'response is a PNG': (r) => r.headers['Content-Type'] == 'image/png',
5253
});
5354
});
5455
});
55-
}
56+
};
5657

57-
export const teardown = () => {}
58+
export const teardown = () => {};

devenv/loadtest/run.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ cd "$(dirname $0)"
55
run() {
66
local duration='15m'
77
local url='http://localhost:3000'
8+
local authToken=''
89
local vus='2'
910
local iterationsOption=''
1011

11-
while getopts ":d:i:u:v:" o; do
12+
while getopts ":d:i:u:v:a:" o; do
1213
case "${o}" in
1314
d)
1415
duration=${OPTARG}
@@ -22,6 +23,9 @@ run() {
2223
v)
2324
vus=${OPTARG}
2425
;;
26+
a)
27+
authToken=${OPTARG}
28+
;;
2529
esac
2630
done
2731
shift $((OPTIND-1))
@@ -31,8 +35,9 @@ run() {
3135
--network=host \
3236
--mount type=bind,source=$PWD,destination=/src \
3337
-e URL=$url \
38+
-e AUTH_TOKEN=$authToken \
3439
--rm \
35-
loadimpact/k6:master run \
40+
grafana/k6:master run \
3641
--vus $vus \
3742
--duration $duration \
3843
$iterationsOption \

0 commit comments

Comments
 (0)