Skip to content
RouteSpear
Documentation
Documentation menu

Script metric output reference

Metric kinds, wire fields, units, labels, distributions and output budgets.

Every SDK writes the same newline-delimited JSON protocol to stdout. One line is one metric. Use language-specific helpers for ordinary emissions; the raw protocol is useful for custom emitters or pre-aggregated distributions.

Metric kinds

Kind Meaning SDK unit Interpretation
gauge Point-in-time reading Caller-supplied, default empty Averaged by the standard display; examples: queue depth, temperature, free bytes.
counter Events counted, or an external running total Default count, overridable Delta values describe this run. Cumulative values describe a running total; use increase/rate when querying them.
duration Elapsed time ms Supply milliseconds. Standard displays can show averages and percentiles.
ratio Fraction ratio Use 0.93 for 93%, not 93.
bool Observed yes/no bool Numeric 1 or 0; averaging gives the fraction true.
distribution Bucketed observations and summary Caller-supplied, default empty Mean/count and explicit bucket evidence; do not pass an array as a scalar value.

These semantics are part of the emission contract. A parser accepting a finite number does not prove it is meaningful: keep ratios in [0,1], booleans in {0,1}, and distinguish unobserved data from a measured zero. Do not emit success or latency when the operation never ran.

Scalar wire object

{"name":"queue_depth","kind":"gauge","unit":"count","value":12,"labels":{"queue":"orders"}}
Field Type Requirements
name String [a-z][a-z0-9_]*, 1–96 characters. rs_ is reserved. Avoid the platform’s script_* diagnostic metric names.
kind String One of the six kinds above.
unit String Up to 32 characters from letters, digits, _, /, %, .; empty is allowed. SDK duration/ratio/bool helpers set their fixed units.
value Number Required for scalar kinds, including a genuine zero. Must be finite. No null, NaN, infinity or numeric strings.
labels Object of strings Optional, at most 8 entries. Keys beginning rs. are reserved. Use stable, bounded values.
temporality String Counters only: delta or cumulative. Omitted/empty counters default to delta; do not attach it to another kind.

The typed helpers convert labels to strings in Python, JavaScript and PowerShell. The raw emitter does not normalize an arbitrary object; give it the correct wire types yourself. Shell callers must supply valid JSON and quote arguments.

Label keys begin with a lowercase letter, contain only lowercase letters, digits, _, ., or -, and are at most 64 bytes. Values are valid UTF-8, at most 256 bytes, with no control characters or leading/trailing whitespace. Avoid timestamps, request IDs, credentials and unbounded response text in labels.

Delta and cumulative counters

A fresh process runs for each invocation. A local counter initialized to zero in that process is normally a delta: emit how many events that run observed. Mark a value cumulative only when it comes from a persistent running total, such as bytes-since-boot on a monitored service. Repeatedly marking an unrelated per-run count cumulative produces misleading increases.

{"name":"requests","kind":"counter","unit":"count","value":340,"temporality":"delta"}
{"name":"bytes_total","kind":"counter","unit":"bytes","value":9812331,"temporality":"cumulative"}

Use the query counter reference for the supported increase/rate behavior. Keep names, label sets and units stable when comparing samples. Do not add invocation IDs as labels merely to distinguish runs.

Distribution wire object

{"name":"payload_bytes","kind":"distribution","unit":"bytes","bounds":[10,50,100],"counts":[1,1,1,0],"count":3,"sum":130,"min":10,"max":90}

This example represents values 10, 30, 90. Bounds are inclusive upper limits. The buckets are ≤10, (10,50], (50,100], and >100.

Field Type Meaning
bounds Array of finite numbers Strictly ascending, at most 512 entries.
counts Array of unsigned integers Exactly one more entry than bounds when bounds are present, including overflow. They are per-bucket counts, not cumulative counts. Counts without bounds are rejected.
count Unsigned integer Total observations. Keep it consistent with the bucket counts.
sum Finite number Sum of observations.
min, max Finite numbers Optional observed extrema; omit when no observations exist.

Fields can be top-level, as above, or inside a single distribution object. Do not mix nested and top-level distribution fields, mix distribution fields with value, or emit a distribution without any numeric evidence. The parser supports summary-only distributions, but summaries cannot invent a bucket shape.

The distribution helpers use default bounds [1,2,5,10,20,50,100,200,500,1000,2000,5000,10000] when bounds are omitted or empty. Those defaults suit millisecond-scale observations; choose explicit bounds for bytes or other units. The SDK buckets raw values and calculates count/sum/min/max. Bash has no distribution helper; construct the documented JSON or use another SDK.

Per-run budgets and malformed output

Budget Maximum
Accepted metrics 256, possibly lower for a signed bundle
Distinct metric-name + label-set series 64
Labels per metric 8
One stdout line 64 KiB
Total stdout read 4 MiB
Lines examined 20,000
Malformed lines before a run-level parser failure More than 100; zero accepted metrics with any malformed attempt also fails

Blank lines are ignored. Rejected/malformed lines and truncation are reported in run diagnostics. A line count is not a packet-loss denominator. Inspect those diagnostics rather than interpreting missing custom metrics as healthy or zero.

Use stderr for logs: rs.log in the engine, console.error in Node, print(..., file=sys.stderr) in Python, printf ... >&2 in Bash, and [Console]::Error.WriteLine(...) in PowerShell. Keep secrets and sensitive responses out of both logs and metric labels.

See the exact language helpers: JavaScript, Python, Node, Bash and PowerShell.

Screenshot