@rulebricks/cli 2.0.1 → 2.0.3
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/benchmarks/README.md +98 -0
- package/benchmarks/Test Flow.rbf +4088 -0
- package/benchmarks/benchmark-flow.json +26 -0
- package/benchmarks/lib/payload.js +101 -0
- package/benchmarks/lib/report.js +929 -0
- package/benchmarks/qps-test.js +136 -0
- package/benchmarks/run-qps-test.sh +115 -0
- package/benchmarks/run-throughput-test.sh +123 -0
- package/benchmarks/throughput-report.html +632 -0
- package/benchmarks/throughput-results.json +298 -0
- package/benchmarks/throughput-test.js +159 -0
- package/dist/commands/deploy.js +12 -1
- package/dist/components/Wizard/steps/BenchmarkSteps.js +2 -2
- package/package.json +7 -4
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QPS (Queries Per Second) Benchmark Test
|
|
3
|
+
*
|
|
4
|
+
* Measures API responsiveness by sending individual payload requests at a constant rate.
|
|
5
|
+
* This test helps you understand:
|
|
6
|
+
* - How many individual requests your deployment can handle per second
|
|
7
|
+
* - API gateway and connection handling performance
|
|
8
|
+
* - Response latency under load
|
|
9
|
+
*
|
|
10
|
+
* Test Structure:
|
|
11
|
+
* - 1 minute warm-up phase (allows cluster to scale, excluded from results)
|
|
12
|
+
* - 4 minutes measurement phase (steady-state performance)
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* k6 run -e API_URL=https://your-instance.com/api/v1/flows/flow_id \
|
|
16
|
+
* -e API_KEY=your-api-key \
|
|
17
|
+
* qps-test.js
|
|
18
|
+
*
|
|
19
|
+
* Optional environment variables:
|
|
20
|
+
* TEST_DURATION - Measurement duration after warm-up (default: 4m)
|
|
21
|
+
* TARGET_RPS - Target requests per second (default: 500)
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { check } from "k6";
|
|
25
|
+
import http from "k6/http";
|
|
26
|
+
import { Counter, Rate, Trend } from "k6/metrics";
|
|
27
|
+
import {
|
|
28
|
+
generatePayload,
|
|
29
|
+
getConfig,
|
|
30
|
+
createRequestParams,
|
|
31
|
+
} from "./lib/payload.js";
|
|
32
|
+
import { generateQpsReport, generateQpsConsoleSummary } from "./lib/report.js";
|
|
33
|
+
|
|
34
|
+
// Load configuration
|
|
35
|
+
const config = getConfig({
|
|
36
|
+
testDuration: "4m",
|
|
37
|
+
targetRps: 500,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Custom metrics (only for measurement phase)
|
|
41
|
+
const errorRate = new Rate("errors");
|
|
42
|
+
const successRate = new Rate("successes");
|
|
43
|
+
const requestDuration = new Trend("request_duration");
|
|
44
|
+
const droppedRequests = new Counter("dropped_requests");
|
|
45
|
+
|
|
46
|
+
// k6 options with warm-up and measurement phases
|
|
47
|
+
export const options = {
|
|
48
|
+
scenarios: {
|
|
49
|
+
// Warm-up phase: 1 minute to let cluster scale
|
|
50
|
+
warm_up: {
|
|
51
|
+
executor: "constant-arrival-rate",
|
|
52
|
+
rate: config.targetRps,
|
|
53
|
+
timeUnit: "1s",
|
|
54
|
+
duration: "1m",
|
|
55
|
+
preAllocatedVUs: Math.min(config.targetRps, 200),
|
|
56
|
+
maxVUs: Math.min(config.targetRps * 2, 1000),
|
|
57
|
+
exec: "warmUp",
|
|
58
|
+
tags: { phase: "warmup" },
|
|
59
|
+
},
|
|
60
|
+
// Measurement phase: actual test after warm-up
|
|
61
|
+
qps_test: {
|
|
62
|
+
executor: "constant-arrival-rate",
|
|
63
|
+
rate: config.targetRps,
|
|
64
|
+
timeUnit: "1s",
|
|
65
|
+
duration: config.testDuration,
|
|
66
|
+
preAllocatedVUs: Math.min(config.targetRps, 200),
|
|
67
|
+
maxVUs: Math.min(config.targetRps * 2, 1000),
|
|
68
|
+
startTime: "1m", // Start after warm-up
|
|
69
|
+
exec: "measureTest",
|
|
70
|
+
tags: { phase: "measurement" },
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
thresholds: {
|
|
74
|
+
// Only apply thresholds to measurement phase
|
|
75
|
+
"http_req_duration{phase:measurement}": ["p(95)<500", "p(99)<1000"],
|
|
76
|
+
"errors{phase:measurement}": ["rate<0.05"],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Request parameters
|
|
81
|
+
const params = createRequestParams(config.apiKey);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Warm-up function - same as test but metrics tagged differently
|
|
85
|
+
*/
|
|
86
|
+
export function warmUp() {
|
|
87
|
+
const payload = generatePayload();
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
http.post(config.apiUrl, JSON.stringify(payload), params);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Ignore errors during warm-up
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Measurement test function - sends individual requests
|
|
98
|
+
*/
|
|
99
|
+
export function measureTest() {
|
|
100
|
+
const payload = generatePayload();
|
|
101
|
+
const start = Date.now();
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const response = http.post(config.apiUrl, JSON.stringify(payload), params);
|
|
105
|
+
|
|
106
|
+
const duration = Date.now() - start;
|
|
107
|
+
requestDuration.add(duration);
|
|
108
|
+
|
|
109
|
+
const success = check(response, {
|
|
110
|
+
"status is 200": (r) => r.status === 200,
|
|
111
|
+
"valid response": (r) => r.body && r.body.length > 0,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
errorRate.add(!success);
|
|
115
|
+
successRate.add(success);
|
|
116
|
+
|
|
117
|
+
if (!success) {
|
|
118
|
+
droppedRequests.add(1);
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
errorRate.add(1);
|
|
122
|
+
successRate.add(0);
|
|
123
|
+
droppedRequests.add(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generate summary report
|
|
129
|
+
*/
|
|
130
|
+
export function handleSummary(data) {
|
|
131
|
+
return {
|
|
132
|
+
stdout: generateQpsConsoleSummary(data, config),
|
|
133
|
+
"qps-report.html": generateQpsReport(data, config),
|
|
134
|
+
"qps-results.json": JSON.stringify(data, null, 2),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# QPS Benchmark Test Runner
|
|
4
|
+
# Runs the QPS test and opens the HTML report in your browser
|
|
5
|
+
#
|
|
6
|
+
# Usage: ./run-qps-test.sh -u <API_URL> -k <API_KEY> [options]
|
|
7
|
+
#
|
|
8
|
+
# Options:
|
|
9
|
+
# -u, --url API URL (required)
|
|
10
|
+
# -k, --key API key (required)
|
|
11
|
+
# -d, --duration Measurement duration after 1m warm-up (default: 4m)
|
|
12
|
+
# -r, --rps Target RPS (default: 500)
|
|
13
|
+
# -n, --no-open Don't open report in browser
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
# Colors
|
|
19
|
+
RED='\033[0;31m'
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
CYAN='\033[0;36m'
|
|
22
|
+
NC='\033[0m'
|
|
23
|
+
|
|
24
|
+
# Defaults
|
|
25
|
+
DURATION="4m"
|
|
26
|
+
RPS="500"
|
|
27
|
+
OPEN_REPORT=true
|
|
28
|
+
|
|
29
|
+
# Parse arguments
|
|
30
|
+
while [[ $# -gt 0 ]]; do
|
|
31
|
+
case $1 in
|
|
32
|
+
-u|--url)
|
|
33
|
+
API_URL="$2"
|
|
34
|
+
shift 2
|
|
35
|
+
;;
|
|
36
|
+
-k|--key)
|
|
37
|
+
API_KEY="$2"
|
|
38
|
+
shift 2
|
|
39
|
+
;;
|
|
40
|
+
-d|--duration)
|
|
41
|
+
DURATION="$2"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
-r|--rps)
|
|
45
|
+
RPS="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
-n|--no-open)
|
|
49
|
+
OPEN_REPORT=false
|
|
50
|
+
shift
|
|
51
|
+
;;
|
|
52
|
+
-h|--help)
|
|
53
|
+
echo "Usage: ./run-qps-test.sh -u <API_URL> -k <API_KEY> [options]"
|
|
54
|
+
echo ""
|
|
55
|
+
echo "Options:"
|
|
56
|
+
echo " -u, --url API URL (required)"
|
|
57
|
+
echo " -k, --key API key (required)"
|
|
58
|
+
echo " -d, --duration Test duration (default: 2m)"
|
|
59
|
+
echo " -r, --rps Target RPS (default: 500)"
|
|
60
|
+
echo " -n, --no-open Don't open report in browser"
|
|
61
|
+
exit 0
|
|
62
|
+
;;
|
|
63
|
+
*)
|
|
64
|
+
echo -e "${RED}Unknown option: $1${NC}"
|
|
65
|
+
exit 1
|
|
66
|
+
;;
|
|
67
|
+
esac
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
# Validate required args
|
|
71
|
+
if [ -z "$API_URL" ]; then
|
|
72
|
+
echo -e "${RED}Error: API_URL is required (-u)${NC}"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
if [ -z "$API_KEY" ]; then
|
|
77
|
+
echo -e "${RED}Error: API_KEY is required (-k)${NC}"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Get script directory
|
|
82
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
83
|
+
|
|
84
|
+
echo -e "${CYAN}Running QPS Benchmark...${NC}"
|
|
85
|
+
echo " URL: $API_URL"
|
|
86
|
+
echo " Warm-up: 1m"
|
|
87
|
+
echo " Duration: $DURATION (after warm-up)"
|
|
88
|
+
echo " Target: $RPS RPS"
|
|
89
|
+
echo ""
|
|
90
|
+
|
|
91
|
+
# Run k6 test
|
|
92
|
+
k6 run \
|
|
93
|
+
-e API_URL="$API_URL" \
|
|
94
|
+
-e API_KEY="$API_KEY" \
|
|
95
|
+
-e TEST_DURATION="$DURATION" \
|
|
96
|
+
-e TARGET_RPS="$RPS" \
|
|
97
|
+
"$SCRIPT_DIR/qps-test.js" || true
|
|
98
|
+
|
|
99
|
+
# Open report in browser
|
|
100
|
+
if [ "$OPEN_REPORT" = true ] && [ -f "$SCRIPT_DIR/qps-report.html" ]; then
|
|
101
|
+
echo ""
|
|
102
|
+
echo -e "${GREEN}Opening report in browser...${NC}"
|
|
103
|
+
|
|
104
|
+
# Cross-platform open command
|
|
105
|
+
if command -v open &> /dev/null; then
|
|
106
|
+
open "$SCRIPT_DIR/qps-report.html"
|
|
107
|
+
elif command -v xdg-open &> /dev/null; then
|
|
108
|
+
xdg-open "$SCRIPT_DIR/qps-report.html"
|
|
109
|
+
elif command -v start &> /dev/null; then
|
|
110
|
+
start "$SCRIPT_DIR/qps-report.html"
|
|
111
|
+
else
|
|
112
|
+
echo "Report saved to: $SCRIPT_DIR/qps-report.html"
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Throughput Benchmark Test Runner
|
|
4
|
+
# Runs the throughput test and opens the HTML report in your browser
|
|
5
|
+
#
|
|
6
|
+
# Usage: ./run-throughput-test.sh -u <API_URL> -k <API_KEY> [options]
|
|
7
|
+
#
|
|
8
|
+
# Options:
|
|
9
|
+
# -u, --url API URL (required)
|
|
10
|
+
# -k, --key API key (required)
|
|
11
|
+
# -d, --duration Measurement duration after 1m warm-up (default: 4m)
|
|
12
|
+
# -r, --rps Target RPS (default: 100)
|
|
13
|
+
# -b, --bulk Bulk size (default: 50)
|
|
14
|
+
# -n, --no-open Don't open report in browser
|
|
15
|
+
#
|
|
16
|
+
|
|
17
|
+
set -e
|
|
18
|
+
|
|
19
|
+
# Colors
|
|
20
|
+
RED='\033[0;31m'
|
|
21
|
+
GREEN='\033[0;32m'
|
|
22
|
+
CYAN='\033[0;36m'
|
|
23
|
+
NC='\033[0m'
|
|
24
|
+
|
|
25
|
+
# Defaults
|
|
26
|
+
DURATION="4m"
|
|
27
|
+
RPS="100"
|
|
28
|
+
BULK_SIZE="50"
|
|
29
|
+
OPEN_REPORT=true
|
|
30
|
+
|
|
31
|
+
# Parse arguments
|
|
32
|
+
while [[ $# -gt 0 ]]; do
|
|
33
|
+
case $1 in
|
|
34
|
+
-u|--url)
|
|
35
|
+
API_URL="$2"
|
|
36
|
+
shift 2
|
|
37
|
+
;;
|
|
38
|
+
-k|--key)
|
|
39
|
+
API_KEY="$2"
|
|
40
|
+
shift 2
|
|
41
|
+
;;
|
|
42
|
+
-d|--duration)
|
|
43
|
+
DURATION="$2"
|
|
44
|
+
shift 2
|
|
45
|
+
;;
|
|
46
|
+
-r|--rps)
|
|
47
|
+
RPS="$2"
|
|
48
|
+
shift 2
|
|
49
|
+
;;
|
|
50
|
+
-b|--bulk)
|
|
51
|
+
BULK_SIZE="$2"
|
|
52
|
+
shift 2
|
|
53
|
+
;;
|
|
54
|
+
-n|--no-open)
|
|
55
|
+
OPEN_REPORT=false
|
|
56
|
+
shift
|
|
57
|
+
;;
|
|
58
|
+
-h|--help)
|
|
59
|
+
echo "Usage: ./run-throughput-test.sh -u <API_URL> -k <API_KEY> [options]"
|
|
60
|
+
echo ""
|
|
61
|
+
echo "Options:"
|
|
62
|
+
echo " -u, --url API URL (required)"
|
|
63
|
+
echo " -k, --key API key (required)"
|
|
64
|
+
echo " -d, --duration Test duration (default: 2m)"
|
|
65
|
+
echo " -r, --rps Target RPS (default: 100)"
|
|
66
|
+
echo " -b, --bulk Bulk size (default: 50)"
|
|
67
|
+
echo " -n, --no-open Don't open report in browser"
|
|
68
|
+
exit 0
|
|
69
|
+
;;
|
|
70
|
+
*)
|
|
71
|
+
echo -e "${RED}Unknown option: $1${NC}"
|
|
72
|
+
exit 1
|
|
73
|
+
;;
|
|
74
|
+
esac
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
# Validate required args
|
|
78
|
+
if [ -z "$API_URL" ]; then
|
|
79
|
+
echo -e "${RED}Error: API_URL is required (-u)${NC}"
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
if [ -z "$API_KEY" ]; then
|
|
84
|
+
echo -e "${RED}Error: API_KEY is required (-k)${NC}"
|
|
85
|
+
exit 1
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Get script directory
|
|
89
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
90
|
+
|
|
91
|
+
echo -e "${CYAN}Running Throughput Benchmark...${NC}"
|
|
92
|
+
echo " URL: $API_URL"
|
|
93
|
+
echo " Warm-up: 1m"
|
|
94
|
+
echo " Duration: $DURATION (after warm-up)"
|
|
95
|
+
echo " Target: $RPS RPS × $BULK_SIZE = $((RPS * BULK_SIZE)) solutions/sec"
|
|
96
|
+
echo ""
|
|
97
|
+
|
|
98
|
+
# Run k6 test (don't exit on threshold failures - we still want to open the report)
|
|
99
|
+
k6 run \
|
|
100
|
+
-e API_URL="$API_URL" \
|
|
101
|
+
-e API_KEY="$API_KEY" \
|
|
102
|
+
-e TEST_DURATION="$DURATION" \
|
|
103
|
+
-e TARGET_RPS="$RPS" \
|
|
104
|
+
-e BULK_SIZE="$BULK_SIZE" \
|
|
105
|
+
"$SCRIPT_DIR/throughput-test.js" || true
|
|
106
|
+
|
|
107
|
+
# Open report in browser
|
|
108
|
+
if [ "$OPEN_REPORT" = true ] && [ -f "$SCRIPT_DIR/throughput-report.html" ]; then
|
|
109
|
+
echo ""
|
|
110
|
+
echo -e "${GREEN}Opening report in browser...${NC}"
|
|
111
|
+
|
|
112
|
+
# Cross-platform open command
|
|
113
|
+
if command -v open &> /dev/null; then
|
|
114
|
+
open "$SCRIPT_DIR/throughput-report.html"
|
|
115
|
+
elif command -v xdg-open &> /dev/null; then
|
|
116
|
+
xdg-open "$SCRIPT_DIR/throughput-report.html"
|
|
117
|
+
elif command -v start &> /dev/null; then
|
|
118
|
+
start "$SCRIPT_DIR/throughput-report.html"
|
|
119
|
+
else
|
|
120
|
+
echo "Report saved to: $SCRIPT_DIR/throughput-report.html"
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|