k6 v0.37.0 is here! 🎉 Mainly it contains fixes and ongoing efforts with refactoring.

## New Features!

### Added experimental basic event loop ([#882](https://github.com/grafana/k6/issues/882))

We added basic event loop support in k6 ([#2228](https://github.com/grafana/k6/pull/2228) and [#2373](https://github.com/grafana/k6/pull/2373)) :tada: This was just the first step and isn't used by any of the existing k6 JS APIs yet. For now, it is only available to [xk6 extensions](https://k6.io/docs/extensions/guides/what-are-k6-extensions/) like [this one](https://github.com/MStoykov/xk6-events) that adds support for `setTimeout()`, `setInterval()`, `clearTimeout()` and `clearInterval()`.

Expect to see more changes related to event loops in the next k6 releases, where event loops will start being used by some core k6 modules! For example, by improving some existing JavaScript APIs to have support for callbacks or return `Promise` values, so they can be used asynchronously. We expect this change will unlock a lot of previously difficult use cases (see [#882](https://github.com/grafana/k6/issues/882)), though we'll likely iterate on these new APIs as experimental extensions for a while, to stabilize them before we merge them into the core.

:information_source: If you are an extension developer, please use it and give your feedback. But take into consideration that it's likely that the current Go API may change.

### Added an option to output k6 logs to a file through --log-output ([#2285](https://github.com/grafana/k6/pull/2285))

This is on top of the already supported options for sending logs to stdout/stderr and to [Grafana Loki](https://grafana.com/oss/loki/). This new feature speaks for itself with simple usage examples:

```sh
k6 run --log-output file=./k6.log --logformat json ./examples/stages.js
```

And one more with a defined minimal log level:

```sh
k6 run --log-output file=./k6.log,level=info --logformat json ./examples/stages.js
```

Thanks, @[alyakimenko](https://github.com/alyakimenko) for the contribution!

**Docs**: [Using file output](https://k6.io/docs/using-k6/options/#file)

## Breaking changes

### Introduced stricter thresholds parsing ([#2400](https://github.com/grafana/k6/pull/2400))

In the past, thresholds were evaluated using a JavaScript runtime. For a multitude of reasons, this wasn't satisfying. As of **v0.37.0**, thresholds are now parsed directly in Go. As a result, k6 will now return an error message on thresholds that do not strictly match [the documented specification](https://k6.io/docs/using-k6/thresholds/), instead of just silently ignoring them. Another change is that when a non syntactically correct threshold expression is detected, k6 will immediately interrupt its execution before even starting the load test run.

Below you can find examples of the thresholds expressions that won't work anymore:

```js
export const options = {
    thresholds: {
        "http_req_duration": [
            // although the aggregation method and values are correct, 
            // the equal sign is invalid; use == or ===
            "rate=200",
            // thresholds do not support javascript expressions anymore
            "throw new Error('wat')",
            // it fails, as foo is not a valid threshold expression's aggregation method keyword
            "foo>500",
        ],
    },
};
```

### Extensions

`v0.37.0` finalizes ([#2376](https://github.com/grafana/k6/pull/2376)) the switching of our internal modules ([gRPC module refactoring](https://github.com/grafana/k6/pull/2365)) to [a new Go/JavaScript module API](https://k6.io/docs/extensions/guides/create-an-extension/#advanced-javascript-extension).

:warning: It's important to highlight that the old API (e.g. methods like `context.WithRuntime`, `common.Bind` and others [#2384](https://github.com/grafana/k6/pull/2384)) is deprecated and will be removed in the next k6 release (`v0.38.0`). For this release, every extension that isn't using the new API will get a warning message like this:

```sh
WARN[0000] Module 'k6/x/sql' is using deprecated APIs that will be removed in k6 v0.38.0, for more details on how to update it see https://k6.io/docs/extensions/guides/create-an-extension/#advanced-javascript-extension
```

We did migrations for some xk6 extensions (see connected issues to the task [#2344](https://github.com/grafana/k6/issues/2344)). The pull requests can serve as examples on how to transition your extension to the new API.

### Docker Repository

We migrated our Docker Hub repository from `loadimpact/k6` to [grafana/k6](https://hub.docker.com/r/grafana/k6) ([#2377](https://github.com/grafana/k6/pull/2377)).

```sh
docker run -i grafana/k6 run - <script.js
```

We will continue publishing our docker image releases as both `loadimpact/k6` and `grafana/k6` for several more releases, but if you use the old one in your local or CI environments, please plan the migration.

## Enhancements and UX improvements

- We continued work on the source map feature: add samples ([#2339](https://github.com/grafana/k6/pull/2339)) and improve loading and parsing ([#2355](https://github.com/grafana/k6/pull/2355)).
- Updated installation from source instructions ([#2359](https://github.com/grafana/k6/pull/2359)). Thanks, @[karitham](https://github.com/Karitham), for making the change.
- Enabled more TC39 tests: [optional-chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) ([#2338](https://github.com/grafana/k6/pull/2338)) and async ([#2396](https://github.com/grafana/k6/pull/2396)).
- We updated our [Code of Conduct](https://github.com/grafana/k6/blob/master/CODE_OF_CONDUCT.md) and a few GitHub URLs ([#2416](https://github.com/grafana/k6/pull/2416)).

## Bugs fixed!

- [`http.head`](https://k6.io/docs/javascript-api/k6-http/head-url-params/) started taking a body as a second argument ([#2402](https://github.com/grafana/k6/pull/2402)) by mistake in v0.36.0. It is now back to its old signature `http.head(url, [params])`.
- Fixed [options.scenarios'](https://k6.io/docs/using-k6/options/#scenarios) JSON marshaling ([#2392](https://github.com/grafana/k6/pull/2392)).
- Metrics' names display again in k6's Rest API ([#2421](https://github.com/grafana/k6/pull/2421)).
- We improved argument validation for [`check`](https://k6.io/docs/javascript-api/k6/check-val-sets-tags)([#2387](https://github.com/grafana/k6/pull/2387)), [`http.batch`](https://k6.io/docs/javascript-api/k6-http/batch-requests)([#2415](https://github.com/grafana/k6/pull/2415)) and [metrics' constructors](https://k6.io/docs/javascript-api/k6-metrics/) ([#2427](https://github.com/grafana/k6/pull/2427)).

## Internals

- We updated our CI to improve developer experience. Dependency and linter checks now run only for pull requests ([#2403](https://github.com/grafana/k6/pull/2403)).
- This release also contains a few refactoring PRs that fix linters errors ([#2334](https://github.com/grafana/k6/pull/2334), [#2331](https://github.com/grafana/k6/pull/2331) and [#2341](https://github.com/grafana/k6/pull/2341)), remove global variable usage ([#2336](https://github.com/grafana/k6/pull/2336), [#2358](https://github.com/grafana/k6/pull/2358), [#2353](https://github.com/grafana/k6/pull/2353) and [#2357](https://github.com/grafana/k6/pull/2357)) and remove an unnecessary dependency ([#2313](https://github.com/grafana/k6/pull/2313)) which makes our codebase more consistent and maintainable.
- The `headers` parameter in k6's GRPC module is marked as deprecated ([#2370](https://github.com/grafana/k6/pull/2370)).
- Switched `envconfig` to our own fork ([#2337](https://github.com/grafana/k6/pull/2337)) in order to abstract the `os` package and improve testability.
