k6 v0.38.0 is here! 🎉

## New Features!

### AWS JSLib

There's a new addition to the officially supported k6 JavaScript libraries: [k6-jslib-aws](https://github.com/grafana/k6-jslib-aws).
This library lets users interact with a selection of AWS services directly from their scripts. The library currently implements support for the [S3](https://k6.io/docs/javascript-api/jslib/aws/s3client/) and the [Secrets Manager](https://k6.io/docs/javascript-api/jslib/aws/secretsmanagerclient/) services.

[The AWS JS lib documentation](https://k6.io/docs/javascript-api/jslib/aws) has examples and details on how to use the library in your scripts.

### Accessing the consolidated and derived options from the default function ([#2493](https://github.com/grafana/k6/pull/2493))

The `k6/execution` core module now lets you access the [consolidated and derived](https://k6.io/docs/using-k6/options/#where-to-set-options) options that k6 computed before it started executing the test. You can access consolidated options through the `exec.test.options` property. Note that consolidated options are frozen and cannot be modified. [The k6 execution module's documentation](https://k6.io/docs/javascript-api/k6-execution/#test) has examples and details on how to use the functionality in your scripts.

```javascript
import exec from "k6/execution";

export const options = {
    vus: 10,
    duration: "30s",
};

export default function () {
    console.log(exec.test.options.scenarios.default.vus); // 10
}
```

### Tagging metric values with the current scenario stage

With the new consolidated script options, we've added a few helper functions to the [k6-jslib-utils](https://k6.io/docs/javascript-api/jslib/utils) library. You can use them to automatically tag all the emitted metric samples by k6 with the currently running stage.

[The k6 documentation](https://k6.io/docs/using-k6/tags-and-groups/#tagging-stages) has examples and details on how to use it.

### Dumping SSL keys to an NSS formatted key log file ([#2487](https://github.com/grafana/k6/pull/2487))

This release adds the ability to dump SSL keys while making TLS connections.
You then can use these keys to decrypt all traffic that k6 generates.

To accomplish this, set the `SSLKEYLOGFILE` environment variable to some file path and run k6.
This will populate the file with the keys.
Then you can use Wireshark to capture the traffic, decrypt it, and use that for debugging.

[Here's an example that uses curl to inspect TLS traffic](https://daniel.haxx.se/blog/2018/01/15/inspect-curls-tls-traffic/).

## Breaking Changes

### `console` methods now pretty print objects and arrays ([2375](https://github.com/grafana/k6/pull/2375))

For convenience, all `console` methods such as `console.log()` and `console.info()` will now automatically `JSON.stringify()` objects and arrays passed to them. Thus, instead of `console.log({'foo': 'bar'})` printing `[object Object]`, it will now print `{'foo': 'bar'}`, which will make the experience of debugging k6 scripts easier and more intuitive.

To achieve the previous behavior, cast the `Object` to a `String`, as in `console.log(String({'foo': 'bar'}))`.

```javascript
export default function () {
    console.log([1, 2, "test", ["foo", "bar"], { user: "Bob" }]);
    // before: 1,2,test,foo,bar,[object Object]
    // after: [1,2,"test",["foo","bar"],{"user":"Bob"}]
}
```

### The Go types in the `stats` package were moved to the `metrics` package [#2433](https://github.com/grafana/k6/pull/2433)

For convenience and to facilitate further developments, the types and functionalities that used to live in k6's `stats` package have been moved to the `metrics` package. The `stats` package is, as of **v0.38.0**, removed in favor of the `metrics` package. Besides, [#2442](https://github.com/grafana/k6/pull/2442) removed the `stats.New` function in favor of initializing new metric via a `register.NewMetric` call instead.  

### Deprecation

-   [#2499](https://github.com/grafana/k6/pull/2499) removed support for the deprecated maxVUs option.
It had been removed in k6 v0.27.0, however using the CLI flag resulted only in a deprecation warning.
Now, using this flag will generate an error.
-   This release drops some leftovers from the previous version of our JS module Go APIs. As of **v0.38.0**, these are now unsupported:
    -   The deprecated `common.Bind` ([#2488](https://github.com/grafana/k6/pull/2448)) and `common.BindToGlobal` ([#2451](https://github.com/grafana/k6/pull/2451)) functions.
    -   The context-based (`common/context.go` [#2488](https://github.com/grafana/k6/pull/2448)) utils have also been removed.

## Enhancements and UX improvements

### Stricter thresholds' evaluation before the execution starts ([#2330](https://github.com/grafana/k6/issues/2330))

k6 **v0.37.0** already improved threshold parsing by switching its underlying implementation from JavaScript to Go. k6 **v0.38.0** introduces two additional improvements:

-   k6 will now parse and evaluate thresholds before the execution starts. If a threshold is invalid, as described below, k6 will immediately exit without starting the load test.
-   k6 will now detect invalid thresholds:
    ```javascript
    export const options = {
        // ...
        thresholds: {
            // Incorrect thresholds expressions:
            http_req_failed: ["rave<0.01"], // e.g. "rave" is not a valid aggregation method
            // Thresholds applying to a non-existing metrics:
            iDoNotExist: ["p(95)<200"], // e.g. the metric 'iDoNotExist' does not exist
            // Thresholds applying an aggregation method that's unsupported by the metric they apply to:
            my_counter: ["p(95)<200"], // Counter metrics do not support the p() aggregation method
        },
    };
    ```

### Disabling colors ([#2410](https://github.com/grafana/k6/pull/2410))

In addition to the [`--no-color` CLI flag](https://k6.io/docs/using-k6/options/#no-color), the ANSI color escape codes emitted by k6 can now also be disabled by setting the `NO_COLOR` or `K6_NO_COLOR` environment variables, following the [NO_COLOR standard](https://no-color.org/).

```bash
# No color output
K6_NO_COLOR=true k6 run script.js

# No color output
NO_COLOR= k6 run script.js
```

### Support for encrypted TLS private keys ([#2488](https://github.com/grafana/k6/pull/2488))

You can now use passphrase-protected private keys when authenticating with TLS. Using the `password` property of an options' `tlsAuth` object, you can now indicate the passphrase to decrypt a private key. Note that this support is limited to the scope of [RFC1423](https://datatracker.ietf.org/doc/html/rfc1423) and does not support PKCS8 keys, as they're not yet supported by the Golang standard library.

```javascript
export const options = {
    tlsAuth: [
        {
            domains: ["example.com"],
            cert: open("mycert.pem"),
            key: open("mycert-key.pem"),
            password: "mycert-passphrase",
        },
    ],
};
```

Thanks, @Gabrielopesantos, for the [contribution](https://github.com/grafana/k6/pull/2488).

### Improve JSON output's performance ([#2436](https://github.com/grafana/k6/pull/2436))

The JSON output was optimized and now should be around 2x more performant at outputting metrics. This means that it either can export twice as many metrics, or use half the resources to do the same amount of metrics.

As a side effect, there is a slight breaking change: the `tags` field is no longer sorted.

### Treat panics as interrupt errors ([#2453](https://github.com/grafana/k6/pull/2453))

We changed the behavior of how k6 treats Go panics, which may happen because of bugs in k6 or in a JavaScript k6 extension. Previously, the behavior was to catch the panic and log it as an error.

Starting with **v0.38.0**, whenever k6 observes a Go panic, it logs an error like before, but more importantly, it will abort the script execution and k6 will exit with a non-0 exit code. This will help extension authors to identify issues in their extensions more easily.

### Miscellaneous

-   [#2411](https://github.com/grafana/k6/pull/2411) The k6 command-line UI (logo, test description, and progress bars) can now effectively be disabled using the [`--quiet`](https://k6.io/docs/using-k6/options/#quiet) flag.
-   [#2429](https://github.com/grafana/k6/pull/2429) `lib/types` now exposes the source of the `NullHostnameTrie` to simplify access to an original list of the hostnames.

## Extensions

### PoC for a new Web Sockets JS API

We built a new xk6 extension, https://github.com/grafana/xk6-websockets, with a proof of concept implementation for a new JavaScript Web Sockets API. This API uses the global event loops [introduced in k6 v0.37.0](https://github.com/grafana/k6/releases/tag/v0.37.0) to allow a single VU to have multiple concurrent web socket connections open simultaneously, greatly reducing the resources needed for large tests. It also is a step towards supporting the [official Web Sockets JS standard](https://websockets.spec.whatwg.org/), potentially allowing the usage of more third-party JS libraries in the future.

Please share any feedback you have about the new extension since it's likely that we'll adopt a future version of it into the k6 core in one of the next several k6 releases.

### gRPC module refactored to enable gRPC extensions to use it

[#2484](https://github.com/grafana/k6/pull/2484) moved out in a new dedicated Go `lib/netext/grpcext` package all the parts not strictly required from the `js/k6/net/grpc` module for binding the gRPC operations and the JavaScript runtime. It facilitates the development of extensions based on gRPC without the direct dependency on the `goja` runtime. Furthermore, the new [Dial](https://github.com/grafana/k6/blob/bef458906f6884a99843573223028981c0a8b8db/lib/netext/grpcext/conn.go#L72-L81) function accepts a [grpc.DialOption](HTTPS://pkg.go.dev/google.golang.org/grpc@v1.45.0#DialOption) variadic for customizing the dialing operation.

### Event loop testing

With this release, you can [export the event loop](https://pkg.go.dev/go.k6.io/k6/js/eventloop) added in v0.37.0. This lets extension developers test event-loop-dependent APIs.

There were also updates to [modulestest.VU](https://pkg.go.dev/go.k6.io/k6/js/modulestest#VU) to support the new API. Head to GitHub to [see it in action](https://github.com/grafana/k6/tree/master/cmd/integration_tests/testmodules/events).

## Bugs Fixed!

-   [#2456](https://github.com/grafana/k6/pull/2456): Fixed a very unlikely panic involving arrival rate executors and execution segments with very low VU counts.
-   [#2349](https://github.com/grafana/k6/issues/2349): Thanks to @rainingmaster it is now possible to leave the options' tlsAuth `domains` property empty.
-   [#1346](https://github.com/grafana/k6/issues/1346): Thresholds over custom metrics for which no data was collected will now be evaluated.
-   [#2390](https://github.com/grafana/k6/issues/2390): Thresholds over sub-metrics with empty tag values will now return the appropriate results.
-   [#2480](https://github.com/grafana/k6/issues/2480): Fixed an error occurring when passing the `data` property of an `http.file()` result as a request body.

## Known issues

-   @hecnavsanz [reported to us](https://github.com/grafana/k6/issues/2500) that in certain scenarios, k6's UI might inaccurately report a test as failed :x: when it actually succeeded :white_check_mark:. This is caused by some concurrency issue in our codebase that only affects the report's UI, and has no impact on the actual test result. A [fix](https://github.com/grafana/k6/pull/2502) is in the works, but won't be ready for this version. We expect to ship it with the next k6 release instead.

## Maintenance

### Dependencies

-   [#2479](https://github.com/grafana/k6/pull/2479) updated k6's Goja version to `9037c2b61cbf`.
-   [#2449](https://github.com/grafana/k6/pull/2449), [#2446](https://github.com/grafana/k6/pull/2446), [#2444](https://github.com/grafana/k6/pull/2444), and [#2443](https://github.com/grafana/k6/pull/2443) updated k6 Go dependencies to their latest compatible versions.

### Other

-   [#2504](https://github.com/grafana/k6/pull/2504) updated our installation instructions to reflect the recent changes in the behavior of the `go install` command. Thanks, @JamieEdge, for your contribution!
-   [#2437](https://github.com/grafana/k6/pull/2437) refreshed our contribution guidelines.
-   [#2431](https://github.com/grafana/k6/pull/2437) refreshed out our dependencies update workflow, process, and guidelines.
