Skip to main content
Testkube 2.11.0 is out! Improved insights and metrics, more responsive AI chat, Gateway API support, and much more! Read More

Performance Metrics

Testkube automatically collects performance metrics from major performance testing tools; k6, Artillery, and JMeter are currently supported; the sections below describe how to export reports and collect them as workflow artifacts for each tool. Ready-to-run workflows are in the Basic K6, Basic Artillery, and Basic JMeter examples.

For other tools, or when you need metrics that do not map to a built-in report format, use Influx Line Protocol instead.

The metrics exported by each tool will differ, but you can chart the values you care about and see how they change over time. For example, charting http_req_duration_p95_ms segmented by Scenario helps you compare p95 latency across load profiles and spot regressions in a single scenario.

k6 Summary Integration

k6 can export a machine-readable summary with the --summary-export flag. To make that summary available as granular metrics in Testkube:

  1. Export the summary JSON into an artifact directory.
  2. Include the JSON file in the workflow artifacts.
  3. Run the workflow normally.

Testkube detects k6 summary JSON files during artifact post-processing and registers them as k6.summary reports. The control plane then ingests the report into granular metric series.

For a complete workflow that exports summary.json and uploads it as an artifact, see the Basic K6 Example.

After the workflow finishes, the summary file remains available as a normal artifact, and Testkube stores the detected k6 metrics as granular series.

k6 Metric Names

Testkube normalizes k6 metric names and summary statistics so they are stable in Insights and API responses. Common examples include:

k6 summary fieldTestkube metric key
http_req_duration.values["p(95)"]http_req_duration_p95_ms
http_req_duration.values.avghttp_req_duration_avg_ms
http_reqs.values.counthttp_reqs_count
http_reqs.values.ratehttp_reqs_rate
checks.values.passeschecks_passes
checks.values.failschecks_fails
iteration_duration.values.avgiteration_duration_avg_ms

Timing metrics are stored in milliseconds. Counter and rate metrics keep their k6 summary values.

Tagged k6 Metrics

k6 can emit tagged metric summaries, for example separate http_req_duration values for successful responses or custom tags. Testkube preserves stable tag dimensions as series identity fields. This lets you compare the same metric overall and for a tagged subset when the k6 summary contains those tagged metrics.

For example, a tagged k6 summary metric can produce separate series for:

  • http_req_duration_p95_ms with no identity fields.
  • http_req_duration_p95_ms with an identity such as expected_response=true.
  • http_req_duration_p95_ms with scenario=homepage or scenario=docs, when the script defines named scenarios and asks k6 to include those scenario-tagged submetrics in the summary.
  • http_req_duration_p95_ms with endpoint=test-workflow-with-executions-list, when the script tags requests by endpoint and asks k6 to include those endpoint-tagged submetrics in the summary.

k6 does not include every possible tag combination in summary.json automatically. If you need scenario-level or endpoint-level series in Insights, define the tag values and add thresholds for the metric/tag combinations you want to chart—for example, http_req_duration{scenario:homepage} or http_reqs{endpoint:my-operation}.

For endpoint-level metrics, tag each request (for example with tags: { endpoint: "my-operation" }) and add a matching threshold. The tag key can be any stable name, but endpoint is useful for API and UI performance tests because it lets Insights split latency by logical operation instead of by raw URL.

Testkube stores tagged summaries as metric keys such as http_req_duration_p95_ms with identity endpoint=test-workflow-with-executions-list, so the same measure can be segmented or filtered by Endpoint in Insights.

Use tags intentionally. High-cardinality tags, such as unique URLs or request IDs, can create many metric series and make analysis harder.

Distributed k6 Workflows

For distributed k6 workflows, each worker should write a unique summary filename and upload it as an artifact. This avoids workers overwriting each other's summary file. See the Distributed K6 Example for a workflow that exports per-worker summary-worker-*.json files alongside the HTML dashboard.

Each uploaded k6 summary report is ingested into granular metric series for the workflow execution.

k6 Troubleshooting

If k6 metrics do not appear in Insights:

  • Confirm that the k6 command includes --summary-export.
  • Confirm that the exported JSON file is included in artifacts.paths.
  • Use a .json file extension for the summary export.
  • Keep the summary file non-empty and in k6 summary JSON format.
  • Check the workflow execution artifacts to confirm the summary file was uploaded.

The summary file can be uploaded alongside other artifacts, such as the k6 HTML dashboard report.

Artillery Report Integration

Artillery can export a machine-readable JSON report with the -o flag. To make that report available as granular metrics in Testkube:

  1. Export the Artillery report JSON into an artifact directory.
  2. Include the JSON file in the workflow artifacts.
  3. Run the workflow normally.

Testkube detects Artillery JSON files with numeric aggregate metrics under counters, rates, summaries, or histograms during artifact post-processing and registers them with the artillery.report report type. The control plane then ingests the report into granular metric series.

For a complete workflow that writes an Artillery JSON report with -o and uploads it as an artifact, see the Basic Artillery Example.

After the workflow finishes, the report file remains available as a normal artifact, and Testkube stores the detected Artillery aggregate metrics as granular series.

Artillery Metric Names

Testkube normalizes Artillery aggregate metric names and statistics into stable metric keys. Common examples include:

Artillery report fieldTestkube metric key
aggregate.counters["http.requests"]http_requests
aggregate.counters["vusers.created"]vusers_created
aggregate.rates["http.request_rate"]http_request_rate
aggregate.summaries["http.response_time"].minhttp_response_time_min_ms
aggregate.summaries["http.response_time"].p95http_response_time_p95_ms
aggregate.histograms["http.response_time"].p99http_response_time_p99_ms
aggregate.histograms["vusers.session_length"].p99vusers_session_length_p99
aggregate.scenariosCreatedscenarios_created
aggregate.requestsCompletedrequests_completed
aggregate.codes["200"]codes_200
aggregate.errors.ETIMEDOUTerrors_etimedout
aggregate.latency.p95latency_p95_ms
aggregate.rps.meanrps_mean
aggregate.scenarioDuration.p95scenario_duration_p95_ms
aggregate.counters["vusers.created_by_name.homepage"]vusers_created with scenario=homepage
aggregate.scenarioCounts.homepagescenario_counts with scenario=homepage
aggregate.summaries["plugins.metrics-by-endpoint.response_time.//"].p95http_response_time_p95_ms with transaction=/
aggregate.counters["plugins.metrics-by-endpoint.//.codes.200"]http_codes_200 with transaction=/

Latency, response-time, and duration metrics are stored in milliseconds when they include a statistic, such as min, max, median, p95, or p99. Counter and rate metrics keep their Artillery report values. The control plane also understands common Artillery aggregate fields such as latency, rps, and scenarioDuration when those fields are present in a report.

Artillery Segmentation

Artillery metrics can use Scenario and Transaction as identity fields when the uploaded report includes those dimensions. This lets Insights split or filter Artillery report metrics by the logical scenario or endpoint that produced the measurement.

Scenario identities are created from named Artillery scenarios. For example, a scenario named homepage can appear in the JSON report as vusers.created_by_name.homepage, and Testkube stores the name as scenario=homepage.

Transaction identities are created from endpoint-level Artillery metrics, such as plugins.metrics-by-endpoint.response_time.// and plugins.metrics-by-endpoint.//.codes.200. Testkube stores the endpoint as the transaction identity, so the root endpoint // is shown as transaction=/.

Scenario and transaction identities are optional per metric. Artillery aggregate metrics that do not carry scenario or transaction context are still stored as workflow-level series. For example, global http.response_time values are available as overall latency metrics, while plugins.metrics-by-endpoint.response_time.<endpoint> values can be segmented by Transaction. If a Scenario or Transaction filter returns no series for a selected Artillery metric, check whether the uploaded report contains that identity for the metric key you are charting.

Distributed Artillery Workflows

For distributed Artillery workflows, each worker should write a unique JSON report filename and upload those files as artifacts. Testkube detects each uploaded Artillery report independently.

Artillery Troubleshooting

If Artillery metrics do not appear in Insights:

  • Confirm that the Artillery command includes -o <report-file>.
  • Confirm that the exported JSON file is included in artifacts.paths.
  • Use a .json file extension for the report.
  • Keep the report non-empty and in Artillery aggregate JSON format, with numeric aggregate metrics under counters, rates, summaries, or histograms.
  • Check the workflow execution artifacts to confirm the report file was uploaded.

JMeter Statistics Integration

JMeter can generate a dashboard report with the -e and -o flags. That dashboard includes a machine-readable statistics.json file. To make JMeter statistics available as granular metrics in Testkube:

  1. Run JMeter with -e -o <report-directory>.
  2. Put the report directory under an artifact directory.
  3. Include the report directory in the workflow artifacts.

Testkube detects JMeter dashboard statistics.json files during artifact post-processing and registers them as jmeter.statistics reports. The control plane then ingests the report into granular metric series.

For a complete workflow that runs JMeter with -e -o and uploads the dashboard directory (including statistics.json) as artifacts, see the Basic JMeter Example.

After the workflow finishes, the dashboard files remain available as normal artifacts, and Testkube stores the detected JMeter statistics as granular series. The detected report file is typically report/statistics.json or artifacts/report/statistics.json, depending on the artifact working directory.

JMeter Metric Names

Testkube normalizes JMeter dashboard statistics into stable metric keys. Common examples include:

JMeter statistics fieldTestkube metric key
sampleCountsample_count
errorCounterror_count
errorPcterror_pct
meanResTimeresponse_time_mean_ms
medianResTimeresponse_time_median_ms
minResTimeresponse_time_min_ms
maxResTimeresponse_time_max_ms
pct1ResTimeresponse_time_p90_ms
pct2ResTimeresponse_time_p95_ms
pct3ResTimeresponse_time_p99_ms
throughputthroughput
receivedKBytesPerSecreceived_kbytes_per_sec
sentKBytesPerSecsent_kbytes_per_sec

Response-time metrics are stored in milliseconds. JMeter transaction labels, including Total, are stored as series identity fields so each transaction can be compared across workflow executions.

JMeter Troubleshooting

If JMeter metrics do not appear in Insights:

  • Confirm that the JMeter command includes -e -o <report-directory>.
  • Confirm that the generated dashboard contains statistics.json.
  • Confirm that the report directory is included in artifacts.paths.
  • Keep the statistics.json file non-empty and in JMeter dashboard statistics format.
  • Check the workflow execution artifacts to confirm the report directory was uploaded.