Releases: grafana/k6
v0.20.0
Lots of goodies in this release! 🎉
We are working towards a 1.0 release of k6, and as part of this release we've also published our roadmap for 2018 in the Github wiki, here it is. We welcome comments and discussion relating to the roadmap, both in the corresponding issues as well as in Slack.
Once again we saw contributions from several members of the community in this release, from 9 people outside of Load Impact, woop woop! A big thanks to the following people for contributing to this release: @antekresic, @cstyan, @cyberw, @danron, @dstpierre, @luizbafilho, @marklagendijk, @na-- and @pkruhlei.
Two of the above contributors have also become full time employees of Load Impact since the last release, to accelerate the development of k6. We welcome @luizbafilho and @na-- to the distributed k6 core team!
To see the current plan for the next release, check out this milestone.
New Features!
k6/http: Support for binary files and multipart requests (#370, #420 and #524)
The init context open()
function now supports binary files:
import http from "k6/http";
import {md5} from "k6/crypto";
let binFile = open("./image.png", "b");
export default function() {
console.log(md5(binFile, "hex"));
}
and the HTTP module has handily gained support for multipart requests:
import http from "k6/http";
let binFile = open("./image.png", "b");
export default function() {
var data = {
field: "this is a standard form field",
file: http.file(binFile, "my image file.png")
};
var res = http.post("https://example.com/upload", data);
}
Thanks @dstpierre for their work on this!
Docs: Multipart requests
k6/http: Request information through response object (#447)
Request information is now exposed through the Response object:
import http from "k6/http";
export default function() {
let res = http.get("https://example.com/")
console.log(`Method: ${res.request.method}`);
new Map(Object.entries(res.request.headers)).forEach((v, k) => console.log(`Header: ${k}=${v}`));
console.log(`Body: ${res.request.method}`);
}
Thanks to @cstyan for their work on this!
Docs: Request information
Lifecycle: setup/teardown functions (#457)
Finally k6 has the same basic test lifecycle hooks as many "normal" testing tools, setup and teardown, and you have the full JS API of k6 available within these functions which means you can make HTTP calls etc. that you can’t do in the global/init scope.
To use the lifecycle hooks you simply define an exported setup() and/or teardown() function in your script:
export function setup() {
return { “data”: “passed to main and teardown function” };
}
export function teardown(data) {
console.log(JSON.stringify(data));
}
export default function(data) {
if (data.v != 1) {
throw new Error("incorrect data: " + JSON.stringify(data));
}
}
Docs: Test life cycle
CLI: HTTP debug flag (#447)
If you specify --http-debug
when running a test k6 will now continuously print request and response information.
Thanks to @marklagendijk for their work on this!
Docs: HTTP debugging
Options: DNS override (#494)
Overriding DNS resolution of hostnames can come in handy when testing a system that is run in multiple environments (dev, staging, prod etc.) with different IP addresses but responds to the same Host
header.
import http from "k6/http";
export let options = {
hosts: {
"loadimpact.com": "1.2.3.4",
"test.loadimpact.com": "5.6.7.8"
}
};
export default function() {
http.get("http://loadimpact.com/");
http.get("http://test.loadimpact.com/");
}
Tip: you can use environment variables to switch the IP based on environment.
Thanks @luizbafilho for their work on this!
Docs: DNS Override option
CLI: Add -e
flag environment variable flag (#495)
You can now specify any number of environment variables on the command line using the -e NAME=VALUE
flag.
As a matter of security, when running k6 cloud ...
or k6 archive ...
the system's environment variables will not be included in the resulting archive, you'll now have to use the new --include-system-env-vars
flag to get that behavior. When executing k6 run ...
the system's environment will continue to be exposed to your script.
We encourage the use of -e NAME=VALUE
to make environment variable use explicit and compatible across local and cloud execution.
Thanks @na-- for their work on this!
Docs: Environment variables
HAR converter: Add --no-batch
flag (#497)
A --no-batch
CLI flag has been added to k6 convert
command to disable the creation of batch request statements in favor of individual http.get/del/options/patch/post/put
statements.
Thanks @danron and @cyberw for their work on this!
HAR converter: Add --return-on-failed-check
flag (#499)
A --return-on-failed-check
CLI flag has been added to k6 convert
command to optionally return/exit the current VU iteration if a response status code check fails (requires the existing --enable-status-code-checks
to be specified as well).
Thanks @cyberw for their work on this!
HAR converter: Add --correlate
flag (#500)
A first step towards doing correlations when converting HAR to JS has implemented. In this first iteration, if --correlate
is specified the converter will try to detect issues with redirects.
Thanks @cyberw for their work on this!
Stats: Use linear interpolation when calculating percentiles (#498)
The percentile calculation has been changed to use linear interpolation of two bounding values if percentile doesn't precisely fall on a value/sample index.
Thresholds: Support for aborting test early as soon as threshold is hit (#508)
Up until now thresholds were evaluated continuously throughout the test but could never abort a running test.
This PR adds functionality to specify that a test run should abort the test as soon as a threshold evaluates to false, optionally with a delay in threshold evaluation to avoid aborting to early when the number of samples collected is low.
export let options = {
thresholds: {
"http_req_duration": ["avg<100", { threshold: "p(95)<200", abortOnFail: true, delayAbortEval: "30s" }]
}
};
Thanks @antekresic for their work on this!
Docs: Thresholds with abort
Docker: Use full Alpine as base image for k6 (#514)
Thanks @pkruhlei for their contribution!
CLI: Option to whitelist what tags should be added to metric samples (#525)
Adds a CLI option --system-tags "url,method,status"
to specify a whitelist of system tags that will be included in the metrics output.
The following tags can be specified:
url
(http, websocket)method
(http)status
(http, websocket)proto
(http)subproto
(websocket)error
(http)name
(http)group
(http)check
(http)tls_version
(http)ocsp_status
(http)iter
(vu)vu
(vu)
All but the last 3 (ocsp_status
, iter
, vu
) are included by default. Some collectors (e.g. cloud
) could require that certain tags are included.
Docs: System tags
k6/http: Support for HTTP Digest Authentication (#533)
import http from "k6/http";
import { check } from "k6";
export default function() {
// Passing username and password as part of URL plus the auth option will authenticate using HTTP Digest authentication
let res = http.get("http://user:[email protected]/digest-auth/auth/user/passwd", {auth: "digest"});
// Verify response
check(res, {
"status is 200": (r) => r.status === 200,
"is authenticated": (r) => r.json().authenticated === true,
"is correct user": (r) => r.json().user === "user"
});
}
Docs: HTTP Params
Bugs fixed!
-
HAR converter: Fixed issue with construction of
body
parameter whenPostData.Params
values are present. (#489) -
Stats: Fixed output of rate metrics to truncate rather than round when converting to string representation from float for summary output.
-
Stats: Fixes issue where calls to
TrendSink.P()
andTrendSink.Format()
could return wrong results ifTrendSink.Calc()
hadn't been previously called. (#498) -
Cloud/Insights: Fixed issue causing default test name to be empty when parsing script from STDIN (#510)
-
Cloud/Insights: Fixed handling of unexpected responses from server. (#522)
-
Stats: Fixed issue with calculation of
data_received
anddata_sent
metrics. (#523) -
WebSockets: Fixed issue that different TLS settings like
InsecureSkipTLSVerify
were ignored for websockets (#531)
Breaking changes
- The
SummaryTrendStats
configuration option has been renamed tosummaryTrendStats
, to match all of the other JS option names.
v0.19.0
The first release of 2018! 🎉
We have contributions from 10 people outside of Load Impact in this release, yay! To celebrate that and make onboarding of new users and contributors easier we’ve improved the README to give a better overview of the project and the Contributing guide with better instructions how to get a k6 dev environment set up.
A big thanks to the following people for contributing to this release: @antekresic, @borjacampina, @cstyan, @dstpierre, @ivoreis, @jonathon-L, @marklagendijk, @Ripolin, @tbroadley, and @tmcgannon
New Features!
HAR to JS converter (#291, #453)
k6 now has a builtin command k6 convert recording.har > recording.js
to convert HAR files to JS. This is great for being able to quickly go from a browser/proxy recording to a k6 script, a common flow for getting started with a new test case.
Thanks to @borjacampina for their work on this!
Docs: HAR converter
CLI/options: RPS limiter
A global request per second limiter has been added to k6. It will trigger if the RPS level goes above the set value, blocking further requests for a short period to maintain the desired level.
export let options = {
rps: 100
};
Or --rps
on the CLI.
CLI: Logging in JSON format (#434)
You can now output logs in JSON format! It looks something like this:
{"level":"debug","msg":"Engine terminated cleanly","time":"2017-12-20T12:30:35Z"}
Thanks to @ivoreis for this PR!
k6/http: Automatic decompression of deflate encoded response bodies (#419)
Adds handling of deflate (as specified in RFC 1950) encoded response bodies by automatically decompressing them.
k6/http: Automatic decompression of gzip encoded response bodies (#438)
Same as the one above but for gzip. k6 previously automatically handled gzip compressed bodies as long as no Accept-Encoding
header was explicitly specified when making a request, but this adds transparent decompression as long as the Content-Encoding
header in a response is set to gzip.
Thanks to @Ripolin for discovering the discrepancy in the handling of gzipped responses and for fixing it!
k6/http: TLS handshaking metric (#454)
k6 will now measure TLS handshaking time. The metric is called http_req_tls_handshaking
and is accessible in scripts as res.timings.tls_handshaking
.
Thanks to @antekresic for this PR!
k6/html: Form serialization methods (#435)
This feature adds some missing jQuery APIs for serializing form elements to a URL-encoded string, array or object.
import http from "k6/http";
export default function() {
let res = http.get(“https://example.com/form”);
let form = res.html().find('form');
const serialized = form.serializeObject();
}
Thanks to @marklagendijk for their work on this!
Docs: serialize(), serializeArray() and serializeObject()
k6/http: Form submission method (#437, #445)
A sister feature to the one above, adding a submitForm(...)
method to the response object for making it easier to work with HTML form submissions.
import http from "k6/http";
export default function() {
let res = http.get(“https://example.com/form”);
res = res.submitForm({ fields: { message: "hello world" });
}
Again, thanks to @marklagendijk for their work on this!
Docs: Response.submitForm() and Working with HTML forms
k6/http: Add back OPTIONS method (#451)
Up until v0.13.0 k6 supported CONNECT
, OPTIONS
and TRACE
methods, besides the more common HTTP methods. In v0.13.0 these methods were then lost in a big refactor where we switched JS engine from Otto to goja.
Thanks to @cstyan for this PR!
k6/http: Link click method (#459)
A wrapper around the Selection API to locate an link/anchor tag in the response HTML and generate a click request. It adds a clickLink(...)
method to the response object.
import http from "k6/http";
export default function() {
let res = http.get("https://httpbin.org/links/10/0");
res = res.clickLink({ selector: 'a:nth-child(4)' })
}
Yet again, thanks to @marklagendijk for their work on this!
Docs: Response.clickLink()
Metrics: iteration_duration
metric, vu
and iter
tags (#460)
A new metric, iteration_duration
, has been added to k6. It measures the time it takes to run one full iteration of the default/main function. Most builtin metrics (http, group, checks etc.) are now also automatically tagged with vu
and iter
tags, representing the VU and iteration number where the metric data point was collected.
CLI: Specify what stats to report for trend metrics (#462)
A new CLI option --summary-trend-stats avg,med,max,p(95),p(99),p(99.9)
for specifying what stats to show for trend metrics (response times) in the summary output after a test run has finished.
Thanks @antekresic for this contribution!
k6/http: Set default user-agent (#466)
By default k6 will now send a user-agent string in the following format: k6/0.19.0 (https://k6.io/);
.
Bugs fixed!
-
k6/http: The val() Selection method now properly returns an empty string for input fields when the value attribute is missing. (#435, thanks @marklagendijk)
-
k6/http: Fixed three bugs related to cookie handling when doing redirects. (#479, thanks @marklagendijk)
-
Archive: Fixed JSON encoding of <, > and & characters. (#421, thanks @dstpierre)
-
Engine: Improved stability of some tests to decrease flakiness of CI builds.
-
Stats: Fixed median calculation when sample count is even (#432, thanks @tmcgannon)
-
Docs: Fixed typo in README (#433, thanks @tbroadley)
-
Docs: Fixed broken link in README (#482, thanks @jonathon-L)
v0.18.2
Features:
-
k6/http: Limit concurrent requests in http.batch() calls. (#296)
export let options = { batch: 20, // Default: 10 }
-
Flag to blacklist certain IP ranges from being called from scripts. (#389)
-
Flag to disable running of thresholds. (#42)
-
Archives now contain original sources, not transpiled gibberish. (#387)
-
k6/http: Enabled TLS Renegotiation
Fixed:
v0.18.0
This release was quite some time in the making, and for good reason - we changed a ton of stuff under the hood, merged a bunch of big features, and we had to make sure it was all stable before releasing it out into the wild.
Note! This version removes the web UI, which has been unmaintained and deprecated for several releases. If you're interested in maintaining a web UI, please contact us and we can work something out. (#300)
Note! Due to some significant changes in how we store disk configuration, if you previously used k6 login
to store credentials for influxdb, you will need to do so again after updating to v0.18.0.
New Features!
k6/html: full jQuery API compatibility!! (#197)
This is a huge feature and incredibly exciting to us - res.html()
now returns an object that supports the full jQuery API!
check(http.get("http://example.com/"), {
"status is 200": (r) => r.status === 200,
"caption is correct": (r) => r.html("h1").text() == "Example Domain",
})
Well, we say the full, but there are actually two exceptions: stuff like height()
and width()
that only makes sense if you're actually rendering the page in a browser, and anything that modifies the document (data("key", "value")
), which doesn't make any sense in the context of a load testing tool.
If you'd like to see these two added, show us a use case and we'll see what we can do!
It's worth noting that this isn't just a huge feature, it's the single biggest pull request I have ever seen, adding over 5000 lines of code (many of which are code generated!). For scale, the entire k6 codebase (before this PR) was around 20,000 lines.
Huge thanks to @mitnuh for their tireless work on this!
Complete rework of the CLI! (#110)
This is a huge change and the biggest culprit for this delay - because the CLI is so important, and because of the sheer size of this change, we couldn't just ship it off until we were absolutely sure it worked.
Not only is the new CLI code substantially easier to work with for us - we don't have to get all antsy about adding any CLI-facing features out of fear we may break something:
- Help pages (
k6 --help
) are now more helpful, complete with usage examples. - There's no more weirdness with certain flags having to be in certain positions (eg.
k6 run -v
now works, not justk6 -v run
). - And we threw in coloured output for control commands while we were at it.
All options can now be set from the environment
Yup. Instead of -u 100
/--vus 100
, or specifying the vus: 100
option, you can now set K6_VUS
in the environment instead.
The order of predecence for this is: defaults > disk config > script options > environment variables > commandline flags.
k6/http: You can pass objects to http.batch()
(#295)
http.batch([
{ "method": "GET", "url": "http://example.com/" },
])
Thanks to @borjacampina for this contribution!
k6/http: TLS information in HTTP responses (#322)
HTTP responses now have several new fields, all of which are also exported as tags, and a couple of new constants for their values:
tls_version
(eg.http.TLS_1_2
)tls_cipher_suite
(eg."TLS_RSA_WITH_RC4_128_SHA"
)ocsp
produced_at
(timestamp, ms)this_update
(timestamp, ms)next_update
(timestamp, ms)revoked_at
(timestamp, ms)revocation_reason
(eg.http.OCSP_REASON_KEY_COMPROMISE
)status
(eg.http.OCSP_STATUS_GOOD
)
k6/http: New API for cookie management (#323)
This is a pretty big feature youthat has been asked about for a long time - we now have a comprehensive API for anything you could possibly want to do regarding cookies.
There's much more, but the biggest thing that's been asked for is how to manually set a cookie for a request, and read it back out - without messing about with manually constructing HTTP headers:
check(http.get("http://example.com/", { cookies: { name: "value" } }), {
"status is 200": (r) => r.status === 200,
"some cookie is set": (r) => r.cookies.my_cookie === "hi",
});
Much smaller Docker images (#337)
With the web UI gone, we could drop our Node dependency, and we're also now using Alpine Linux base images.
Thanks to @StephenRadachy for this contribution!
Much faster loading of external ES5 libraries! (#212)
The code responsible for loading JS files now skips invoking Babel for files that are already valid ES5. Yes, it was actually that simple, and it cuts minutes(!) off loading big, already minimised libraries like Faker.js.
k6/encoding: base64 encoding and decoding (#327)
What it says on the tin. Supports normal or URL-safe encodings.
import enc from "k6/encoding";
export default function() {
console.log(enc.b64encode("hello!!")); // aGVsbG8hIQ==
console.log(enc.b64encode("hello!!", "rawurl")); // aGVsbG8hIQ
}
Bugs fixed!
-
The
iterations
metric wasn't exported properly. (#313) -
Sporadic errors at the end of tests. (#358)
-
Incorrect scaling/failed requests at the start of a test when using stages. (#326)
-
k6/ws: The
close
event sometimes wouldn't be emitted. (#329) -
k6/ws: Respond to pings with pongs as decreed by the ws spec. (#330)
-
k6/ws: Missing metrics at the end of a test. (#333)
-
cloud: Anonymous tests with
-o cloud
now show correct URLs. (#348) -
cloud: More useful error messages from tests with
-o cloud
.
v0.17.2
New Features!
-
TLS client certificates:
export let options = { tlsAuth: [ { domains: ["example.com"], cert: open("mycert.pem"), key: open("mycert-key.pem") } ] };
-
Reduced memory usage: Using buffer pools for HTTP responses
Fixed:
- Go build error (#293)
- Quieter output with —quiet
- Fixed usage reports
- Some minor fixes & refactoring
v0.17.1
v0.17.0
New Features!
-
TLS configuration options (thanks @gbts!) #235
export let options = { tlsCipherSuites: [ "TLS_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", ], tlsVersion: { min: "ssl3.0", max: "tls1.2" }, };
-
HMAC support added to the
k6/crypto
module (thanks @edgardoalz!) #256 -
A new, more intuitive way to display checks (thanks @ppcano!) #253
-
Percentiles in metrics now displayed as
p(95)
rather thanp95
, for consistency with the threshold syntax (@ppcano again!) #255 -
New
proto
tag onhttp_*
metrics for telling whether HTTP/1.1 or HTTP/2.0 is used. f4b4456
Bug fixes!
- Inaccurate
data_sent
anddata_received
values (thanks @jkpl!) #272 console.log()
calls made past the end of the test are now ignored. 77c90b8- The stock Grafana setup with
docker-compose
now allows anonymous access. #260 - Checks in the same batch were tagged with the same name by accident. #270
- HTTP/2 requests were broken for a while. #268
- Imports are no longer dumped into the global namespace. #276
- A couple of odd race conditions taken care of.
…along with some major changes under the hood: the groundwork for cloud- and clustered execution, simpler and more resilient VU orchestration algorithms, and more.
Also: we now have a beautiful Grafana dashboard for k6 and InfluxDB, contributed by @geekdave! Check it out: https://grafana.com/dashboards/2587
v0.16.0
New Features:
- Websocket support, contributed by @gbts! (#178 #228)
k6 login influxdb
; no more need to pass in URLs. (#179)http.url
"tag" for interpolating templated URLs. (#148)
Fixed:
- Bandwidth tracking is now more accurate, but also less granular. (#242)
- Invalid path construction on Windows. (#227)
- Invalid stage duration serialization in archives. (#241)
- A race condition in
http.batch()
that could lose samples. (b2e140c) - Invalid durations reported from cancelled requests. (#236)
- Checks ran past the end of a test weren't properly ignored. (eda9294)
v0.15.0
New Features:
- Archive your tests for easy distribution!
This will also be the underpinnings of clustered execution, see #140. timeout
option for HTTP requests.userAgent
option for HTTP requests.- Request errors are no longer thrown, but logged as warnings.
Fixed:
__ENV
was broken in v0.13.0.insecureSkipTLSVerify
was broken in v0.13.0.HTTP_PROXY
/HTTPS_PROXY
/NO_PROXY
in the environment weren't respected properly.