A feed's schema: what each of its fields means (spec/08 §10.1, D-136).
A schema maps a field — named as the feed's rows name it, an atom or a string — to a
description: its type, and as much of unit, quantity, label, order,
status, polarity, target, continuity, window, metric_kind and bounds as
the feed knows. It says what
the numbers are, whoever draws them, and never how they are drawn: a description has
no colour key, since colour is the theme's to choose from the meaning (#533). A :time
field holds instants; a feed whose clock is a number describes it :number and
window: true, the field its windows are over (D-154). A numeric field may say how it
was measured, metric_kind: :gauge | :counter | :rate, which refines what its
quantity's additivity allows, and where its values lie, bounds: [min, max], a display
hint over its quantity's (D-155). A unit is a UCUM code Visualize.Unit reads and a
quantity one of Visualize.Quantity.all/0, and when both are given the unit measures
the quantity (D-157).
A schema is identified by its version, a content hash (spec/08 §10.2): the same
schema has the same version on every node and under every release, and any change of
content is a new version. A Visualize.Data.Delivery names the version its rows were
produced under; Visualize.Data.Schema.Cache holds schemas by {feed, version}.
Examples
iex> {:ok, schema} =
...> Visualize.Data.Schema.new(%{
...> t: %{type: :time},
...> latency: %{type: :number, unit: "s", quantity: :duration, label: "Request time"},
...> state: %{type: :category, order: ["ok", "warn", "fail"],
...> status: %{"ok" => :good, "warn" => :warning, "fail" => :bad}}
...> })
iex> Visualize.Data.Schema.fetch(schema, "latency", :unit)
{:ok, "s"}
iex> String.length(Visualize.Data.Schema.version(schema))
64
iex> Visualize.Data.Schema.new(%{state: %{type: :category, colors: %{"ok" => "#0a0"}}})
{:error, [{[:state, :colors], {:colour_key, :colors}}]}
Summary
Functions
The twelve description keys, :type first (spec/08 §10.1).
A field's description, by either spelling of its name (spec/08 §6.2).
One attribute of a field's description; :error when the field or the attribute is absent.
One fault of new/1 as a line a person reads.
The schema of a map of field descriptions, or every fault of it by path (spec/08 §10.1).
The schema of a map of field descriptions, or ArgumentError naming every fault.
The schema's version: the SHA-256 of its canonical encoding as 64 lowercase hex digits
(spec/08 §10.2), computed once by new/1.
Types
@type description() :: %{ :type => :time | :number | :category | :text, optional(:unit) => String.t(), optional(:quantity) => atom(), optional(:label) => String.t(), optional(:order) => [String.t() | atom() | number(), ...], optional(:status) => %{required(term()) => atom()}, optional(:polarity) => :higher_is_better | :lower_is_better | :neutral, optional(:target) => number(), optional(:continuity) => number(), optional(:window) => boolean(), optional(:metric_kind) => :gauge | :counter | :rate, optional(:bounds) => [number() | nil] }
What one field means (spec/08 §10.1).
@type error() :: {[name() | atom() | non_neg_integer() | term()], term()}
A fault of new/1: the path from the schema to the value, and why.
A field name, as the feed's rows spell it.
@type t() :: %Visualize.Data.Schema{ fields: %{required(name()) => description()}, version: String.t() }
Functions
@spec attributes() :: [atom(), ...]
The twelve description keys, :type first (spec/08 §10.1).
@spec fetch(t(), name()) :: {:ok, description()} | :error
A field's description, by either spelling of its name (spec/08 §6.2).
iex> schema = Visualize.Data.Schema.new!(%{"v" => %{type: :number}})
iex> Visualize.Data.Schema.fetch(schema, :v)
{:ok, %{type: :number}}
iex> Visualize.Data.Schema.fetch(schema, :w)
:error
One attribute of a field's description; :error when the field or the attribute is absent.
One fault of new/1 as a line a person reads.
iex> Visualize.Data.Schema.format_error({[:latency, :unit], {:invalid_for, :category}})
"latency.unit: is not a key a :category field takes"
The schema of a map of field descriptions, or every fault of it by path (spec/08 §10.1).
iex> Visualize.Data.Schema.new(%{v: %{type: :category, unit: "s"}})
{:error, [{[:v, :unit], {:invalid_for, :category}}]}
iex> Visualize.Data.Schema.new(%{v: %{type: :number, unit: "By", quantity: :duration}})
{:error, [{[:v, :quantity], {:quantity, :duration, "By"}}]}
The schema of a map of field descriptions, or ArgumentError naming every fault.
The schema's version: the SHA-256 of its canonical encoding as 64 lowercase hex digits
(spec/08 §10.2), computed once by new/1.