myrtille

module
v0.0.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2026 License: MIT

README

myrtille

myrtille

myrtille orchestrates k6 load tests in three phases:

  1. init — brings the tested service into a known state (creating data via declarative HTTP calls) and builds a state dictionary.
  2. run — launches the k6 scenario, passing it this state dictionary. With the custom k6 binary described in Live dashboard, k6's own live web dashboard is served for the duration of the run, and — if service.metrics.url is configured — the service's own /metrics endpoint (Prometheus format) is mirrored into it too, alongside k6's own metrics, updating in real time.
  3. report — writes a Markdown and/or JSON summary once the run finishes: the init/teardown step tables, and the k6 results (thresholds, percentiles, per-check pass/fail counts, etc.).

A single generic CLI binary (myrtille), driven by a per-project YAML config file — no Go code to write on the consuming project's side.

Requirements

  • Go 1.27+
  • The k6 binary must be on the PATH — unless you're using a release tarball (see "Installation"), which already bundles the custom k6 binary the live dashboard needs (see Live dashboard).

Installation

go install github.com/thecoons/myrtille/cmd/myrtille@latest

Or locally:

go build -o bin/myrtille ./cmd/myrtille

Or download a prebuilt Linux binary (amd64/arm64) from the releases page — the tarball bundles myrtille alongside the custom k6 binary the live dashboard needs, so extracting it is enough:

tar -xzf myrtille-vX.Y.Z-linux-amd64.tar.gz
cd myrtille-vX.Y.Z-linux-amd64
./myrtille run --config myrtille.yaml   # live dashboard works immediately, no setup

To install system-wide, move both binaries together — myrtille looks for a k6 sitting right next to itself (see Live dashboard) — or just myrtille alone if you don't want the live dashboard, or already manage k6 separately:

sudo mv myrtille-vX.Y.Z-linux-amd64/{myrtille,k6} /usr/local/bin/

Usage

myrtille run --config myrtille.yaml
myrtille init --config myrtille.yaml   # runs only the init phase, for debugging
myrtille teardown --config myrtille.yaml --state-file /tmp/myrtille-state-XXXX.json

The exit code of myrtille run mirrors k6's (0 = success, 99 = failed thresholds, other = script error). The report is always written, even if the init phase or the thresholds fail.

myrtille run always attempts teardown.steps (see the config reference) before returning, even if init or k6 failed partway — so if teardown.steps is configured, it prints the state file's path to stderr first: state file: /tmp/myrtille-state-XXXX.json. That path is only useful for recovery — if the process is killed hard enough (kill -9) to skip its own cleanup, rerun it standalone with myrtille teardown --state-file <that path>.

k6's own ASCII banner and per-second progress lines are suppressed by default (--quiet) — they add up fast in --suite, where they'd otherwise repeat once per scenario. The final summary (checks, custom metrics, thresholds) still prints in full; only the noise in between is gone. This only applies without the live dashboard: k6 gates the one line that prints the dashboard's URL behind the same flag, so myrtille skips --quiet whenever the dashboard is active. Add k6.args: ["--quiet=false"] to a scenario's config to opt back into the verbose output.

Documentation

  • Config reference — every myrtille.yaml field: init/teardown steps, derived state, declarative k6 scenarios, k6.setup, custom k6.script, .env/vars.
  • Live dashboard — k6's live web dashboard, mirroring the service's own Prometheus metrics and OpenTelemetry spans into it, exporting it to report.html.
  • Advanced usage — myrtille managing the service's own start/stop, running a suite of scenarios, loading a preloaded state file.

Full example

See examples/demo-service: a minimal HTTP service (stubservice) and a myrtille.yaml config exercising it end-to-end (init steps + declarative k6.steps, no hand-written script), forming a complete smoke test. The demo config also sets service.metrics.url and report.formats: [..., "dashboard-html"], so it doubles as a live and exported-dashboard demo — and service.managed, so myrtille run starts/stops stubservice itself (see Advanced usage); only building it is left to you.

go build -o /tmp/stubservice ./examples/demo-service/stubservice

go build -o bin/myrtille ./cmd/myrtille

go install go.k6.io/xk6/cmd/xk6@latest
export PATH="$PATH:$(go env GOPATH)/bin"
./scripts/build-k6.sh   # builds bin/k6, right next to bin/myrtille — auto-detected, no config needed

bin/myrtille run --config examples/demo-service/myrtille.yaml

Watch for web dashboard: http://127.0.0.1:XXXXX in the output and open it while the run is in progress (10s by default) — k6's own metrics show up immediately, and the "Service" tab's counters (fed from stubservice's own /metrics) appear a couple of seconds in, once there's a second scrape to compute a delta from.

The report is written to examples/demo-service/reports/<timestamp>/: report.md, report.json, and — thanks to "dashboard-html" — report.html, the same dashboard frozen at the end of the run, open it straight from disk once the run is done, no server needed.

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
myrtille command
Command myrtille orchestrates a load-test run against a service: bring it into a known state (init), run a k6 scenario against it while scraping its /metrics endpoint, and write a report of what happened.
Command myrtille orchestrates a load-test run against a service: bring it into a known state (init), run a k6 scenario against it while scraping its /metrics endpoint, and write a report of what happened.
examples
demo-service/stubservice command
Command stubservice is a tiny fixture service used by the myrtille demo: it exposes /healthz (for service.managed.readiness), /users (create, delete), /products (list), /orders (write endpoint scenarios hit under load), and /metrics (Prometheus format — a counter, a gauge, and a histogram, all three real metric types service.metrics.url scrapes), so examples/demo-service/myrtille.yaml has something real to talk to.
Command stubservice is a tiny fixture service used by the myrtille demo: it exposes /healthz (for service.managed.readiness), /users (create, delete), /products (list), /orders (write endpoint scenarios hit under load), and /metrics (Prometheus format — a counter, a gauge, and a histogram, all three real metric types service.metrics.url scrapes), so examples/demo-service/myrtille.yaml has something real to talk to.
internal
config
Package config parses and validates the myrtille.yaml file that describes a single load-test project: the service under test, the declarative init steps, the k6 script to run, and where to write the report.
Package config parses and validates the myrtille.yaml file that describes a single load-test project: the service under test, the declarative init steps, the k6 script to run, and where to write the report.
dashboardconfig
Package dashboardconfig builds the JSON config k6's web-dashboard reads from XK6_DASHBOARD_CONFIG (see https://github.com/grafana/k6/tree/master/internal/dashboard's customize.go): the bundled default config — the same one k6 falls back to on its own, fetched at runtime from xk6-dashboard-assets rather than vendored, so it can't drift out of sync with whatever version is actually bundled — plus one extra "Service" tab with a chart panel per metric scraped from the service's own /metrics endpoint, and (when service.traces.enabled) an aggregate panel each for the OTel spans it receives — see docs/plans/otel-span-metrics.md.
Package dashboardconfig builds the JSON config k6's web-dashboard reads from XK6_DASHBOARD_CONFIG (see https://github.com/grafana/k6/tree/master/internal/dashboard's customize.go): the bundled default config — the same one k6 falls back to on its own, fetched at runtime from xk6-dashboard-assets rather than vendored, so it can't drift out of sync with whatever version is actually bundled — plus one extra "Service" tab with a chart panel per metric scraped from the service's own /metrics endpoint, and (when service.traces.enabled) an aggregate panel each for the OTel spans it receives — see docs/plans/otel-span-metrics.md.
initphase
Package initphase executes the declarative HTTP steps configured under `init.steps` to bring the target service into a known state, extracting values (IDs, etc.) from responses into a state.Dict that k6 scenarios can later randomize over.
Package initphase executes the declarative HTTP steps configured under `init.steps` to bring the target service into a known state, extracting values (IDs, etc.) from responses into a state.Dict that k6 scenarios can later randomize over.
k6gen
Package k6gen renders the declarative HTTP steps configured under `k6.steps` into a k6-compatible JS scenario file, for projects that don't need a hand-written scenario.js.
Package k6gen renders the declarative HTTP steps configured under `k6.steps` into a k6-compatible JS scenario file, for projects that don't need a hand-written scenario.js.
k6run
Package k6run shells out to the k6 binary to execute a load test scenario, passing it the generated state dictionary via an environment variable, and parses the resulting --summary-export JSON so the report phase can show pass/fail thresholds and key metrics.
Package k6run shells out to the k6 binary to execute a load test scenario, passing it the generated state dictionary via an environment variable, and parses the resulting --summary-export JSON so the report phase can show pass/fail thresholds and key metrics.
metrics
Package metrics decodes a Prometheus text-exposition payload into samples.
Package metrics decodes a Prometheus text-exposition payload into samples.
orchestrator
Package orchestrator wires the init, k6 run, and report phases together into the single pipeline the CLI drives.
Package orchestrator wires the init, k6 run, and report phases together into the single pipeline the CLI drives.
report
Package report aggregates the results of the init, k6 run, and metrics scraping phases into a single Report, rendered to Markdown and/or JSON files for a human (or an issue/ticket comment) to read.
Package report aggregates the results of the init, k6 run, and metrics scraping phases into a single Report, rendered to Markdown and/or JSON files for a human (or an issue/ticket comment) to read.
servicelifecycle
Package servicelifecycle starts and stops the service under test itself (service.managed.start_command), for projects that want a fresh instance per `myrtille run` rather than assuming one is already up.
Package servicelifecycle starts and stops the service under test itself (service.managed.start_command), for projects that want a fresh instance per `myrtille run` rather than assuming one is already up.
state
Package state holds the dictionary of values gathered during the init phase (e.g.
Package state holds the dictionary of values gathered during the init phase (e.g.
style
Package style adds lightweight, optional visual formatting — a symbol prefix and, when the output looks like an interactive terminal, ANSI color — to myrtille's own progress messages (service start/stop, init phase transitions, k6 run).
Package style adds lightweight, optional visual formatting — a symbol prefix and, when the output looks like an interactive terminal, ANSI color — to myrtille's own progress messages (service start/stop, init phase transitions, k6 run).
suite
Package suite parses `suite.yaml` — an ordered list of scenario config paths that `myrtille run --suite` runs one after another, each as its own separate `myrtille run` subprocess (not an in-process loop — see docs/plans/suite-mode.md for why: config.Load mutates the process environment via os.Setenv, which would silently leak between scenarios if they shared one process).
Package suite parses `suite.yaml` — an ordered list of scenario config paths that `myrtille run --suite` runs one after another, each as its own separate `myrtille run` subprocess (not an in-process loop — see docs/plans/suite-mode.md for why: config.Load mutates the process environment via os.Setenv, which would silently leak between scenarios if they shared one process).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL