k6 v0.35.0 is here! :tada: It introduces several new features that nicely enhance its usability and also contains a whole lot of fixes and ongoing efforts with refactoring.

In total, we have closed 14 issues. We have also branched out three new [xk6 extensions](https://k6.io/docs/misc/k6-extensions/) during this release :star:

## New features

### Ability to set VU-wide custom metric tags ([#2172](https://github.com/grafana/k6/pull/2172))

k6 now supports setting tags for VUs as part of the Execution API with an easy key-value interface. These tags are attached to the metrics emitted by the VU. Example usage:

```js
import http from 'k6/http';
import exec from 'k6/execution';

export const options = {
    duration: '10s',
    vus: 3,
};

export default function () {
    exec.vu.tags['mytag'] = 'value';
    exec.vu.tags['vuId'] = exec.vu.idInTest;

    console.log(`mytag is ${exec.vu.tags['mytag']} and my VU's ID in tags ${exec.vu.tags['vuId']}`);

    // the metrics these HTTP requests emit will get tagged with `mytag` and `vuId`:
    http.batch(['https://test.k6.io', 'https://test-api.k6.io']);
}
```

One of the most requested use cases for this feature is that now we can tag all metrics with the current stage number. [With a bit of JS code](https://github.com/grafana/k6/issues/796#issuecomment-959396841) it is possible to calculate which stage of a [`ramping-vus`](https://k6.io/docs/using-k6/scenarios/executors/ramping-vus/) or [`ramping-arrival-rate`](https://k6.io/docs/using-k6/scenarios/executors/ramping-arrival-rate/) scenario the VU is currently in. This in turn allows the setting of [thresholds](https://k6.io/docs/using-k6/thresholds/) only on the metrics that were emitted in specific stages of the test run! :tada:

There are some caveats, however: values can be only of `String`, `Number` or `Boolean` type, while values of other types will result either in a warning or an exception if [`throw` option](https://k6.io/docs/using-k6/options/#throw) is enabled. Additionally, given that k6 has a whole bunch of system tags, one should be careful with using them as keys. You can read complete information about VU tags in [`k6/execution` docs](https://k6.io/docs/javascript-api/k6-execution/#vu).

### Initial basic support for JS promises

With the goja update in [#2197](https://github.com/grafana/k6/pull/2197), you can now make a `Promise` and chain it in your k6 scripts:

```js
export default function () {
    var p = new Promise((resolve, reject) => {
        console.log('do something promising!');
        reject('here');
    });

    p.then(
        (s) => { console.log('fulfilled with', s) },
        (s) => { console.log('rejected with', s) },
    );
}
```

It must be noted that `Promise`s are not used by k6 itself yet but this addition is a stepping stone for implementing async functionality in future releases. Thanks, @dop251, for your awesome work in developing [goja](https://github.com/dop251/goja)! :heart:

### Support for gRPC server reflection ([#2160](https://github.com/grafana/k6/pull/2160))

k6's gRPC capabilities were extended with a support for server reflection which allows one to use gRPC even without a `proto` file at hand. In other words, the following script is now possible:

```js
import grpc from 'k6/net/grpc';
import { check } from "k6";

let client = new grpc.Client();

export default () => {
	client.connect("127.0.0.1:10000", {plaintext: true, reflect: true})
	const response = client.invoke("main.RouteGuide/GetFeature", {
		latitude: 410248224,
		longitude: -747127767
	})

	check(response, {"status is OK": (r) => r && r.status === grpc.StatusOK});
	console.log(JSON.stringify(response.message))

	client.close()
}
```

You can read more about the protocol [here](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md). Thanks, @joshcarp, for putting a lot of effort into this feature!

### Other changes and UX improvements

- Support for cookie jars in `k6/ws` ([#2193](https://github.com/grafana/k6/pull/2193)).
- Forbid `metric.Add` calls to let `NaN` values through. Instead, k6 will log nice warnings or throw an exception if `--throw` is enabled ([#1876](https://github.com/grafana/k6/pull/1876), [#2219](https://github.com/grafana/k6/pull/2219)).
- Support for compression in websockets ([#2162](https://github.com/grafana/k6/pull/2162)). Thanks, @cooliscool!
- Switch to camel case for CLI options to the outputs ([#2150](https://github.com/grafana/k6/pull/2150)). Thanks, @JosephWoodward!
- Much neater error message on `nil` response body ([#2195](https://github.com/grafana/k6/pull/2195)). Thanks, @daniel-shuy!

## New xk6 extensions

### xk6-browser

[xk6-browser](https://github.com/grafana/xk6-browser) is a browser automation extension which relies on [Chrome Devtools Protocol](https://chromedevtools.github.io/devtools-protocol/). With xk6-browser, you can interact with the browser to test your web applications end-to-end while accessing all of the k6 core features, including protocol-level APIs and other k6 extensions. It’s a single tool for both protocol and browser-level testing.

The browser extension comes with an [API](https://k6.io/docs/javascript-api/k6-x-browser/) that aims for rough compatibility with the [Playwright API](https://playwright.dev/docs/api/class-playwright) for NodeJS, meaning k6 users do not have to learn an entirely new API.

### xk6-output-remote-write

Prometheus is now officially supported in k6 OSS with a [xk6-output-remote-write extension](https://github.com/grafana/xk6-output-prometheus-remote). This is an output extension with implementation for [Prometheus Remote-Write protocol](https://docs.google.com/document/d/1LPhVRSFkGNSuU1fBd81ulhsCPR4hkSZyyBj1SZ8fWOM/edit#heading=h.3p42p5s8n0ui) which means that beyond Prometheus, any compatible remote-write solution can be used with it. You can read the full guide to using the extension in the [relevant tutorial](https://k6.io/docs/results-visualization/prometheus/).

### xk6-output-influxdb

After hard work at working out how to integrate InfluxDB v2 API, it was decided to pull that integration into a new [xk6-output-influxdb extension](https://github.com/grafana/xk6-output-influxdb) [for now](https://github.com/grafana/k6/issues/1730#issuecomment-964239639). The built-in `influxdb` output in k6 still supports only InfluxDB v1, as before, with some minor optimizations ([#2190](https://github.com/grafana/k6/pull/2190)).

Please try out the new extensions and tell us what you think!

## Breaking changes

- The addition of common metrics registry ([#2071](https://github.com/grafana/k6/pull/2071)) no longer allows defining custom metrics with the same name as one of the builtin metrics, e.g. `new Counter("http_req_duration")` will now abort. Similarly, an attempt to redefine a metric with the same name but with different type will error out. Builtin metrics may no longer be referenced as global objects in xk6 extensions either.
- Fix inconsistency in environment variables' names: use `K6_NO_SETUP` and `K6_NO_TEARDOWN` options instead of `NO_SETUP` and `NO_TEARDOWN` ([#2140](https://github.com/grafana/k6/pull/2140)).
- Module interfaces were changed as part of refactoring efforts. Any JS module that needs access to the VU must now implement the new interfaces. This change can impact some xk6 extensions ([#2234](https://github.com/grafana/k6/pull/2234)).

## Bugs fixed!

- Fix of a misleading sorting of custom submetrics in the default end-of-test summary ([#2198](https://github.com/grafana/k6/pull/2198)). Thanks, @knittl!
- Fix for extensions depending on `afero.FS`: implement a newer version of the `afero.FS` interface for internal filesystems so that extension depending on that or newer version can be built ([#2216](https://github.com/grafana/k6/pull/2216)).
- Fix for websockets: websockets now use the global `User-Agent` setting ([#2151](https://github.com/grafana/k6/pull/2151)). Thanks, @cooliscool!
- Fixes for tests, Github actions, and Loki integration ([#2205](https://github.com/grafana/k6/pull/2205), [#2153](https://github.com/grafana/k6/pull/2153), [#2220](https://github.com/grafana/k6/pull/2220)).

## Maintenance

- Update a whole bunch of dependencies ([#2159](https://github.com/grafana/k6/pull/2159), [#2170](https://github.com/grafana/k6/pull/2170), [#2165](https://github.com/grafana/k6/pull/2165)).
- Switch to Go 1.17 ([#2156](https://github.com/grafana/k6/pull/2156)). Thanks, @b5710546232!
- Get rid of `mapstructure` ([#2223](https://github.com/grafana/k6/pull/2223)).
- Minor but necessary cleanups ([#2164](https://github.com/grafana/k6/pull/2164), [#2192](https://github.com/grafana/k6/pull/2192)).

## hacktoberfest

k6 participated in this year's [hacktoberfest](https://github.com/grafana/k6/issues?q=is%3Aissue+label%3Ahacktoberfest+is%3Aclosed+milestone%3Av0.35.0) and we would like to thank all contributors! Here're some additional improvements made by the community members:

- Add multi-message WebSockets tests ([#2184](https://github.com/grafana/k6/pull/2184)).
- Try out the new and shiny Github forms which are already improving the formatting of k6's new issues ([#2174](https://github.com/grafana/k6/pull/2174),[#2179](https://github.com/grafana/k6/pull/2179)).
- An improved writing style and correctness in our README ([#2189](https://github.com/grafana/k6/pull/2189), [#2152](https://github.com/grafana/k6/pull/2152), [#2169](https://github.com/grafana/k6/pull/2169), [#2181](https://github.com/grafana/k6/pull/2181)) and in some other places ([#2182](https://github.com/grafana/k6/pull/2182)).

Thank you, @knittl, @cooliscool, @JosephWoodward, @b5710546232, @nontw, @divshacker, @daniel-shuy, @Sayanta66, @marooncoder09, @idivyanshbansal, @saintmalik, @EricSmekens, for helping make k6 better :smile: