Naming rules
Names are validated identically on the client and the server, so a name the SDK accepts is one ingestion accepts. Validation is blacklist-based — Metrana rejects only what’s genuinely unsafe and allows everything else, including arbitrary Unicode (Chinese, Japanese, Cyrillic, emoji, …) and most ASCII punctuation.
There are three tiers, each building on the one before it.
Tier 1 — names (metric names, scales, attribute paths, label keys)
Section titled “Tier 1 — names (metric names, scales, attribute paths, label keys)”A plain name must:
- be non-empty;
- not start with
:(e.g.:metric✗, butns:metric✓ anda:b:c✓); - contain no whitespace or control characters (no spaces, tabs, newlines, NUL, …);
- contain none of the query-language reserved characters:
( ) [ ] , = < > ! ~ " |
Everything else is allowed — including / (used for hierarchy), ., -, _, : (not leading), and
punctuation like # $ + * ; { } @ ? &, plus any Unicode.
metrana.log("train/loss", v) # ✓ slash for hierarchymetrana.log("model.layers.0", v) # ✓metrana.log("my-metric_v2", v) # ✓metrana.log("ns:metric", v) # ✓ colon allowed (just not leading)metrana.log("loss_损失", v) # ✓ unicodemetrana.log("a=b", v) # ✗ '=' is reservedmetrana.log("a b", v) # ✗ whitespaceUse /-delimited prefixes to group related series (train/loss, eval/loss are distinct series);
labels and the evaluation shorthand are the
other way to split a name into distinct series.
Tier 2 — URL-segment names (run, project, environment ids)
Section titled “Tier 2 — URL-segment names (run, project, environment ids)”Run names, project names, and environment ids are rendered into portal URL paths and used as by-name lookup keys, so they add two restrictions on top of Tier 1:
- no URL-structural characters:
/ \ ? # %(these break or get rewritten in a URL path segment — e.g. the browser rewrites\→/, and%starts an escape); - must not be a reserved portal route segment (case-insensitive) — names like
login,dashboard,settings,runs,searchwould collide with a portal route and are rejected.
metrana.log_rl_environment_step("reward", r, rl_step=s, env_id="worker-3") # ✓metrana.log_rl_environment_step("reward", r, rl_step=s, env_id="env/0") # ✗ '/' not allowed in an env idSo an environment id like env0 or cartpole-7 is fine; env/0, a?b, or dashboard are not. (Note /
is fine in a metric name, which is not a URL segment — only the URL-segment names forbid it.)
Tier 3 — labels
Section titled “Tier 3 — labels”Label keys and values are stored in a k=v&k=v
encoding, so they reserve a couple more characters:
- Label keys follow the Tier-1 name rules plus reserve
&and=. (Non-empty, no leading:, no whitespace/control, none of()[],=<>!~"|&.) - Label values are more permissive: only control characters,
=, and&are rejected. Spaces, parens, colons, and Unicode are all fine, and an empty value is allowed.
metrana.log("r", v, labels={"policy": "greedy"}) # ✓metrana.log("r", v, labels={"host": "node-0:gpu1"}) # ✓ colon fine in a valuemetrana.log("r", v, labels={"a=b": "x"}) # ✗ '=' in a keymetrana.log("r", v, labels={"split": "a&b"}) # ✗ '&' in a valueAttribute paths
Section titled “Attribute paths”Attribute paths are /-delimited Tier-1 names. Nested
dicts/lists passed to log_config / config= / log_attributes flatten into these paths automatically (e.g.
{"optimizer": {"lr": 3e-4}} → config/optimizer/lr).
Two reservations apply by attribute kind:
- Run attributes: the
sys/sys/*namespace is reserved for system-managed fields — writing to it is rejected (useset_description/set_tagsfor the supported ones). - Environment attributes: there is no
sys/*reservation, but the three RL-environment query-language special fields —environment_id,latest_episode,latest_rl_step(and their camelCase aliases) — are reserved so a config attribute can’t shadow them in a filter / order-by.
Other limits
Section titled “Other limits”- Steps and episodes must not exceed
i64::MAX(9_223_372_036_854_775_807). - The orchestration id is an opaque token (often a framework job id), so it skips the name rules entirely: any characters are fine, it only must be ≤ 256 characters and contain no control characters. See Distributed logging.
Invalid names are rejected synchronously with a MetranaValidationError from the log* call (see
Errors).