In k6, how do you choose where a run streams its metrics, and which `--out` targets does v2 accept?
answer
- one flag, and you may repeat it
- an environment variable holds the same list
- target name, then an optional =argument
- eight accepted names in k6 v2
- 'summary' is in the enum, not the map
basics
~20 sk6 picks streaming destinations with the repeatable -o/--out flag or the K6_OUT environment variable. k6 v2 accepts json, csv, cloud, influxdb, experimental-prometheus-rw, opentelemetry, experimental-opentelemetry and web-dashboard; any other name aborts the run before it starts.
solid answer
~40 s`-o` (long form `--out`) is a repeatable flag, so `k6 run -o json=raw.json -o experimental-prometheus-rw script.js` attaches both and every sample goes to both. Each value is a bare target name or `name=argument`, split at the first `=`, and the argument means whatever that one target decides. `K6_OUT` sets the same list, but a `-o` on the command line replaces it rather than adding to it, and the script's exported `options` object has no key for it at all. The names k6 v2 accepts are `json`, `csv`, `cloud`, `influxdb`, `experimental-prometheus-rw`, `opentelemetry`, `experimental-opentelemetry` and `web-dashboard`; `K6_WEB_DASHBOARD=true` also appends `web-dashboard`. Anything else fails with `invalid output type`, and `summary` is one of those failures.
code
bash · 9 lines# two destinations from one run; -o is repeatable
k6 run -o json=raw.json.gz -o experimental-prometheus-rw script.js
# the same list via the environment variable
K6_OUT=json=raw.json.gz k6 run script.js
# rejected before any VU starts:
# invalid output type 'summary', available types are: cloud, csv, ...
k6 run -o summary script.jsgo deeper
Remember the flag itself: -o or --out, and that it takes a target name optionally followed by = and that target's own argument, as in -o json=out.json.
Be able to list the accepted names for k6 v2 and explain that the flag repeats, that K6_OUT holds the same list, and that a target name is resolved before any virtual user starts.
Show that you attach a cheap local target alongside a network one on a long run, and that you know which targets ignore their -o argument and take environment variables instead.
The tradeoff to voice is standardisation: fixing the output names and their environment variables in one place across a team's runs, so a result stream is never lost to a per-pipeline spelling.
## What `--out` decides k6 produces metric samples continuously while a test runs, and `-o` (long form `--out`) is the single setting that decides where those samples go **while the run is still in progress**. It is a repeatable string-array flag: each occurrence appends one more destination, and k6 hands every sample it produces to all of them. ```bash k6 run -o json=raw.json.gz -o experimental-prometheus-rw script.js ``` That run writes a gzipped local file and pushes to a Prometheus remote-write endpoint at the same time, from one process, with no duplication of work in the script. ## Where the setting can live - **`-o` / `--out` on the command line** — repeatable, and the last word on the subject. - **`K6_OUT`** — the environment variable bound to the same list. A `-o` on the command line **replaces** what `K6_OUT` produced rather than adding to it; the two lists are never concatenated. - **The script's exported `options` object cannot do it.** k6 has no `out` key at script level, so `export const options = { out: 'json' }` selects nothing. Outputs are a command-layer setting. - **`K6_WEB_DASHBOARD=true`** is the one exception in shape: it names no target, it simply appends `web-dashboard` to whatever list you already have. ## The `name=argument` split Each `-o` value is either a bare target name or `name=argument`, and k6 cuts it at the **first** `=`. Everything left of the cut is the target name; everything right of it is handed to that target verbatim, and what it means is that target's private business. | `-o` value | what the argument means | |---|---| | `json=raw.json` | output file path; `-` or an empty value means stdout | | `csv=out.csv` | output file path | | `csv=fileName=out.csv,saveInterval=5s` | comma-separated settings for the CSV target | | `influxdb=http://localhost:8086/k6db` | InfluxDB v1 address plus the database name | | `web-dashboard=port=5665&period=10s` | a URL query string of dashboard settings | | `experimental-prometheus-rw` | nothing — the argument is discarded; use `K6_PROMETHEUS_RW_*` | | `opentelemetry` | nothing — the argument is discarded; use `K6_OTEL_*` | No target reads another target's variables. `K6_OTEL_EXPORT_INTERVAL` has no effect on Prometheus remote write, and `K6_CSV_SAVE_INTERVAL` has none on the JSON file. ## The names k6 v2 accepts Eight names resolve in k6 v2: - **`json`** — newline-delimited records, to a file or to stdout. - **`csv`** — a header row and one row per sample, to a file or to stdout. - **`influxdb`** — the InfluxDB v1 line protocol; v2 needs an xk6 extension of its own. - **`experimental-prometheus-rw`** — Prometheus remote write, configured by `K6_PROMETHEUS_RW_*`. - **`opentelemetry`** — OTLP metrics to a collector or backend, configured by `K6_OTEL_*`. - **`experimental-opentelemetry`** — the pre-graduation alias of the one above it. - **`web-dashboard`** — a live HTTP dashboard, served on port `5665` by default. - **`cloud`** — Grafana Cloud k6, configured through `options.cloud` and `K6_CLOUD_*`. Two things about that list catch people out: 1. **OpenTelemetry graduated; Prometheus remote write did not.** `opentelemetry` is the stable name. `experimental-opentelemetry` still resolves, but k6 logs a warning telling you to use the short one. Prometheus remote write kept its prefix, so `experimental-prometheus-rw` is the *current and correct* spelling in k6 v2, not a leftover you are expected to modernise. 2. **`summary` is not selectable.** The token exists inside k6's internal output enumeration, but no constructor is registered against it, so `-o summary` is rejected exactly as a typo would be. ## Attaching several destinations to one long run k6 does not deduplicate the list, so two `-o json=` values with different filenames give you two complete files. The practical shape for a long run streaming to a time-series store is a network target plus a cheap local one: the extra `-o json=raw.json.gz` costs one more writer on the same sample stream and leaves a byte-for-byte record of what k6 emitted, which is the only artifact that survives if the remote endpoint starts refusing pushes halfway through. ## When a bad name is caught k6 resolves and constructs every output before it starts a single VU: 1. The output list is assembled from the config file, `K6_OUT` and the `-o` flags. 2. Each name is looked up. An unknown one aborts with `invalid output type '<name>', available types are: <sorted list>`. 3. Each target's own constructor runs, reading its argument and its `K6_*` variables. A bad setting at this stage — an unparseable trend stat, an unknown CSV key — aborts too. 4. Only once all of them exist does the run begin. So an output mistake costs a restart and nothing else. A run that gets past step 4 has working streams attached, and a long run never discovers an hour in that its destination was misspelled, because k6 would not have let it start.
- If `K6_OUT=csv=out.csv` is exported and the command also passes `-o json=raw.json`, what runs?Only the JSON output. k6 assembles the list from the config file, then the environment, then the CLI, and a non-empty `-o` list replaces the earlier one wholesale instead of being appended to it. To keep both, pass both on the command line: `-o csv=out.csv -o json=raw.json`.
- Why does `-o experimental-prometheus-rw=url=http://prom:9090/api/v1/write` not point k6 at that host?Because the Prometheus remote-write output never reads the text after the `=`. It builds its configuration from `K6_PROMETHEUS_RW_*` environment variables and the config file only, so the argument is silently discarded and the output falls back to its default `http://localhost:9090/api/v1/write`. Set `K6_PROMETHEUS_RW_SERVER_URL` instead.
saying these in an interview costs you the question
- Says an out key in the script's exported options selects a target
- Believes -o can only be given once per run
- Expects K6_OUT and -o to be merged into one list
- Assumes -o summary prints the end-of-test summary
- Thinks an unknown output name is warned about and then ignored
- Treats experimental-prometheus-rw as an outdated spelling of a stable name