3.22 Fields and Results
Every result record is a flat MessagePack map. There is no nesting in a result, in any mode.
Flatness is what makes one set of rules — for access control, for ordering, for grouping, for projection — apply uniformly to a header field, a payload field and a metric label alike. A nested result would need a path language, and a path language would need to be reproduced identically by every SD author and every client.
3.22.1 Event fields #
These names resolve to header fields:
timestamp, cpu_id, sequence, origin_class, event_type,
effective_token_guid, true_token_guid, process_guid, boot_id
Every other name resolves to a payload field.
3.22.1.1 Header names are reserved #
Header field names are reserved in the query language and in result maps. If a payload carries a top-level key with a header field's name, the header wins.
The colliding payload value is stored unchanged, and is retrievable as
part of the raw payload by whatever holds it, but it is not exposed
through field resolution, SELECT, WHERE, aggregation, access control
or result maps. Suppression is applied before descendants are
flattened, so a payload key named timestamp removes its entire subtree
from the query surface, not just itself.
An emitter SHOULD avoid payload keys that collide with header names.
3.22.1.2 Flattening #
Payload maps are flattened recursively, path segments joined with .:
a payload {source: {name: "x"}} exposes the field source.name.
Each map key on a queryable path MUST be a MessagePack string matching:
[A-Za-z_][A-Za-z0-9_-]*
Note that . is not permitted in a segment, though it is permitted
in an identifier generally (§3.19) — a key containing a dot could not be
distinguished from a path through two maps.
A key that is not a string, contains ., or does not match the grammar
is stored unchanged and is not queryable: it does not resolve, does
not appear in a result map, and has no field identity for access
control. An empty map produces no field at all.
Maps are containers; every non-map value, arrays included, is emitted at its flattened path (§3.17).
If two payload entries flatten to the same path, the first in MessagePack map order wins and later duplicates are suppressed.
3.22.2 Log fields #
timestamp, origin, is_error, message, boot_id, job_id
The set is closed. There are no payload fields and no flattening, and a collector MUST reject any other log field name as a parse error rather than resolving it to null. A log record has a fixed shape, so a name outside it is a mistake the collector can see — unlike an event payload field, which may legitimately be absent from a given record.
is_error is a boolean in the query language, and compares against
true/false or against 1/0.
3.22.3 Metric fields #
timestamp, boot_id, name, type, value
Every other name resolves to a label. Ingestion refuses labels colliding with these five (§3.10), so the flat namespace is unambiguous by construction rather than by a precedence rule.
type is the series type as a string: "counter", "gauge" or
"histogram".
3.22.4 What a record contains #
Event records carry the header fields plus every non-suppressed flattened payload field, as top-level keys.
Log records carry the log fields.
Raw metric sample records carry timestamp, boot_id, name,
type, value, and the series' labels as top-level keys.
Aggregated metric results carry name, type and value, plus
labels when the result belongs to one label set. They carry boot_id
only when the query restricted the samples to exactly one boot by a
boot_id equality predicate, in which case the value is that boot ID; a
result that could span boots omits it rather than picking one.
Aggregation results in event and log mode carry the group key fields and the aggregate output, with the fixed schemas of §3.23.
3.22.5 SELECT #
SELECT narrows a result record to the named fields. It is valid only
for non-aggregating event and log queries.
A collector MUST reject SELECT combined with COUNT BY, TOP N BY,
DISTINCT or GROUP, and MUST reject it in metric mode: all of those
have fixed output schemas, and a clause that reshapes a fixed schema is
a contradiction rather than a refinement.
SELECT is applied last, after every other phase (§3.23). It
controls the shape of the output and nothing else: a field not selected
is still available to WHERE, to SORT, and to grouping. Narrowing
what is displayed MUST NOT narrow what is filtered on.