Release
Announcing Toise 0.11.0 — vocabulary and correlation
A graph is only useful if you can get from a node to its measurements. 0.11.0 fixes an answer that was quietly wrong on that path — an entity could hand you somebody else's identity — and gives producers the type vocabulary they were previously obliged to retype by hand. Nothing on the wire changes.
Both halves come from the same place: a contract that was asserted rather than checked. Neither defect was visible from inside the code that had it, which is the part worth reading even if you do not run Toise.
An entity answering with its observer's identity
telemetry_keys derives the labels that locate an entity's
metrics and logs. To be useful it walks one hop and inherits from a
neighbor: a listening socket has no host.id of its own, it
gains its host's through runs_on.
It walked every relation. For an entity with no key of its
own that meant inheriting from whatever happened to touch it. A database
observed by a monitoring agent came back carrying that agent's
service.name, sourced honestly as "via monitors" — and a
consumer that trusted the answer went and queried the wrong machine's
telemetry. Not an error anyone would see: a plausible answer about the
wrong thing.
Inheritance is now restricted to ownership hops, and it is
directional — a listener gains its host's keys by following
runs_on outward, a route gains its device's by following
has_route back. Observation and peer relations contribute
nothing, because the neighbor there describes something else. Graph
traversal is untouched: paths still cross those edges. Only key derivation
was at fault.
An empty answer now means something too. Some types legitimately have no telemetry — an address or a route is a graph fact, not a measurement — and the tool now says no key exists rather than reporting that it found none, which a consumer cannot distinguish from "keep looking".
Where the round trip actually holds
The guidance no longer implies a uniform guarantee, because there is not one. On the OTLP rail the round trip is guaranteed. On a Prometheus-family backend it holds only where the collector was configured to flatten resource attributes into labels — a deployment choice, not a property of the wire. On a producer's own scrape endpoint there is no resource at all, so resource-borne keys are simply absent. Saying which rail you are on is the contract; pretending it does not matter is how a join silently returns nothing.
The type vocabulary is exported
Entity and relation types were free strings on the producer side. The registered vocabulary lived in an internal package nobody could import, so every producer kept private constants — and one product could spell the same type two ways in two of its own sources with nothing failing. That is not hypothetical: it is how a real mismatch reached production.
pkg/emit/wire now exports the whole set — twelve entity types,
thirteen relation types, plus accessors to validate a value you did not
write yourself. An invented or mistyped type becomes a compile error
instead of a batch rejected at runtime. The package stays deliberately
stdlib-only, so importing the vocabulary pulls no protocol stack into a
producer's module graph.
The part that makes it honest: Toise's own registry derives from
those same constants rather than keeping a parallel copy, and a
test compares the two sets in both directions. A type Toise accepts but
does not publish would leave producers unable to name it; a type published
but not accepted would be refused after a producer trusted it. Neither can
ship now. Available as pkg/emit/v0.6.0.
Typed attributes were always possible
The SDK carries two descriptive maps that always landed in the same place on the wire: one keeping each value's type, one a shortcut for values that really are strings. The string map was declared first and the typed one documented as "the rarer structured case" — so a producer reading the SDK concluded it could not carry typed values at all, and planned a re-encoding around a limitation that did not exist. A capacity, a frequency or a flag is a number or a boolean; that is the common case. The presentation is now the right way round, and nothing on the wire changed.
Who owns what
One line of governance came out of the same round, and it is now in the API stability policy: each side owns what it can verify. Toise holds the vocabulary and the wire form; a producer holds the transport and the verification of its own emission. It follows that a producer whose pipeline already owns batching, backpressure, retries and tenant propagation should not adopt the SDK's client at runtime — that would cost it four properties to gain none. Importing the vocabulary, or the encoder inside a differential test that fails the build on drift, gets the guarantee without the coupling.
Get it
go install github.com/toise-dev/toise/cmd/toise-server@v0.11.0
Binaries for linux and darwin (amd64 / arm64) are on the
release,
each with a checksum, and the container image is on
GHCR.
See the 0.11.0 docs and the
changelog.
Producers pick up the vocabulary with pkg/emit/v0.6.0.