Measurements and Metrics
Step analytics are built on two complementary data types:
Measurements
A measurement is a named, timed observation attached to a plan’s execution step. Each measurement captures a name, a duration in milliseconds, a start timestamp, a status (PASSED, FAILED, or TECHNICAL_ERROR), and optional custom attributes (key/value pairs).
Measurements are created automatically by the Step framework for keyword calls as well as for instrumented plan nodes. Custom measurements with finer granularity or enriched attributes can also be defined in keyword code (see Measurements in the Keyword API). Measurements are the foundation of the response time and throughput charts in analytics dashboards.
Metrics
Metrics are named instruments that aggregate numerical observations over time. Unlike measurements, metrics are not tied to a single observation — they accumulate values across many events and are summarized into snapshots over time intervals. Three instrument types are available:
| Type | Description | Typical use |
|---|---|---|
| Counter | Monotonically increasing total | Records processed, error count |
| Gauge | A value that rises and falls | Queue depth, active connections |
| Histogram | Distribution of observed values | Response time spread, payload sizes |
Sources of metrics
Metrics in Step come from multiple sources — the majority are produced automatically by the platform:
Automatic — plan node level
| Metric name | Description | Default aggregation |
|---|---|---|
response-time |
Duration in ms of keywords calls and instrumented plan nodes | Average |
threadgroup |
Number of concurrently active threads in a thread group | Maximum |
Automatic — execution-level
Scope: Generated at the end of each execution
| Metric name | Description | Default aggregation |
|---|---|---|
executions/count |
Number of plan executions that ended in the selected period | Sum |
executions/duration |
Wall-clock duration of each execution (ms) | Average |
executions/failure-percentage |
Failure rate — each execution contributes 0 (pass) or 100 (fail); average gives the overall rate | Average |
executions/failure-count |
Number of failed executions | Sum |
executions/failures-count-by-error-code |
Failed execution count broken down by error code | Sum |
Automatic — grid/controller
Scope: Platform-level, not bound to a single execution; visible in the Grid Monitoring dashboard from any tenant
Keyword-emitted
Scope: Explicitly defined in keyword code, emitted at completion or in real time
| Metric name | Description | Default aggregation |
|---|---|---|
response-time |
Duration in ms of keyword’s custom measurements | Average |
counter |
Custom cumulative totals | Sum |
gauge |
Custom instantaneous values | Average |
histogram |
Custom value distributions | Average |
For details on emitting custom metrics from keyword code, see the Keyword API.
Labels
Custom keyword metrics (Counter, Gauge, Histogram) accept an optional labels map — a flat set of string key/value pairs defined at metric creation time. Labels are stored on every snapshot the metric produces and flow through Step’s internal analytics pipeline, where they can be used to filter and group metrics in dashboards — for example, charting response_time_ms broken down by endpoint or environment.
Labels are set once at creation and are immutable: all observations on a metric carry the same label set.
For the API usage, see the Labels section of the Keyword API.
Understanding metric fields
Each metric snapshot exposes the following fields. The interpretation of min, max, and Rate differs by instrument type:
Gauge and Histogram — straightforward: observations are the values passed to observe().
| Field | Meaning |
|---|---|
| count | Number of observations in the interval |
| sum | Sum of all observed values |
| avg | Average observed value (sum / count) |
| min | Smallest observed value in the interval |
| max | Largest observed value in the interval |
| last | Most recently observed value |
| Rate | Observations per time unit (count / duration) |
Counter — tracks a running total, so min/max have a different meaning:
| Field | Meaning |
|---|---|
| count | Number of increment() calls in the interval |
| sum | Total amount added by those increments in the interval |
| avg | Average increment per call (sum / count) |
| min | Running total at the start of the interval (before this interval’s increments) |
| max | Running total at the end of the interval (= last) |
| last | Current all-time running total |
| Rate | Increment per time unit (sum / duration) — not call count per time unit |
The counter’s Rate therefore answers “how much was added per second”, not “how many times was increment called per second”. This distinction matters when choosing the right aggregation for throughput-style counter dashlets.
Label cardinality safeguard
Custom metrics and measurements can carry user-defined labels. If a label takes on a very large number of distinct values during an execution — for example a UUID, a timestamp, or a per-request identifier — it can explode the number of time series stored and degrade analytics performance.
To prevent this, Step applies two complementary quotas to the user-defined labels of each metric and measurement. Built-in and platform labels are never affected.
The first quota limits the number of unique values a single label may take, scoped per execution, per metric/measurement name, and per label name (20 values by default). Once a label exceeds this quota, any further new value is replaced with the placeholder values dismissed due to quota exceeded before it is ingested into the time series. Values seen before the quota was reached continue to be recorded normally.
The second quota limits the number of distinct labels a single metric or measurement may carry, scoped per execution and per metric/measurement name (20 labels by default). Once this quota is reached, any further new label is dropped before ingestion. This guards against keywords that attach an unbounded set of label names rather than an unbounded set of values.
Both quotas apply to custom metrics and custom measurements ingested into the time series during an execution.
Resolving high cardinality
When this warning appears, choose one of the following, in order of preference:
- Reduce the label’s cardinality (recommended). Fix the keyword so the offending label takes a bounded set of values, or remove the label altogether if it is not needed for filtering or grouping. Labels carrying UUIDs, timestamps, or per-request identifiers are rarely useful in analytics and are the usual cause.
- Exclude the label from time-series ingestion. If the high-cardinality attribute must stay on the raw data but is not needed in the analytics charts, exclude it from the ingested attributes (see Configuring ingested attributes).
- Raise the relevant quota (discouraged). Increasing a quota is possible but strongly discouraged: a high quota reintroduces the cardinality explosion the safeguard is meant to prevent and degrades analytics performance.
Configuration
You can adjust or disable either quota in step.properties:
| Property | Default | Description |
|---|---|---|
timeseries.attributes.max-unique-label-values |
20 |
Maximum number of unique values tolerated per execution, metric/measurement name and label. Set to 0 to replace all values of every custom label with the placeholder; set to a negative value to disable the quota. |
timeseries.attributes.max-labels-per-metric |
20 |
Maximum number of distinct labels tolerated per execution and metric/measurement name. Set to 0 to drop all custom labels; set to a negative value to disable the quota. |