> OctoPerf load testing - K6 protocols and extensions documentation page. The protocols a K6 Virtual User can load test, how their calls show in the report, and how to add xk6 extensions.

Source: https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-protocols/

# K6 protocols and extensions

A [K6 Virtual User](https://api.octoperf.com/doc/design/create-virtual-user/import-k6-scripts/) runs in the `octoperf/k6` image, on a K6 binary that carries the modules of K6 and a few xk6 extensions. Each call a script makes through one of the modules below is measured and shows in the report as a request, with its response time, its status and, in a validation or for an error, the exchange itself.

## Protocols

| Protocol | Module | A request in the report | Status |
|----------|--------|-------------------------|--------|
| HTTP | `k6/http` | one per request, named after its `name` tag, or its URL without the query | the HTTP status |
| gRPC | `k6/net/grpc` | one per call, unary or streamed | the gRPC status name, `OK`, `NOT_FOUND`... |
| WebSocket | `k6/websockets`, `k6/ws` | one per session, from its handshake to its closure | failed when the handshake is refused or the connection is lost without a close frame |
| SQL | `k6/x/sql`, with the `k6/x/sql/driver/postgres` and `k6/x/sql/driver/mysql` drivers | one per `query` or `exec`, named after the statement, literals masked | `OK` or `FAILED` |
| Redis | `k6/x/redis` | one per command, named after the command, never its key | `OK` or `FAILED` |
| Kafka | `k6/x/kafka` | one per `produce`, `flush`, `close` and `consume`, named after the operation and its topic: `PRODUCE orders` | `OK` or `FAILED` |

- A request sits under the entrypoint of the script and the `group` it runs in, like the actions of a JMeter Virtual User.
- The messages of a gRPC stream, a WebSocket session or a Kafka call are counted on their own, as `sent` and `received`, rather than as hits: a message has no response time.
- The connection strings of SQL and the credentials of Redis are never recorded: the target of a SQL request is `sql://<driver>/`, the one of a Redis command `redis://host:port`.

!!! info
    A Kafka producer sends its messages to the broker when it flushes: a `produce` to a topic that cannot receive them returns at once, and the failure shows on the `FLUSH` of that topic, when the producer is flushed or closed.

!!! note
    The `k6/browser` module is not supported: to drive a real browser, use a [Playwright Virtual User](https://api.octoperf.com/doc/design/create-virtual-user/import-playwright-node-project/). See [K6 limits](https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-limits/#script).

## Extensions

An xk6 extension is Go code compiled into the K6 binary: K6 cannot load one when the test starts. The binary of the load generators carries these extensions, which a script imports by their `k6/x/` name:

- `k6/x/sql`, with its Postgres and MySQL drivers,
- `k6/x/redis`,
- `k6/x/kafka`.

A script that imports another extension is refused by the [sanity check](https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-script-action/#sanity-check), and by the load generator if it runs anyway. K6 would otherwise download a binary of its own that carries the extension, but not the OctoPerf measurements, so this automatic resolution is turned off.

### Adding your own extensions

With OctoPerf Enterprise Edition, you can rebuild the `octoperf/k6` image with extensions of your own. The image carries what it takes in `/opt/octoperf/k6`, its `Dockerfile` included:

```sh
docker run --rm --entrypoint cat octoperf/k6 /opt/octoperf/k6/Dockerfile > Dockerfile
docker build --platform linux/amd64 \
  --build-arg EXTENSIONS="github.com/grafana/xk6-faker@v0.5.3" \
  -t registry.acme.com/octoperf/k6:1.0 .
```

- `EXTENSIONS` lists the Go modules to compile in, each at the version named, separated by spaces.
- `OCTOPERF_K6` names the image to start from, `octoperf/k6:latest` by default: pass `--build-arg OCTOPERF_K6=octoperf/k6:<version>` to build on the version of your OctoPerf installation.
- The build ends by running `k6 version` in the new image.

To use the new image:

- push it to the registry of your load generators, and set `docker.image.k6` in the [configuration of the OctoPerf backend](https://api.octoperf.com/doc/on-premise-infra/configuration/#k6) to its name;
- add the modules your extensions register to `octoperf.k6.extensions`, by the name after `k6/x/`, so that the sanity check accepts them. The default value lists the extensions of the stock image: `octoperf,sql,sql/driver/postgres,sql/driver/mysql,redis,kafka`.

!!! warning
    An extension of your own is not measured the way the extensions above are: its calls do not show as requests, and the K6 metrics it records show as [custom metrics](https://api.octoperf.com/doc/analysis/edit-bench-report/metrics-selection/#custom-metrics). The load generator also refuses a binary that no longer carries the `k6/x/octoperf` extension, so always start from the `Dockerfile` of the image.

## Licence

K6 is published under the [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.html), and so is the K6 binary of the `octoperf/k6` image. Its corresponding source ships in the image, in `/opt/octoperf/k6`:

- `LICENSE`, the licence,
- `extension/`, the source of the OctoPerf extension,
- `binary/`, the Go module that builds the binary,
- `SOURCES.txt`, where to get the source of every other module compiled in, at its exact version, with their licences in `licenses/`.

```sh
docker run --rm --entrypoint cat octoperf/k6 /opt/octoperf/k6/SOURCES.txt
```

The rest of OctoPerf, the Java agent that runs next to K6 in the image included, is not covered by this licence.
