├── README.md ├── install-ubuntu.sh └── magento.js /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 K6-performance toolkit 2 | 3 | k6 Magento 2 is a modern performance under load-testing tool when more than one user hits your page, built on years of experience in the Magento 2 performance and testing industries. It's built to be powerful, extensible, and full-featured. The key design goal is to provide the best developer experience. 4 | 5 | ![New Project (17)](https://github.com/Genaker/magento-k6-performance/assets/9213670/73f0334f-ea2f-40fe-9ae9-5c3e6bd285cd) 6 | 7 | ## Installation 8 | 9 | ``` 10 | # Download ARM binary 11 | wget https://github.com/grafana/k6/releases/download/v0.50.0/k6-v0.50.0-linux-arm64.tar.gz 12 | 13 | # Extract 14 | tar -xvzf k6-v0.50.0-linux-arm64.tar.gz 15 | sudo mv k6-v0.50.0-linux-arm64/k6 /usr/local/bin/ 16 | 17 | # Verify 18 | k6 version 19 | ``` 20 | 21 | ## Linux 22 | ## Debian/Ubuntu 23 | ``` 24 | sudo gpg -k 25 | sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 26 | echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list 27 | sudo apt-get update 28 | sudo apt-get install k6 29 | ``` 30 | 31 | If you are behind a firewall or proxy 32 | There have been reports of users being unable to download the key from Ubuntu's key-server using apt-key command due to firewalls or proxies blocking their requests. If you experience this issue, you may try this alternative approach instead: 33 | ``` 34 | wget -q -O - https://bintray.com/user/downloadSubjectPublicKey?username=bintray | sudo apt-key add - 35 | ``` 36 | or just install script 37 | ``` 38 | bash install-ubuntu.sh 39 | ``` 40 | ## Red Hat/CentOS 41 | ``` 42 | wget https://bintray.com/loadimpact/rpm/rpm -O bintray-loadimpact-rpm.repo 43 | sudo mv bintray-loadimpact-rpm.repo /etc/yum.repos.d/ 44 | sudo yum install k6 45 | ``` 46 | ## Mac (brew) 47 | 48 | ## Brew 49 | ``` 50 | brew install k6 51 | ``` 52 | ## Docker 53 | ``` 54 | docker pull loadimpact/k6 55 | ``` 56 | 57 | # Usage with Magento 58 | 59 | ``` 60 | k6 run magento.js -e url=https://example.com -u 200 -i 6000 --include-system-env-vars=false 61 | ``` 62 | Where: 63 | 64 | magento.js - script name 65 | -e url= site URL to test as env variable 66 | -e sleep=0.2 etc. add sleep after HTTP response 67 | -u virtual users / concurrency / threads 68 | -i number of iteration 69 | --include-system-env-vars=false - don't include OS/system env variables 70 | 71 | # Load Testing Guide 72 | 73 | ## Installation 74 | ```bash 75 | # Install k6 76 | sudo apt-get update && sudo apt-get install k6 77 | 78 | # Verify installation 79 | k6 version 80 | ``` 81 | 82 | ## Basic Test Scenarios 83 | 84 | ### 1. Quick Smoke Test 85 | ```bash 86 | k6 run -e URL="http://yoursite.com/product/36" \ 87 | --vus 10 --duration 30s \ 88 | magento.js 89 | ``` 90 | 91 | ### 2. Average Load Simulation 92 | ```bash 93 | k6 run -e URL="http://yoursite.com/product/36" \ 94 | --vus 100 --duration 5m \ 95 | magento.js 96 | ``` 97 | 98 | ### 3. Peak Load Stress Test 99 | ```bash 100 | k6 run -e URL="http://yoursite.com/product/36" \ 101 | --vus 500 --duration 10m \ 102 | --rps 200 \ 103 | magento.js 104 | ``` 105 | 106 | ## Advanced Scenarios 107 | 108 | ### 4. Ramp-up Pattern 109 | ```bash 110 | k6 run -e URL="http://yoursite.com/product/36" \ 111 | --stage 2m:200 --stage 5m:200 --stage 1m:0 \ 112 | magento.js 113 | ``` 114 | 115 | ### 5. Spike Testing 116 | ```bash 117 | k6 run -e URL="http://yoursite.com/product/36" \ 118 | --stage 30s:1000 --stage 1m:1000 --stage 30s:50 \ 119 | magento.js 120 | ``` 121 | 122 | ## Configuration Options 123 | 124 | ### Environment Variables 125 | | Variable | Description | Default | 126 | |-------------|----------------------------|-------------| 127 | | `URL` | Target endpoint | Required | 128 | | `METHOD` | HTTP Method | `GET` | 129 | | `N` | Iterations per VU | `1` | 130 | | `SLEEP` | Delay between requests (s) | `0` | 131 | | `FPC` | Full Page Cache | `OFF` | 132 | | `USERNAME` | Basic Auth username | - | 133 | | `PASSWORD` | Basic Auth password | - | 134 | 135 | ## Example Command with All Options 136 | ```bash 137 | k6 run \ 138 | -e URL="http://yoursite.com/product/36" \ 139 | -e METHOD=GET \ 140 | -e N=5 \ 141 | -e SLEEP=0.5 \ 142 | -e FPC=ON \ 143 | -e USERNAME=test -e PASSWORD=test123 \ 144 | --vus 200 \ 145 | --duration 10m \ 146 | --rps 100 \ 147 | --out json=metrics.json \ 148 | magento.js 149 | ``` 150 | 151 | ## Results Interpretation 152 | 153 | Key metrics to monitor: 154 | - **VUs**: Active virtual users 155 | - **iterations**: Completed requests 156 | - **http_req_duration**: Response times 157 | - p(95): 95th percentile 158 | - max: Maximum response time 159 | - **http_req_failed**: Error rate 160 | - **rps**: Requests per second 161 | 162 | ## Generating Reports 163 | 164 | 1. JSON output: 165 | ```bash 166 | k6 run --out json=results.json magento.js 167 | ``` 168 | 169 | 2. HTML report (requires k6-html-reporter): 170 | ```bash 171 | k6 run --out json=results.json magento.js 172 | npx k6-html-reporter -i results.json -o report.html 173 | ``` 174 | 175 | ## Best Practices 176 | 177 | 1. Start with low VUs and gradually increase 178 | 2. Monitor application metrics during tests 179 | 3. Run tests from different locations 180 | 4. Combine with cache busting (FPC=OFF) 181 | 5. Test different endpoints simultaneously 182 | 183 | ## Troubleshooting 184 | 185 | **Common Errors**: 186 | - `405 Method Not Allowed`: Ensure correct HTTP method case (UPPERCASE) 187 | - `429 Too Many Requests`: Reduce RPS/VUs 188 | - `500 Errors`: Check application logs 189 | 190 | **Debug Command**: 191 | ```bash 192 | k6 run -e URL="http://yoursite.com/product/36" \ 193 | --http-debug=full \ 194 | --vus 1 --iterations 1 \ 195 | magento.js 196 | ``` 197 | 198 | # Full K6 documentation 199 | 200 | [https://k6.io/docs/](https://k6.io/docs/) 201 | 202 | -------------------------------------------------------------------------------- /install-ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo gpg -k 3 | sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 4 | echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list 5 | sudo apt-get update 6 | sudo apt-get install k6 7 | sudo apt-get install wget 8 | wget https://raw.githubusercontent.com/Genaker/magento-k6-performance/main/magento.js 9 | echo "TEST GOOGLE.com" 10 | k6 run magento.js -e url=https://www.google.com/ -u 1 -i 10 --include-system-env-vars=false 11 | -------------------------------------------------------------------------------- /magento.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http'; 2 | import encoding from 'k6/encoding'; 3 | import { sleep } from 'k6'; 4 | import { Trend, Rate } from 'k6/metrics'; 5 | 6 | 7 | const username = __ENV.USERNAME || 'defaultUser'; 8 | const password = __ENV.PASSWORD || 'defaultPassword'; 9 | 10 | const responseTimes = new Trend('response_times'); 11 | const errorRate = new Rate('errors'); 12 | 13 | export let options = { 14 | vus: 1, 15 | discardResponseBodies: true, 16 | insecureSkipTLSVerify: true, 17 | summaryTrendStats: ['min', 'med', 'avg', 'max', 'p(95)'], 18 | thresholds: { 19 | //'errors': ['rate<1'], 20 | 'response_times': ['p(95)<10000'] 21 | } 22 | }; 23 | 24 | export function setup() { 25 | if (!__ENV.URL) throw new Error('Missing required URL parameter'); 26 | if (__ENV.N && isNaN(__ENV.N)) throw new Error('Parameter N must be a number'); 27 | 28 | return { 29 | url: __ENV.URL, 30 | method: (__ENV.METHOD || 'GET').toUpperCase(), 31 | separ: __ENV.URL.includes('?') ? '&' : '?', 32 | n: parseInt(__ENV.N) || 1, 33 | sleep: parseFloat(__ENV.SLEEP) || 0, 34 | fpc_enabled: __ENV.FPC ? __ENV.FPC.toUpperCase() === 'ON' : false 35 | }; 36 | } 37 | 38 | export default function (data) { 39 | // Initialize headers 40 | const headers = { 41 | 'User-Agent': 'k6/MagentoLoadTest/1.25' 42 | }; 43 | 44 | // Add auth only if credentials are provided 45 | if (__ENV.USERNAME && __ENV.PASSWORD) { 46 | headers.Authorization = `Basic ${encoding.b64encode(`${__ENV.USERNAME}:${__ENV.PASSWORD}`)}`; 47 | } 48 | //console.log(`FPC Status: ${data.fpc_enabled ? 'ENABLED' : 'DISABLED'}`); 49 | const url = data.fpc_enabled ? data.url : `${data.url}${data.separ}fpc=${__VU}_${__ITER}_${Date.now()}`; 50 | const res = http.request(data.method, url, null, { headers: headers }); 51 | //console.log(`FINAL URL: ${url}`); 52 | // Track metrics 53 | responseTimes.add(res.timings.duration); 54 | errorRate.add(res.status !== 200); 55 | 56 | // Detailed logging with URL and method 57 | console.log(`[${data.method.toUpperCase()}] ${data.url}`); 58 | console.log(`Response time: ${res.timings.duration} ms | Status: ${res.status} | TTFB: ${res.timings.waiting} ms`); 59 | console.log('------------------------------------'); 60 | 61 | // Error logging 62 | if (res.status !== 200) { 63 | console.error(`[VU${__VU}] ${data.method.toUpperCase()} ${data.url} - Error ${res.status}`); 64 | } 65 | 66 | sleep(data.sleep); 67 | } 68 | 69 | export function teardown(data) { 70 | console.log(`\nTest Summary: 71 | URL: ${data.url} 72 | Method: ${data.method.toUpperCase()} 73 | Iterations: ${data.n} 74 | Cache Strategy: ${data.fpc ? 'FPC Enabled' : 'Cache Busted'} 75 | Avg Sleep: ${data.sleep}s`); 76 | } 77 | --------------------------------------------------------------------------------