---
title: "Test result metrics | Grafana Cloud documentation"
description: "A reference of the metric names, labels, and metric types that Performance testing uses to store test results in Grafana Cloud Metrics, and examples of how to query them with PromQL."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Test result metrics

Performance testing stores test result metrics in [Grafana Cloud Metrics](/docs/grafana-cloud/observe-and-act/send-data/metrics/), which is powered by Mimir. Test results work like any other metrics in your Grafana Cloud stack: you can query them with PromQL through your stack’s Prometheus data source, build custom dashboards with them, and correlate them with the rest of your observability data.

This page describes how test result metrics are stored, including their names, labels, and metric types, as well as how to query each type of metric.

## Before you begin

- Test result metrics are available to any user with query access to your stack’s Prometheus data source, regardless of their [project permissions](/docs/grafana-cloud/testing/k6/projects-and-users/configure-rbac/#project-permissions) in the Performance testing app. To restrict raw metric access along project boundaries, refer to [Configure LBAC](/docs/grafana-cloud/testing/k6/projects-and-users/configure-lbac/).
- Metrics are recorded at the time the test runs. When you query them, make sure the time range of your query covers the test run.

## Query test result metrics

To query test result metrics in Grafana:

1. Log in to your Grafana Cloud account.
2. Click **Explore** on the main menu.
3. Select the `grafanacloud-<yourstackname>-prom` data source.
4. Query a test result metric. For example:
   
   promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```promql
   rate(k6_http_reqs_total{k6_cloud_test_name="<TEST_NAME>"}[$__rate_interval])
   ```
   
   Replace `<TEST_NAME>` with the name of one of your tests.

You can use the same queries in dashboard panels and in [Grafana Alerting](/docs/grafana-cloud/observe-and-act/alert-and-measure-reliability/alerting/).

> Note
> 
> The `grafanacloud-<yourstackname>-prom` data source queries the raw stored series. The `k6` data source used by the Performance testing app provides pre-aggregated, test-oriented query types instead. Refer to [Query types](/docs/grafana-cloud/testing/k6/reference/query-types/) for details.

### Range and instant queries

Each example on this page is marked as either a range query or an instant query. A *range query* evaluates the expression at every step of the selected time range. An *instant query* evaluates it once at the end of the time range.

To choose between them in Explore or in a dashboard panel, set **Type** in the query options. The default, **Both**, runs the query both ways and returns combined results. Refer to [Prometheus query editor](/docs/grafana/latest/datasources/prometheus/query-editor/#type) for details, including how to display instant results in a time series panel.

For test result metrics, instant queries are especially useful: counter, rate, and trend series are scoped to a single test run and accumulate from the start of the run, so the last sample of each series holds the whole-run total or distribution. The instant examples on this page wrap the metric in `last_over_time(...[$__range])`, which returns that last sample as long as the selected time range covers the test run. The evaluation time doesn’t need to align with the end of the run.

### Query from the command line

To query test result metrics from scripts, CI pipelines, or your terminal, use the [gcx CLI](/docs/grafana-cloud/ai-tools/gcx/). Authenticate against your stack once:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
gcx login mystack --server https://<yourstackname>.grafana.net
```

For unattended use, such as CI, authenticate with a [service account token](/docs/grafana/latest/administration/service-accounts/) instead:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
gcx login --yes ci --server https://<yourstackname>.grafana.net --token <SERVICE_ACCOUNT_TOKEN>
```

Any query on this page works with `gcx metrics query`, which targets your stack’s default Prometheus data source. Run range queries with `--from`, `--to`, and `--step`:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
gcx metrics query 'sum(rate(k6_http_reqs_total{test_run_id="<TEST_RUN_ID>"}[2m]))' \
  --from <RUN_START> --to <RUN_END> --step 30s
```

Run instant queries with `--time` and a window that reaches back past the run:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
gcx metrics query 'sum(last_over_time(k6_http_reqs_total{test_run_id="<TEST_RUN_ID>"}[30d]))' \
  --time now
```

Query results are unordered. To list the runs of a test newest first, like the run list in the Performance testing app, combine a per-run query from [Across the runs of a test](#across-the-runs-of-a-test) with the `--jq` flag and an expression that sorts the results by run ID:

Bash ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```bash
gcx metrics query 'histogram_quantile(0.95, sum by (test_run_id) (last_over_time(k6_http_req_duration{k6_cloud_test_id="<TEST_ID>"}[30d])))' \
  --time now \
  --jq '[.data.result[] | {run: .metric.test_run_id, p95_ms: .value[1]}] | sort_by(.run | tonumber) | reverse'
```

Replace:

- `<TEST_RUN_ID>` with the ID of a test run
- `<TEST_ID>` with the ID of a test
- `<RUN_START>` and `<RUN_END>` with the start and end times of the test run, as RFC3339 timestamps such as `2026-08-12T11:28:00Z`
- `<SERVICE_ACCOUNT_TOKEN>` with a token you created in your stack.

> Note
> 
> The `$__rate_interval` and `$__range` variables used in the examples on this page are provided by Grafana dashboards and Explore. When you query from the command line, use fixed windows instead, such as `[2m]` for `$__rate_interval` and a window that covers the test run, such as `[30d]`, for `$__range`.

## Sample rate

k6 samples metrics at a fixed interval. This interval sets the resolution of range queries and the minimum window `rate()` and similar functions need to return accurate results; refer to [Min step](/docs/grafana/latest/datasources/prometheus/query-editor/#min-step) and [Use `$__rate_interval`](/docs/grafana/latest/datasources/prometheus/template-variables/#use-__rate_interval) for more on querying at a given sample interval.

The default sample rate is 12 seconds, or 5 data points per minute.

The sample rate is configurable per organization. To change your organization’s sample rate, [contact support](mailto:support@k6.io).

## Metric names

Test result metrics use the [k6 metric names](/docs/k6/latest/using-k6/metrics/reference/), prefixed with `k6_`:

- The built-in `http_reqs` metric is stored as `k6_http_reqs_total`.
- The built-in `http_req_duration` metric is stored as `k6_http_req_duration`.
- A custom metric named `my_counter` is stored as `k6_my_counter_total`.

Counter and rate metrics additionally carry a `_total` suffix, following the Prometheus naming convention for counters. Gauge and trend metrics don’t have a suffix.

Every series carries the original metric name, without the prefix or suffix, in the `k6_metric_name` label. Use it to find a metric when you know its k6 name:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
{k6_metric_name="http_reqs"}
```

## Labels

Test result metrics include labels that identify the metric and the project, test, and test run that produced it:

Expand table

| Label                   | Description                                                                                                                                         |
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| `k6_metric_name`        | The original k6 metric name, without the `k6_` prefix or `_total` suffix.                                                                           |
| `k6_metric_type`        | The [k6 metric type](/docs/k6/latest/using-k6/metrics/): `counter`, `gauge`, `rate`, or `trend`.                                                    |
| `k6_metric_origin`      | `builtin` for standard k6 metrics, or `script` for custom metrics defined in your test script.                                                      |
| `k6_cloud_project_id`   | The ID of the project.                                                                                                                              |
| `k6_cloud_project_name` | The name of the project.                                                                                                                            |
| `k6_cloud_test_id`      | The ID of the test.                                                                                                                                 |
| `k6_cloud_test_name`    | The name of the test.                                                                                                                               |
| `test_run_id`           | The ID of the test run.                                                                                                                             |
| `condition`             | Rate metrics only: `nonzero` or `zero`. Refer to [Rate metrics](#rate-metrics).                                                                     |
| `instance_id`           | The ID of the load generator instance that produced the sample.                                                                                     |
| `load_zone`             | The [load zone](/docs/grafana-cloud/testing/k6/author-run/cloud-scripting-extras/cloud-tags/) that ran the sample, for example `amazon:us:ashburn`. |

In addition, all tags from your test script—built-in tags such as `url`, `status`, and `scenario`, and any custom tags—are included as labels. Tests that use multiple load generator instances or load zones produce one series per instance or zone for each metric; aggregate over `instance_id` and `load_zone` unless you’re inspecting a specific one.

Prefer the ID labels over the name labels in queries you want to keep, because projects and tests can be renamed, but their IDs never change. Refer to [Project ID](/docs/grafana-cloud/testing/k6/projects-and-users/projects/#project-id) for details on how to find the ID of a project.

## Metric types

Each [k6 metric type](/docs/k6/latest/using-k6/metrics/) maps to a Prometheus metric type:

Expand table

| k6 type | Stored as                                                                                          |
|---------|----------------------------------------------------------------------------------------------------|
| Counter | A counter, named `k6_<name>_total`                                                                 |
| Gauge   | A gauge                                                                                            |
| Rate    | Two counter series, `k6_<name>_total{condition="nonzero"}` and `k6_<name>_total{condition="zero"}` |
| Trend   | A [native histogram](/docs/mimir/latest/visualize/native-histograms/)                              |

### Counter metrics

Counter metrics are standard Prometheus counters that accumulate over the course of a test run. To graph requests per second during a test run, use `rate()` in a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum(rate(k6_http_reqs_total{test_run_id="<TEST_RUN_ID>"}[$__rate_interval]))
```

To get the total number of requests for a whole test run, read the counter’s final value with an instant query over a time range that includes the run:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum(last_over_time(k6_http_reqs_total{test_run_id="<TEST_RUN_ID>"}[$__range]))
```

In this and the following examples, replace `<TEST_RUN_ID>` with the ID of a test run, and `<TEST_ID>` with the ID of a test.

### Gauge metrics

Gauge metrics are standard Prometheus gauges. To graph the number of active virtual users during a test run across all load generator instances, use a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum(k6_vus{test_run_id="<TEST_RUN_ID>"})
```

### Rate metrics

A k6 rate metric tracks the proportion of nonzero observations, such as the proportion of passed [checks](/docs/k6/latest/using-k6/checks/). It’s stored as two counter series distinguished by the `condition` label: `condition="nonzero"` counts the nonzero observations, and `condition="zero"` counts the rest.

For example, a `checks` metric with six passed and two failed observations is stored as:

text ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```text
k6_checks_total{check="my_check", condition="nonzero"}  6
k6_checks_total{check="my_check", condition="zero"}     2
```

To get the total number of observations for a whole test run, sum over both conditions by querying without the `condition` label, using an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum by (check) (last_over_time(k6_checks_total{test_run_id="<TEST_RUN_ID>"}[$__range]))
```

To get the rate value as k6 reports it—a ratio from 0.0 to 1.0—divide the nonzero count by the total. As an instant query, this returns the whole-run ratio:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum by (check) (last_over_time(k6_checks_total{test_run_id="<TEST_RUN_ID>", condition="nonzero"}[$__range]))
/
sum by (check) (last_over_time(k6_checks_total{test_run_id="<TEST_RUN_ID>"}[$__range]))
```

To graph how the ratio evolves during the run instead, apply `rate()` to both sides in a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum by (check) (rate(k6_checks_total{test_run_id="<TEST_RUN_ID>", condition="nonzero"}[$__rate_interval]))
/
sum by (check) (rate(k6_checks_total{test_run_id="<TEST_RUN_ID>"}[$__rate_interval]))
```

### Trend metrics

Trend metrics, such as `http_req_duration`, are stored as [native histograms](/docs/mimir/latest/visualize/native-histograms/): a single series that holds the full value distribution, rather than the separate `_bucket`, `_sum`, and `_count` series of classic histograms.

Use the histogram functions to query them. To graph the 95th percentile of the HTTP request duration as it evolves during a test run, use a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_quantile(0.95, sum(rate(k6_http_req_duration{test_run_id="<TEST_RUN_ID>"}[$__rate_interval])))
```

Because the stored histogram accumulates over the run, its last sample holds the distribution of the whole run. To get the 95th percentile for a whole test run, as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_quantile(0.95, sum(last_over_time(k6_http_req_duration{test_run_id="<TEST_RUN_ID>"}[$__range])))
```

To get the whole-run average, divide the sum of observed values by the observation count, also as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_sum(sum(last_over_time(k6_http_req_duration{test_run_id="<TEST_RUN_ID>"}[$__range])))
/
histogram_count(sum(last_over_time(k6_http_req_duration{test_run_id="<TEST_RUN_ID>"}[$__range])))
```

## Example queries

### One test run

The 95th percentile of request duration, split by URL, over the course of one test run, as a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_quantile(0.95, sum by (url) (rate(k6_http_req_duration{test_run_id="<TEST_RUN_ID>"}[$__rate_interval])))
```

The failed request rate over time during one test run, as a range query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum(rate(k6_http_req_failed_total{test_run_id="<TEST_RUN_ID>", condition="nonzero"}[$__rate_interval]))
/
sum(rate(k6_http_req_failed_total{test_run_id="<TEST_RUN_ID>"}[$__rate_interval]))
```

All metrics produced by a specific test run, as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
group by (__name__, k6_metric_name, k6_metric_type) (last_over_time({test_run_id="<TEST_RUN_ID>"}[$__range]))
```

### Across the runs of a test

To compare runs of the same test, filter by `k6_cloud_test_id` and aggregate `by (test_run_id)`, over a time range that covers all the runs you want to compare. Instant queries then return one whole-run summary value per run, the same shape as the performance-trending chart in [Compare tests](/docs/grafana-cloud/observe-and-act/testing/k6/analyze-results/test-comparison/#explore-test-trends), and work well in table and bar chart panels.

The 95th percentile of request duration for each run, as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_quantile(0.95, sum by (test_run_id) (last_over_time(k6_http_req_duration{k6_cloud_test_id="<TEST_ID>"}[$__range])))
```

The total number of requests in each run, as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum by (test_run_id) (last_over_time(k6_http_reqs_total{k6_cloud_test_id="<TEST_ID>"}[$__range]))
```

The failed request ratio of each run, as an instant query:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
sum by (test_run_id) (last_over_time(k6_http_req_failed_total{k6_cloud_test_id="<TEST_ID>", condition="nonzero"}[$__range]))
/
sum by (test_run_id) (last_over_time(k6_http_req_failed_total{k6_cloud_test_id="<TEST_ID>"}[$__range]))
```

The peak requests per second reached in each run, as an instant query. The inner expression is evaluated as a PromQL subquery at every step of the time range, so keep the time range close to the runs you’re comparing:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
max_over_time(sum by (test_run_id) (rate(k6_http_reqs_total{k6_cloud_test_id="<TEST_ID>"}[2m]))[$__range:])
```

The 95th percentile of request duration over time, split by run, as a range query—over a time range that spans multiple runs, this graphs each run’s behavior side by side:

promql ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```promql
histogram_quantile(0.95, sum by (test_run_id) (rate(k6_http_req_duration{k6_cloud_test_id="<TEST_ID>"}[$__rate_interval])))
```
