Releases: grafana/k6
v1.0.0
Grafana k6 v1.0 is here! π
After 9 years of iteration and countless community contributions, we're thrilled to announce Grafana k6 v1.0.
While many features and capabilities in this release were introduced gradually in previous versions, k6 v1.0 marks a turning point: a commitment to stability, formal support guarantees, and transparency in how we evolve and develop the project from here. This milestone is more than a version number; it's about trust, reliability, and empowering you to test confidently.
Thank you, k6 community! π
This release wouldn't be possible without you:
- βοΈ 27000+ GitHub stars.
- π§ 9000+ git commits.
- π€ 200+ contributors.
- π Countless test runs of any scale, in every timezone.
It's been amazing to watch k6 grow from a simple load testing command-line tool into a comprehensive reliability tool, used by teams worldwide and supported by a passionate and dedicated community.
To everyone who filed bugs, built extensions and libraries, or championed k6:οΈ
Thank you! You've shaped what k6 is today. πββοΈ
What's New in k6 1.0?
1. Stability You Can Build On
- β Semantic Versioning: k6 now follows Semantic Versioning 2.0. Breaking changes will only happen in major releases, with prior deprecation warnings.
- π 2-Year Support Guarantees: Every major version will be supported with critical fixes for at least two years; upgrade on your schedule.
- π¦ Public API Surface: We've established a clearly delineated and supported API surface for the k6 codebase. Extensions, integrations, and projects building on top of the k6 code now have a stable foundation to rely on.
π Read more in our versioning and stability guarantees guide.
2. First-Class TypeScript Support
Write type-safe and maintainable testsβno transpilation needed. Simply save your file with a .ts
extension and run it directly using k6 run script.ts
.
import http from 'k6/http';
// PizzaRequest defines the request body format the quickpizza API expects
export interface PizzaRequest {
maxCaloriesPerSlice: number;
mustBeVegetarian: boolean;
}
export default function () {
const payload: PizzaRequest = {
maxCaloriesPerSlice: 500, // Type-checked!
mustBeVegetarian: true,
}
http.post(
'https://quickpizza.grafana.com/api/pizza',
JSON.stringify(payload),
{
headers: {
"Content-Type": "application/json",
"Authorization": "Token " + "abcdef0123456789"
} as Record<string, string>
});
}
3. Extensions Made Simple
With k6 v1.0, extensions now work out of the box in k6 cloud run
and k6 cloud run --local-execution
. Support for k6 run
is coming soon.
β
No more xk6 toolchain.
β
No manual builds.
β
Import an extension's module and go.
import faker from 'k6/x/faker';
export default function () {
console.log(faker.person.firstName());
}
To try the experimental feature, first enable its feature flag, then run it on Grafana Cloud with the following command:
K6_BINARY_PROVISIONING=true k6 cloud run script.js,
or if you want to run it locally and stream the results to Grafana Cloud then use:
K6_BINARY_PROVISIONING=true k6 cloud run --local-execution script.js
4. Revamped test summary
The new end-of-test summary makes it easier to understand results and spot issues:
- π Hierarchical output: Metrics are grouped by scenario, group, and category.
- β Improved thresholds & checks: Clearer layout for faster debugging.
- π Multiple summary modes:
compact
(default): big picture results, focusing on essentials.full
: full picture results, providing granularity.
k6 run --summary-mode=full script.ts
5. Quality of Life Upgrades
- Stable modules:
k6/browser
,k6/net/grpc
, andk6/crypto
are now production-ready. - Improved Grafana Cloud integration: Stream local test results to Grafana Cloud with
k6 cloud run --local-execution
.
v1.0.0-rc2
k6 v1.0.0-rc2
is here π!
Continuing our commitment beyond the v1.0.0 release, we are pleased to announce a new release candidate that includes several significant changes:
- Native support for extensions in the Cloud
- New test failure control with
execution.test.fail
New features
Native support for extensions in the Cloud #4671
The new Binary Provisioning feature automatically requests and uses custom k6 binaries with the required extensions for your tests. This allows you to run scripts that use extensions without manually rebuilding k6 as it was in the past by depending on tools like xk6
. The system caches binaries locally for efficiency, and any additional runs with the same dependencies will use the same binary and will run faster.
Binary Provisioning is available for all k6 Cloud users (free and paid plans). It is an experimental feature, it's enabled by opt-in with the feature flag K6_BINARY_PROVISIONING=true
.
Binary provisioning is a limited set of extensions that are supported, and it's not available for the k6 run
command that might be added in the future. However, local development is supported with the k6 cloud run --local-execution
command if a cloud token is provided by the canonical login methods.
Che
10000
ck out the documentation for additional details.
Test failure control with execution.test.fail
#4672
The new execution.test.fail
function allows you to explicitly fail a test while letting it continue execution until completion. This gives you more control over test outcomes while still collecting all metrics and completing necessary cleanup tasks.
UX improvements and enhancements
- #4698 Displays threshold values even when are not configured in
summaryTrendStats
option. - #4699 Drops the link of the legacy k6 website from the user agent.
Bug fixes
- #4717 Safeguards against
pressedKeys
being updated concurrently in the browser module. - #4665 Prevents race condition between
Ended
&Interrupted
execution states. - #4677 Makes
secretsource
also redactfloat32
andfloat64
values.
Maintenance and internal improvements
- #4675, #4676, #4678 Move several packages to
internal
as preparations for v1.0.0 stabilization - #4686 Drops the redundant
NO_COLOR
detection. - #4709 Fixes JS native objects override to avoid a page under the test from overwriting native JavaScript objects, like
Set
andMap
. - #4726 Unifies the internal/cmd.Execute methods.
- #4703 Makes wptTests run without tags or skip if repos not checkout.
- #4701 Fixes WebCrypto errors not propagating from the tests.
- #4691, #4674, #4673, #4663 Bumps the versions for
OpenTelemetry
,grpc
,golang/x
andesbuild
dependencies. - #4691 Bumps x509roots/fallback dependency for fallback certificates.
- #4739 Removes deprecated
GetLayoutMetrics.VisualViewport
CDP usage.
v0.59.0
The v0.59.0
release mirrors the previous v1.0.0-rc2
release to allow automation tools to recognize it as the latest version.
For example, Homebrew's k6 formulae and pkg.go.dev do not automatically fetch unstable versions such as v1.0.0-rc2
, which is legitimately the expected behavior for these tools.
However, this has been the default for all previous v0.*
releases, where they were considered the latest stable versionβeven if they were under a version typically associated with unstable releases. To address this, we will continue releasing mirrored versions under v0.*
for necessary release candidates.
This practice will end once the official stable v1.0.0
release is available, after which we will follow the standard SemVer lifecycle to simplify the workflow for everyone.
The release notes for v1.0.0-rc2 provide a detailed look at all the changes that have been implemented since v1.0.0-rc1
/v0.58.0
and are now part of this version.
v0.58.0
The v0.58.0
release mirrors the previous v1.0.0-rc1
release to allow automation tools to recognize it as the latest version.
For example, Homebrew's k6 formulae and pkg.go.dev do not automatically fetch unstable versions such as v1.0.0-rc1
, which is legitimately the expected behavior for these tools.
However, this has been the default for all previous v0.*
releases, where they were considered the latest stable versionβeven if they were under a version typically associated with unstable releases. To address this, we will continue releasing mirrored versions under v0.*
for necessary release candidates.
This practice will end once the official stable v1.0.0
release is available, after which we will follow the standard SemVer lifecycle to simplify the workflow for everyone.
The release notes for v1.0.0-rc1 provide a detailed look at all the changes that have been implemented since v0.57.0
and are now part of this version.
v1.0.0-rc1
k6 v1.0.0-rc1
is here π!
This release marks a special, non-conventional milestone in the k6 software life-cycle, serving as a preview of the upcoming version 1.0.0.
The purpose of this release is to give the community a chance to test the new version, identify any potential issues, and test migrations of any parts affected by breaking changes. If you encounter any problems or have trouble with the migration, we encourage you to report them by creating an issue. Your feedback will help improve the final release. If no critical issues are reported, we plan to release the final v1.0.0
within the next month.
Hereβs a glimpse of whatβs new in this release:
k6/experimental/webcrypto
promoted to stable and available globally undercrypto
.- A revamped end-of-test summary aiming to bring an easier way to understand test results.
k6/browser
provided an API for tracking network requests and responses.- The new
k6/secrets
module for retrieving secrets with extension support.
Breaking changes
- #4541 Commas(
,
) are now supported in the values of the--tag
CLI flag. This is a breaking change, as previously, a comma meant the start of a new set of tag-values. As a comma is a valid symbol for the value of a tag, this is necessary to have equivalency between different ways of setting tags. This still allows multiple tags to be set on the CLI with multiple--tag key=value
arguments.
A new default path for the configuration file #4301
When running the k6 cloud login
or the deprecated k6 login
commands, a configuration file was automatically created at {USER_CONFIG_DIR}/loadimpact/config.json
. Now, the configuration file is created at {USER_CONFIG_DIR}/k6/config.json
.
To migrate your configuration file to the new path:
- Run
k6 cloud login
ork6 login
to automatically migrate the configuration file to the new location. - Run
k6 cloud run
ork6 run
to verify that the version is now fully functional and no related warning is emitted.
The configuration file in the old path remains available and can continue to be used with the previous k6 versions. If you're not using an old version of k6 anymore, consider deleting the files manually.
The k6 run
commands search for the configuration file in the new location. If it can't find it, it tries to fall back on the old path and then logs a warning message suggesting to migrate it.
New features
A revamped end-of-test summary aiming to bring an easier way to understand test results #4089, #4649
The end-of-test-summary has been revamped to make it easier for users to understand test results. That includes:
- A new format to summarize the results of the user-defined Checks and Thresholds.
- Now metrics are split into different sections, making it easier to focus on what really matters.
The new end-of-test summary is enabled by default for users, but you can use the summary-mode
flag to choose between different modes:
compact
(default): what you can see in the example above, with the most relevant information.full
: similar tocompact
, but also includes some more detailed metrics and results for each group and scenario defined in the test.legacy
: the old summary format for backward compatibility.
Note: The data structure received by the
handleSummary
function,
as well as the data exported using--summary-export
, has not changed in this release. However, these may change in upcoming releases, which could introduce breaking changes.
Browser: Tracking network requests and responses #4290, #4296
The browser module adds support for tracking network requests and responses. This feature is especially useful for validating certain aspects of the requests and responses to determine whether the test was successful. It can also be used to debug issues with the test script or the tested application. Refer to the documentation for more details.
For example, to track all requests and responses made by a page, you can use the following script:
import { browser } from 'k6/browser';
export const options = {
scenarios: {
ui: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
};
export default async function () {
const page = await browser.newPage();
// registers a handler that logs all requests made by the page
page.on('request', async request => console.log(request.url()));
// registers a handler that logs all responses received by the page
page.on('response', async response => console.log(response.url()));
await page.goto('https://quickpizza.grafana.com/', { waitUntil: 'networkidle' });
await page.close();
}
The output might look like this:
INFO[0000] https://quickpizza.grafana.com/ source=console
INFO[0001] https://quickpizza.grafana.com/api/tools source=console
INFO[0001] https://quickpizza.grafana.com/images/pizza.png source=console
...
k6/experimental/webcrypto
promoted to stable and available globally under crypto
#4278
With this release, the k6/experimental/webcrypto
module is promoted to stable and available globally under crypto
. That means you can remove the import { crypto } from 'k6/experimental/webcrypto';
statement from your scripts and still use the module.
export default function () {
const myUUID = crypto.randomUUID();
console.log(myUUID);
}
k6/experimental/webcrypto
is deprecated and will be removed in v1.1.0
.
Support for custom templates in k6 new
command #4618
The k6 new
command now accepts a path to a file to use as a template for the new script. Templates use Go templates syntax and can include the following variables:
ScriptName
: The name of the new script.ProjectID
: The ID of the Grafana Cloud project to use for the new script.
To generate a new script using a custom template, use the following command:
k6 new --template /path/to/my-template.js
Secret Sources #4514, #4621, #4637
We've added support for retrieving secrets from different sources. Among other things, this means that the values received from a secret source will be redacted from the logs. Refer to the documentation for more details.
The two implementations available are to read secrets from a key-value file or from CLI flags, which are meant mostly to test the feature. We've also included extension support, which can be used to implement retrieving secrets from more secure sources.
In the future, we'll likely include additional implementations that are more production-ready.
Here's an example where we log the secret directly, make a request, and then log the whole response. In both cases, the secrets are redacted from the logs.
import http from 'k6/http';
import secrets from 'k6/secrets';
export default async () => {
const my_secret = await secrets.get('cool'); // get secret from a source with the provided identifier
console.log(my_secret);
const response = await http.asyncRequest("GET", "https://httpbin.org/get", null, {
headers: {
"Custom-Authentication": `Bearer ${await secrets.get("else")}`,
}
})
console.log(response.body)
}
$ k6 run --secret-source=mock=cool="not cool secret",else="totally a secret" script.js
...
INFO[0000] ***SECRET_REDACTED*** source=console
INFO[0031] {
"args": {},
"headers": {
"Custom-Authentication": "Bearer ***SECRET_REDACTED***",
"Host": "httpbin.org",
"User-Agent": "k6/1.0.0-rc1 (https://k6.io/)",
"X-Amzn-Trace-Id": "Root=1-67dd6691-18eeaf5d1782bf292da5037c"
},
"origin": "1.1.1.1",
"url": "https://httpbin.org/get"
} source=console
...
UX improvements and enhancements
- #4547 The k6 banner now outputs with the original TrueColor (24-bit) logo only if the terminal supports it.
- #4590 Moves the
docker-compose
example with InfluxDB to theexamples/docker-compose
directory and adds an opentelemetry example. - #4602, #4629 Improves the error message on options error from script. k6 now will try to print the part of the options that fails as JSON.
- #4612 Updates the link included in the local modules' error message. Thanks, @tanurrra!
Bug fixes
- #4544 Fixes race in
ReadableStream.cancel
and run WPT test with race detection for easier finding of similar pro...
v0.57.0
k6 v0.57.0
is here π! This release includes:
- Introducing helpers for functional testing.
- The
k6 new
command now supports templates and ProjectIDs. - The
k6/experimental/csv
module gets a newasObjects
option. - We no longer support the
k6/experimental/browser
module, in favor ofk6/browser
. - Moving most of non-public APIs to the
internal
package.
Breaking changes
- #4161 Drops
k6/experimental/browser
. If you're still using it, follow the instructions to move to the graduated and stablek6/browser
module. - #4133 Moves all not publicly used APIs in
internal
package. This was based on the publicly available extensions for k6 and may break private ones. More APIs will likely be removed or updated in follow-up releases after this more mechanical change. - #4292 TypeScript is automatically supported and recognized if the script files use the
.ts
extension. It also deprecatesexperimental_enhanced
compatibility mode as it is no longer necessary.
New features
New functional testing focused official jslib k6-testing
The k6 team has been developing a new official jslib dedicated to functional testing. While it is still under active development and will potentially see breaking changes, the set of APIs and behaviors it offers are meant to make their way into k6 eventually, and it is now available for early feedback.
k6-testing is a k6 JavaScript library that offers a seamless way to write functional tests in k6, using a Playwright-compatible assertions API. It exposes an expect
function, with which assertions can be performed using specific matchers that reflect the expected results.
Unlike current k6's check
when expects
assertions fail, the test will immediately fail with a clear error message, including the expected and actual values in a similar fashion to what users would observe when using Playwright assertions.
There are many generic matchers (and more to come), such as toEqual
, toBe
, or toBeTruthy
, to only name a few, that can be used to assert conditions during a k6 test.
import { expect } from 'https://jslib.k6.io/k6-testing/0.2.0/index.js';
export default function () {
const response = http.get('https://test.k6.io');
expect(response.status).toEqual(200);
expect(response.body).toBeTruthy();
expect(response.json()).toEqual(JSON.stringify({ message: 'Hello, world!' }));
}
k6-jslib-testing also includes browser-specific async matchers that wait until the expected condition is met such as toBeVisible
, toBeDisabled
, or toBeChecked
, to name a few.
import { expect } from "https://jslib.k6.io/k6-testing/0.2.0/index.js";
import { browser } from "k6/browser";
export const options = {
scenarios: {
ui: {
executor: "shared-iterations",
options: {
browser: {
type: "chromium",
},
},
},
},
};
export default async function () {
const page = await browser.newPage();
try {
// Navigate to the page
await page.goto("https://test.k6.io/my_messages.php");
// Type into the login input field: 'testlogin'
const loc = await page.locator('input[name="login"]');
await loc.type("testlogin");
// Assert that the login input field is visible
await expect(page.locator('input[name="login"]')).toBeVisible();
// Expecting this to fail as we have typed 'testlogin' into the input instead of 'foo'
await expect(page.locator('input[name="login"]')).toHaveValue("foo");
} finally {
await page.close();
}
}
It is currently available as part of the jslib.k6.io repository and is available to use in your k6 tests by adding the following import:
import { expect } from "https://jslib.k6.io/k6-testing/0.2.0/index.js";
Try it out and give us feedback or contribute to the project on the k6-jslib-testing repository!
--template
and --project-id
flags for k6 new
command #4153
The k6 new
command has been revamped to provide an improved experience when scaffolding new k6 tests. It now supports a --template
flag with options such as minimal
, protocol
, and browser
, letting you generate a script tailored to your specific use case.
The command also now accepts a --project-id
flag, which allows you to easily parameterize the test's Grafana Cloud configuration.
# Create a new k6 script using the 'protocol' template
$ k6 new --template protocol
# Create a Grafana k6 cloud-ready script with a specific project ID
$ k6 new --project-id 12345
New asObjects
option in k6/experimental/csv
module #4295
The CSV module's parsing operations now support the asObjects
option, which enables parsing CSV data into JavaScript objects instead of arrays of strings (the default behavior).
When asObjects
is set to true
, the module parses CSV data into objects where:
- Column names from the header row become object keys.
- Column values become the corresponding object values.
- An error is thrown if no header row exists or if options modify the parsing start point.
With the option set to true
,
import http from 'k6/http';
import csv from 'k6/experimental/csv';
const csvData = csv.parse('data.csv', { asObjects: true });
the following CSV file:
name,age,city
John,30,New York
Jane,25,Los Angeles
will be parsed into the following JavaScript objects:
[
{ name: 'John', age: '30', city: 'New York' },
{ name: 'Jane', age: '25', city: 'Los Angeles' },
]
Refer to the CSV module's documentation for more information.
UX improvements and enhancements
- #4176 Warns on using shorthand options when that override scenarios.
- #4293 Renames browser data directory name prefix from
xk6-browser-data-
tok6browser-data-
. - #4513 Adds support for
file
scheme URLs across file loading APIs -open
,k6/experimental/fs.open
andk6/net/grpc.Client#load
. - #4517 Switches from the legacy examples to quickpizza.grafana.com.
Bug fixes
- #4536, #4534, #4533, #4531, #4530, #4528, #4523, #4522, #4521 Fix possible data races while using k6 browser's APIs.
- #4174 Fixes an NPD during a click, which could occur when either the load generator or chrome instance is under a lot of load.
- #4192 Fixes a memory leak in general event handling between components.
- #4280 Fixes an NPD by not disposing of the original handle.
- #4288 Cleans up browser download path artifacts after a test run.
- #4532 Fixes
--local-execution
runs by isolatingArchive
's urls.
Maintenance and internal improvements
- #4184 Fixes some browser Windows tests.
- #4131 Moves experimental WebSocket code into the k6 codebase.
- #4143 Fixes for k6packager workflow building image to do k6 releases.
- #4172 Drops Slack URL from the README.
- #4173 Updates dependencies in gRPC example server.
- #4187 Removes packaging folder from browser module - not needed after it was moved to the k6 codebase.
- #4188, #4190 Merge xk6-webcrypto extension code into k6.
- #4189 Uses
modulestest
to make experimental streams test simpler. - #4191 Removes BaseEventEmitter from components that don't work with it.
- #4201 Tracks more dependencies to dependabot.
- #4212 Fixes gRPC tests after update to golang internal test certificates.
- #4213 Updates k6-taskqueue-lib to v0.1.3.
- #4271 Runs dependabot weekly instead of daily.
- #4275 Fixes the
browser
module working with reused VUs that originally weren't used in browser scenarios. - #4276 REST API stays on while outputs are flushing, only stopping after that.
- #4294 TestStreamLogsToLogger: increase wait time to get less flakiness.
- #4209, #4208, #4196, #4195, [#4...
v0.56.0
k6 v0.56.0
is here π! This release includes:
- We've merged xk6-browser into k6.
- Many small improvements, bug fixes and internal refactors.
Breaking changes
- browser#1541 Removes
accessibility-events
from a test, which is no longer a valid permission that can be granted by the latest version of Chromium/Chrome. - #4093 Unexports
lib/consts.FullVersion
from the k6's Golang API.
New features
Merge browser code in k6 codebase #4056
While the browser module has been stabilized, the codebase was not moved inside of k6.
As part of the stabilization this is now also merged in the k6 codebase. In the following months we would move issues from the xk6-browser repo and then archive it.
UX improvements and enhancements
- browser#1536 Removes
Headless
from the user agent to prevent test traffic from being blocked. - browser#1553 Reduces logging noise produced by the browser module.
- #4093 Introduces a
--json
flag to ak6 version
sub-command, which switches an output to a JSON format. - #4140 Tags browser module metrics with a
resource_type
tag which can be one of these values:"Document"
,"Stylesheet"
,"Image"
,"Media"
,"Font"
,"Script"
,"TextTrack"
,"XHR"
,"Fetch"
,"Prefetch"
,"EventSource"
,"WebSocket"
,"Manifest"
,"SignedExchange"
,"Ping"
,"CSPViolationReport"
,"Preflight"
,"Other"
, or"Unknown"
. - #4092 Populates
__ENV.K6_CLOUDRUN_TEST_RUN_ID
with the corresponding value for local executions streaming results to the Cloud:k6 cloud run --local-execution
.
Bug fixes
- browser#1507 Fixes the
Geolocation.Accuracy
field. - browser#1515 Fixes Sobek
Object.Get(key)
by returning*[]any
instead of[]any
. - browser#1534 Fixes
locator
APIs to wait during a navigation without erroring out. - browser#1538 Fixes
frame.title
. - browser#1542 Fixes a panic which can occur when a frame navigates.
- browser#1547 Fixes a panic due to events associated to stale frames.
- browser#1552 Fixes a panic for
locator.selectOption
when value is an object. - browser#1559 Fixes a panic for
page.screenshot
. - browser#1544 Fixes a nil pointer dereference when calling
evaluate
orevaluateHandle
with an invalid page function. - #4058 Fixes the namespaced object export when default is the only one available.
- #4132 Returns an error when a page is
null
during the creation of a page.
Maintenance and internal improvements
- browser#1504, browser#1510, browser#1511 browser#1512 browser#1513, browser#1518, browser#1519, browser#1520, browser#1523, browser#1521, browser#1524, browser#1526, browser#1527, browser#1531 Removes Sobek out of business logic layers.
- browser#1528, browser#1529, browser#1557 Aligns repo with k6.
- browser#1517 Fixes internal tests.
- browser#1540 Refactors internals.
- #4049, #4095, browser#1535, browser#1537, #4073, #4101, #4103, #4104, #4134, #4148 Updates dependencies.
- #4057 Update k6-taskqueue-lib to drop goja dependency.
- #4076 modules.NewModuleInstance doc updates.
- #4137, #4148 Updates a dependency and adds release notes.
- #4099, #4114 Fixes to CI after browser merge, around running tests on windows.
- #4102 Fix windows-packaging CI after update of the windows github action.
- #4047 Uses
(*Regexp).MatchString
to avoid unnecessary[]byte
conversions. Thanks, @Juneezee for the contribution. - #4055 Updates release template.
- #4143 Fix k6packager workflow which also broke v0.55.1 initial release.
- #4063 Updates usage report to return whether k6 was ran from CI.
- #4072 Uses the precompiled 'gotip' on the xk6 workflow.
- #4084 Updates usage report to return usage of the deprecated 'ext.loadimpact' option.
Roadmap
Removal of deprecated k6/experimental/browser
module
Since v0.52.0
we have had a non experimental version of the browser module (k6/browser
). We urge you to migrate your scripts over to the non experimental browser module as we will be removing the experimental version of it in the next release (v0.57.0
).
v0.55.2
k6 v0.55.2
is a patch release that fixes packaging issue.
There are no functional changes in k6 compared to v0.55.1.
v0.55.1
k6 v0.55.1
is here π! This release includes:
- Dependency updates for
golang.org/x/net
.
Maintenance and internal improvements
- #4134 Updates
golang.org/x/net
which contains a fix for CVE-2024-45338.
v0.55.0
k6 v0.55.0
is here π! This release includes:
β οΈ The deprecated StatsD output has been removed.β οΈ The experimentalk6/experimental/tracing
module has been removed.- π URL grouping support in the browser module.
- π Top-level
await
support. - π Complete RSA support for
k6/experimental/webcrypto
.
Breaking changes
k6/experimental/tracing
module removed #3855
The experimental k6/experimental/tracing
module has been removed, in favor of a replacement jslib polyfill, please consult our guide on how to migrate, #3855
.
StatsD output removed #3849
The StatsD output was deprecated in k6 v0.47.0 and is now removed. You could still output results to StatsD using the community xk6 extension LeonAdato/xk6-output-statsd. Thanks, @LeonAdato for taking over the extension!
open
will have a breaking change in the future.
Currently, open
opens relative files based on an unusual root, similar to how require
behaved before it was updated for ESM compatibility. To make k6 more consistent, open
and other functions like it will start handling relative paths in the same way as imports and require
.
For a more in-depth explanation, please refer to the related issue.
With this version, k6 will start emitting warnings when it detects that in the future, this will break. We recommend using import.meta.resolve()
as a way to make your scripts future proof.
http.file#data
now truly has the same type as the provided data #4009
Previously http.file#data
was always a slice of byte ([]byte
) - which was very likely a bug and a leftover from years past.
The original aim (also documented) was to have the same type as the data provided when creating the http.file
object, and it is now effectively the case.
New features
Top-level await support 4007
After the initial native support for ECMAScript modules, k6 can now load those modules asynchronously which also allows await
to be used in the top-level of a module. That is you can write await someFunc()
directly in the top most level of a module instead of having to make an async function that you call that can than use await
.
Until now, you had to wrap your code in an async function to use await
in the top-level of a module. For example, the following code:
import { open } from 'k6/experimental/fs'
import csv from 'k6/experimental/csv'
let file;
let parser;
(async function () {
file = await open('data.csv');
parser = new csv.Parser(file);
})();
Can now be written as:
import { open } from 'k6/experimental/fs'
import csv from 'k6/experimental/csv'
const file = await open('data.csv');
const parser = new csv.Parser(file);
This should make using the increasing number of async APIs in k6 easier in the init context.
This is not allowed in case of using the CommonJS modules, only ECMAScript modules, as CommonJS modules are synchronous by definition.
Complete1 RSA support for k6/experimental/webcrypto
#4025
This update includes support for the RSA family of algorithms, including RSA-OAEP
, RSA-PSS
and RSASSA-PKCS1-v1_5
. You can use these algorithms with the crypto.subtle
API in the same way as the other algorithms, precisely for generateKey
, importKey
, exportKey
, encrypt
, decrypt
, sign
, and verify
operations.
By implementing RSA support, we make our WebCrypto API implementation more complete and useful for a broader range of use cases.
Example usage
Expand to see an example of generation RSA-PSS key pair.
import { crypto } from "k6/experimental/webcrypto";
export default async function () {
const keyPair = await crypto.subtle.generateKey(
{
name: "RSA-PSS",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: { name: "SHA-1" },
},
true,
["sign", "verify"]
);
console.log(JSON.stringify(keyPair));
}
page.on('metric)
to group urls browser#371, browser#1487
Modern websites are complex and make a high number of requests to function as intended by their developers. These requests no longer serve only content for display to the end user but also retrieve insights, analytics, advertisements, and for cache-busting purposes. Such requests are usually generated dynamically and may contain frequently changing IDs, posing challenges when correlating and analyzing your k6 test results.
When load testing a website using the k6 browser module, these dynamic requests can result in a high number of similar-looking requests, making it difficult to correlate them and extract valuable insights. This can also lead to test errors, such as a "too-many-metrics" error, due to high cardinality from metrics tagged with similar but dynamically changing URLs.
This issue also affects synthetic tests. While you may not encounter the "too-many-metrics" error, you may end up with a large amount of uncorrelated metric data that cannot be tracked effectively over time.
To address this in the browser module, we have implemented page.on('metric')
, which allows you to define URL patterns using regex for matching. When a match is found, the URL and name tags for the metric are replaced with the new name.
Example usage
Expand to see an example of working with `page.on('metric')`.
import { browser } from 'k6/browser';
export const options = {
scenarios: {
ui: {
executor: 'shared-iterations',
options: {
browser: {
type: 'chromium',
},
},
},
},
}
export default async function() {
const page = await browser.newPage();
// Here, we set up an event listener using page.on('metric').
// You can call page.on('metric') multiple times, and each callback function
// will be executed in the order that page.on was called.
page.on('metric', (metric) => {
// Currently, metric.tag is the only available method on the metric object.
// It enables matching on the URL tag using a specified regex pattern.
// You can call metric.tag multiple times within the callback function.
metric.tag({
// This is the new name assigned to any metric that matches the defined
// URL pattern below.
name: 'test',
// Provide one or more match patterns here. Any metrics that match a pattern
// will use the new name specified above.
matches: [
// Each match pattern can include a URL and an optional method.
// When a method is specified, the metric must match both the URL pattern
// and the method. If no method is provided, the pattern will match all
// HTTP methods.
{url: /^https:\/\/test\.k6\.io\/\?q=[0-9a-z]+$/, method: 'GET'},
]
});
});
try {
// The following lines are for demonstration purposes.
// Visiting URLs with different query parameters (q) to illustrate matching.
await page.goto('https://test.k6.io/?q=abc123');
await page.goto('https://test.k6.io/?q=def456');
} finally {
// Ensure the page is closed after testing.
await page.close();
}
}
ControlOrMeta
support in the keyboard browser#1457
This approach enables tests to be written for all platforms, accommodating either Control
or Meta
for keyboard actions. For example, Control+click
on Windows and Meta+click
on Mac to open a link in a new window.
Example usage
Expand to see an example usage of `ControlOrMeta`
await page.keyboard.down('ControlOrMeta');
// Open the link in a new tab.
// Wait for the new page to be created.
const browserContext = browser.context();
const [newTab] = await Promise.all([
browserContext.waitForEvent('page'),
await page.locator('a[href="/my_messages.php"]').click()
]);
await page.keyboard.up('ControlOrMeta');
UX improvements and enhancements
- browser#1462 Enhances
waitForSelector
error message to better reflect why a selector doesn't resolve to an element. - #4028 Adds support of SigV4 signing for the
experimental-prometheus-rw
output. This allows users to authenticate with AWS services that require SigV4 signing. Thanks, @obanby for the contribution! - #4026 Allows setting of service.name from the
OTEL_SERVICE_NAME
environment variable for theexperimental-opentelemetry
output. This aligns better with standard OTEL practices. Thanks, @TimotejKovacka for the contribution! - browser#1426 Instruments
page.waitForTimeout
with tracing which will allow it to be displayed in the timeline.
Bug fixes
- browser#1452 Fixes a possible deadlock when working with
page.on
. - [browser#1469](https://git...
-
Since under the hood we do fully rely on the Golang's SDK, our implementation doesn't support zero salt lengths for the
RSA-PSS
sign
/verify
operations. β©