Skip to content

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 ✗, but ns:metric ✓ and a: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 hierarchy
metrana.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) # ✓ unicode
metrana.log("a=b", v) # ✗ '=' is reserved
metrana.log("a b", v) # ✗ whitespace

Use /-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, search would 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 id

So 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.)

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 value
metrana.log("r", v, labels={"a=b": "x"}) # ✗ '=' in a key
metrana.log("r", v, labels={"split": "a&b"}) # ✗ '&' in a value

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 (use set_description / set_tags for 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.
  • 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).