Candia is the longest siege in history. Here, it is a load-testing tool that allows to model your scenario as initiated requests per interval.
Candia does not allow you to craft complex funnels, following the browsing pattern of a user, with conditions and complex scenarii. Instead, it gives you tool to control how many requests are initiated for a given period of time. For this, currently, you can use four strategies:
For each spawned request, a random request specification is picked from the configured upstreams.
A scenario is represented as the following configuration file:
``` options: timeout: 5
schedulers: - kind: SteppedConstant steps: - duration: 30 count: 10 interval: 2 - duration: 30 count: 20 interval: 2 - kind: Pause args: duration: 5 - kind: RampUp args: duration: 60 from: 10 to: 100 interval: 5
upstreams: - name: example method: GET url: https://example.com/api/users/1 headers: Accept: application/json Authorization: Bearer abcdefghijklmnopqrstuvwxyz ```
For now, only GET
and POST
requests are supported.
As well as setting each request's timeout, the timeout
setting defines how long the runner will wait when all schedulers are done to possibly wait for to-be-fulfilled requests. Preferably, we will, in the future, actually check if all requests have been fulfilled.
By default, for each scheduler, a random upstream is picked for each request sent. You can constraint a scheduler to using one or several specific upstreams by using an upstream filter:
schedulers:
- kind: RampUp
args:
duration: 60
from: 10
to: 100
interval: 5
upstreams: ["upstream1", "upstream2"]
This scheduler will pick a random upstream between upstream1
and upstream2
and will never hit another one.
You have the possibility, for some configuration attributes, to replace substrings from random seed data taken from data sources. For now, you can interpolate data in url strings, header values and bodies. For retrieving data, there are two strategies for now: from text files (one value per line), and from static arrays defined in the configuration.
Every data source must be declared in a separate datasource
section of the configuration, with a label which will be used in strings, and used as {label}
.
The following methods of retrieving data can be used:
array
: each item in the YAML array is mapped to a value in the pool.file
: each line is mapped to a value in the pool.directory
: each file in the directory is mapped to a value in the pool.``` upstreams: - method: GET url: https://{domain}/user?user={users} headers: Authorization: {users} - method: POST url: https://{domain}/user bodies: "{bodies}"
datasources:
bodies:
kind: directory
source: /tmp/bodies
domains:
kind: array
data:
- example.net
- api.example.net
users:
kind: file
source: /tmp/users
```
Those interpolators, in the future, will be usable in more locations and more data sources will be implemeted (such as from a directory of files).
``` $ candia check config.yml OPTIONS: - timeout: 5s
SCHEDULERS: - kind: RampUp ramp up requests every 1s from 1 to 100 for 15s
kind: Pause pause for 10s
kind: Constant 100 requests every 5s for 10s
UPSTREAMS: - name: localhost GET http://127.0.0.1:8080/ ```
``` $ candia run config.yml INFO: running batch with 1 requests over 1 seconds... INFO: running batch with 7 requests over 1 seconds... INFO: running batch with 14 requests over 1 seconds... [...] INFO: running batch with 86 requests over 1 seconds... INFO: running batch with 93 requests over 1 seconds... INFO: running batch with 100 requests over 1 seconds...
INFO: done.
STATISTICS: Requests count 801 Success count: 801 Error count: 0 Success rate: 100.00% Mean: 17ms Std. dev.: 14ms 90th percentile: 34ms 95th percentile: 46ms 99th percentile: 69ms ```
On top of the simple statistics returned by the run
command, each run created at CSV log file, detailing the execution of each request, its name is candia-YYYY-MM-DDTHH:MM:SS.log
, and looks like this:
$ cat candia-2018-11-08T16:33:13.csv
Start offset,Request,State,Status code,Duration (ms)
1,GET http://127.1.1.1:8080/?user=user1,OK,200,8
1,GET http://127.0.0.1:8080/?user=user1,OK,200,28
1,GET http://127.0.0.1:8080/?user=user1,OK,200,9
2,GET http://127.1.1.1:8080/?user=user1,OK,200,21
2,GET http://127.0.0.1:8080/?user=user2,OK,200,25
2,GET http://127.0.0.1:8080/?user=user1,OK,200,14
2,GET http://127.0.0.1:8080/?user=user1,OK,200,24
3,GET http://127.1.1.1:8080/?user=user3,OK,200,14
3,GET http://127.1.1.1:8080/?user=user3,OK,200,24