skip to content

Continuous Streams

Pushing samples out of the process while the run is still going rather than waiting for the closing block. Interviewers ask what you can watch mid-run and what that costs.

on this pageshow

explore

questions

4

In k6, how do you choose where a run streams its metrics, and which `--out` targets does v2 accept?

level: middleimportance: must knowfreq 58%

answer

  1. one flag, and you may repeat it
  2. an environment variable holds the same list
  3. target name, then an optional =argument
  4. eight accepted names in k6 v2
  5. 'summary' is in the enum, not the map

basics

~20 s

k6 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
bash
# 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.js

go deeper

for a junior

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.

for a middle

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.

for a senior

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.

for a principal

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
open as a page

What does k6's `--out json=` write to its file, and how does `--out csv=` differ?

level: juniorimportance: should knowfreq 50%

basics

~20 s

k6's json target writes newline-delimited objects: a Metric declaration, then a Point per sample with time, value and tags. The csv target writes a fixed header of metric_name, timestamp and metric_value, then tag columns. Both gzip on a .gz path.

open as a page

What happens when a k6 v2 run is started with `-o kafka`, `-o statsd` or `-o datadog`?

level: middleimportance: should knowfreq 42%

basics

~20 s

All three names still resolve in k6 v2, but their constructors do nothing except return a migration error naming an xk6 output extension, so the run aborts before any virtual user starts. kafka and datadog were removed in v0.34.0, statsd in v0.55.0.

open as a page

In k6, why does a Trend metric reach Prometheus as one `p99` series, and how do you change that?

level: seniorimportance: nice to knowfreq 33%

basics

~10 s

k6's experimental-prometheus-rw output reduces each Trend to the stats named by K6_PROMETHEUS_RW_TREND_STATS, which defaults to p(99) alone. Set it to a comma-separated list such as p(95),p(99),max and each token becomes its own k6_<metric>_<stat> series.

open as a page