k6 v0.41.0 is here! :tada: It has relatively few user-facing changes, but includes massive internal improvements that pave the way for some awesome features for the near future. Unfortunately, this work also required us to make a few [minor breaking changes](#breaking-changes).

## Breaking changes

### Changes in the `url`, `iter` and `vu` system metric tags

As we warned in the release notes for k6 [v0.39.0](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/release%20notes/v0.39.0.md#roadmap-and-future-plans) and [v0.40.0](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/release%20notes/v0.40.0.md), we've been fundamentally [refactoring the metrics sub-systems](#metric-time-series) of k6. We now have efficient support for time series, which required a few minor user-facing breaking changes:

- If [URL grouping](https://k6.io/docs/using-k6/http-requests/#url-grouping) is used for HTTP requests (that is, if the [`http.url` helper](https://k6.io/docs/javascript-api/k6-http/urlurl/) is used or the `name` metric tag is specified), then the `url` tag in the resulting `http_req_*` metric samples will also have the same value as the `name` tag. Previously, k6 did this only for [the `cloud` output](https://k6.io/docs/results-output/real-time/cloud/), but now it does this universally ([#2703](https://github.com/grafana/k6/pull/2703)).
- The [`vu` and `iter` system tags](https://k6.io/docs/using-k6/tags-and-groups/#system-tags), which are disabled by default, have been transformed into [high-cardinality metrics metadata](#internal-support-for-high-cardinality-metrics-metadata) instead. It means that they will no longer be usable in thresholds, and various outputs may emit them differently or ignore them completely ([#2726](https://github.com/grafana/k6/pull/2726)).

### Changes in the Go metrics APIs

While the user-facing changes from our metrics refactoring are few and relatively minor, and there are no changes to JavaScript APIs yet, we have extensively refactored our internal Go APIs ([#2594](https://github.com/grafana/k6/pull/2594), [#2726](https://github.com/grafana/k6/pull/2726), [#2727](https://github.com/grafana/k6/pull/2727)). The [`metrics.Sample`](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/metrics/sample.go#L11-L33) and [`metrics.TagSet`](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/metrics/tags.go#L16-L157) types are now entirely different. We also have high-cardinality metadata attributes in each `Sample` and at the VU level (see the [combined `TagsAndMeta` code](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/metrics/tags.go#L159-L231) and [how it is used in the per-VU `State` object](https://github.com/grafana/k6/blob/2fe2dd32b3827eeeeb3959aff63a6b402aab0a5a/lib/vu_state.go#L83-L119)).

### `k6 convert` is officially deprecated ([#2714](https://github.com/grafana/k6/pull/2714))

`k6 convert` has been a sub-command to convert a [HAR file recording](https://en.wikipedia.org/wiki/HAR_(file_format)) of HTTP traffic into a preliminary k6 script that makes roughly the same requests. It has been long neglected and softly deprecated in favor of the newer and more feature-rich [har-to-k6 standalone converter](https://github.com/grafana/har-to-k6).

We have now officially deprecated `k6 convert`. The command still works and will continue to do so for a few more k6 versions. However, it's not visible from `k6 --help` and will emit a warning when used. Please see the [documentation for the standalone har-to-k6 converter](https://k6.io/docs/test-authoring/recording-a-session/har-converter/) and [open an issue](https://github.com/grafana/har-to-k6/issues) (or comment on an existing one) if you have any problems with it.

## New Features, enhancements, and UX improvements

- [#2679](https://github.com/grafana/k6/pull/2679) added support for `maxReceiveSize` and `maxSendSize` parameters in the [gRPC's `Client.connect()` method](https://k6.io/docs/javascript-api/k6-net-grpc/client/client-connect/). Thanks, @ariasmn!
- [#2605](https://github.com/grafana/k6/pull/2605) introduced a new `--exclude-env-vars` CLI flag to [`k6 archive`](https://k6.io/docs/misc/archive-command/) that causes it to not include the provided environment variables in the resulting archive bundle's `metadata.json` file.
- [#2700](https://github.com/grafana/k6/issues/2700) added support for loading gRPC protoset files. Thanks, @jklipp!

## Bug fixes

- [#2678](https://github.com/grafana/k6/pull/2678) fixed the Docker image labels. Thanks, @knittl, for reporting the problem ([#2677](https://github.com/grafana/k6/issues/2677))!
- [#2689](https://github.com/grafana/k6/pull/2689) fixed the REST API's `Content-Type` response header. Thanks, @wingyplus!
- [#2691](https://github.com/grafana/k6/pull/2691) fixed the detailed `k6 version` information embedded in the k6 releases.
- [#2693](https://github.com/grafana/k6/pull/2693) fixed a bug that made the k6 event loop unusable when a Promise rejection was left unhandled.
- [#2696](https://github.com/grafana/k6/pull/2696) fixed a problem with HTTP redirects with empty `Location` headers ([#2474](https://github.com/grafana/k6/issues/2474)) by updating the Go version we use to compile k6 to 1.19.x. Thanks, @agilob!
- [#2705](https://github.com/grafana/k6/pull/2705) fixed a panic in the `k6/net/grpc` module ([#2661](https://github.com/grafana/k6/issues/2661)). Thanks, @c47gao and @robpickerill!
- [#2738](https://github.com/grafana/k6/pull/2738) fixed a panic when a Promise was rejected with an `undefined` reason.
- [#2739](https://github.com/grafana/k6/pull/2739) fixed hidden stack traces in certain types of errors originating from k6's Go code.

## Maintenance and internal improvements

We had a few minor changes in this release:

- [#2687](https://github.com/grafana/k6/pull/2687) improved our logging tests. Thanks, @nsmith5!
- [#2696](https://github.com/grafana/k6/pull/2696) updated the used Go version to 1.19.x and the Alpine version in our Docker image to 3.16. Thanks, @agilob!
- [#2707](https://github.com/grafana/k6/pull/2707), [#2708](https://github.com/grafana/k6/pull/2708), [#2709](https://github.com/grafana/k6/pull/2709), [#2710](https://github.com/grafana/k6/pull/2710) updated most of the Go dependencies k6 has.
- [#2716](https://github.com/grafana/k6/pull/2716) refactored how custom JS tags are applied to metrics and cleaned up validation for invalid tag values.

We also have a couple of significant improvements that will help us develop exciting new features soon:

### Metric time series ([#2594](https://github.com/grafana/k6/pull/2594))

Previous to [#2594](https://github.com/grafana/k6/pull/2594), k6 didn't have an efficient way to group metric samples with the same tags. It meant that a whole class of applications for processing and aggregating metrics were nearly impossible to do or, at best, very inefficient.

At the cost of some minor [breaking changes](#breaking-changes), we now have a performant internal representation to group metric samples with the same tags at the time of the action that generated them, i.e. the time of metric measurement. With this, k6 can efficiently group samples for the same action (e.g. an HTTP request to a specific URL) over time and construct time series with them.

### Internal support for high-cardinality metrics metadata ([#2726](https://github.com/grafana/k6/pull/2726), [#2727](https://github.com/grafana/k6/pull/2727))

As described in the previous section, the efficient grouping of metric samples into time series works well for relatively low-cardinality data. However, k6 needed some way to attach high-cardinality metadata as well. This is necessary for data that's unique or random, such as Trace and Span IDs in distributed tracing or user IDs in tests with huge data sets.

k6 v0.41.0 has added support for attaching high-cardinality metadata to metric samples, and the `vu` and `iter` system tags have been transformed into such metadata (see the [breaking changes section](#breaking-changes) above), but it is not yet accessible from user scripts. There is no JavaScript API to modify this metadata, only built-in k6 Go modules and [xk6](https://github.com/grafana/xk6) Go extensions can make use of it, for now.
