Metrics group¶
Run-local measurements (training curves, validation scores, performance
counters) are stored in the metrics group. Published scientific series
belong under Observables.
Events¶
Each logical event has a type, a slash-separated series key, a wall-clock time, a value, and optionally a step and tags:
| Field | Type | Meaning |
|---|---|---|
type |
string | scalar for a number; a custom type names a module under meta/modules |
key |
string | the series key, slash-separated (train/loss) |
step |
integer, optional | the producer's iteration counter |
wall_time |
string | when the event happened: RFC 3339 with an explicit offset (2026-08-04T12:00:00Z, …+02:00) |
value |
number | for scalar, a finite JSON number |
tags |
object, optional | free-form labels, preserved |
A series is the events of one key, in the order they were logged. Within a
series, two events with the same step are one point: the later one
wins (a resumed run that re-logs step 100 replaces the earlier value).
Events without a step are never merged.
The closed form: dense series¶
metrics
+-- (catalog document) the group's attributes
\-- series
| \-- <safe_name>: f64[n] one value per point
\-- (steps)
| \-- (<safe_name>: i64[n]) the point's step, when the series has steps
\-- (wall_time)
| \-- (<safe_name>: string[n]) the point's RFC 3339 time
\-- (metrics.jsonl) the live WAL, a plain file (not a Zarr node)
metrics/series/<safe_name>holds onef64per point of the series, in log order after the duplicate-step rule above.steps/andwall_time/hold the matching per-point step (i64) and time (string), aligned index for index; a series with no steps has nosteps/array.- The array name is the series key's safe name: every byte of the UTF-8
key outside
[A-Za-z0-9._-]becomes%XXwith uppercase hex (train/loss→train%2Floss). The encoding is total and reversible. Because a safe name is one node name it must also not be one Zarr forbids: a key that is.or.., or that would start with__, has its first byte escaped too (.→%2E,..→%2E.,__x→%5F_x), and a reader decodes it back the same way. The empty string is not a series key.
The catalog¶
The metrics/ group attributes are the catalog document:
{
"wal": { "lines": 3, "bytes": 233 },
"series": {
"train/loss": { "type": "scalar", "count": 2, "latest_step": 2,
"latest_timestamp": "2026-08-04T00:00:02+00:00" }
}
}
seriesnames every densified series: itstype, its pointcount, and the step and time of its last point (nullwhen it has none).walis the watermark: the dense series hold exactly the firstlinescomplete lines (bytesbytes) ofmetrics/metrics.jsonl. Up to the watermark the dense series are authoritative; WAL lines past it are newer and a reader appends them, under the same duplicate-step rule. A catalog withoutwalcovers no WAL: the dense series are the whole record.- Other keys are preserved.
The live WAL is specified in Metrics WAL.