Documentation
¶
Overview ¶
Package measurement provides types and utilities for collecting, comparing, and filtering system measurements from various sources (Kubernetes, GPU, OS, SystemD, NodeTopology, NetworkTopology).
Public API contract ¶
This package is part of aicr's cross-repo public API. External producers (e.g. k8s-launch-kit) import these types directly to emit Measurements that aicr Snapshots can consume. The Go type definitions AND the schema conventions (which Subtype names mean what, which fields belong in Data vs Context, the NetworkTopology layout) are part of the contract — see docs/integrator/measurement-api.md. Breaking changes require a pseudo-version bump that downstream consumers pin against.
Core Types ¶
The package defines a hierarchical structure for measurements:
- Type: Enum identifying the measurement source (K8s, GPU, OS, SystemD, NodeTopology, NetworkTopology)
- Measurement: Contains a Type and a slice of Subtypes
- Subtype: Named collection of key-value data (e.g., "cluster", "node"); may also carry an ordered Items list of structured records
- ItemEntry: One element of a Subtype.Items list. Data holds Reading scalars; Context holds string metadata. Mirrors Subtype's payload contract.
- Reading: Interface for type-safe scalar values (int, float64, string, bool, etc.)
Creating Measurements ¶
Use convenience constructors to create readings:
m := &Measurement{
Type: TypeK8s,
Subtypes: []Subtype{
{
Name: "cluster",
Data: map[string]Reading{
"version": Str("1.28.0"),
"nodes": Int(3),
"ready": Bool(true),
},
},
},
}
Or use the builder pattern for cleaner code:
m := NewMeasurement(TypeK8s).
WithSubtype(
NewSubtypeBuilder("cluster").
Set("version", Str("1.28.0")).
Set("nodes", Int(3)).
Build(),
)
Accessing Data ¶
Use type-safe getters to retrieve values:
version, err := m.GetSubtype("cluster").GetString("version")
nodes, err := m.GetSubtype("cluster").GetInt64("nodes")
ready, err := m.GetSubtype("cluster").getBool("ready")
Filtering Data ¶
Filter sensitive or unwanted keys using wildcard patterns:
// Remove all keys containing "password" or starting with "secret"
filtered := FilterOut(readings, []string{"*password*", "secret*"})
// Keep only version and count fields
kept := filterIn(readings, []string{"version", "count"})
Serialization ¶
Measurements support JSON and YAML marshaling/unmarshaling:
data, _ := json.Marshal(m) yaml, _ := yaml.Marshal(m)
The Reading interface is automatically marshaled to its underlying value, avoiding wrapper structures in the output.
Index ¶
- Constants
- Variables
- func FilterOut(readings map[string]Reading, keys []string) map[string]Reading
- type AllowedScalar
- type ItemEntry
- type Measurement
- type MeasurementBuilder
- type Reading
- type Scalar
- type Subtype
- func (st *Subtype) Get(key string) Reading
- func (st *Subtype) GetInt64(key string) (int64, error)
- func (st *Subtype) GetString(key string) (string, error)
- func (st *Subtype) Has(key string) bool
- func (st *Subtype) UnmarshalJSON(data []byte) error
- func (st *Subtype) UnmarshalYAML(node *yaml.Node) error
- func (st *Subtype) Validate() error
- type SubtypeBuilder
- func (b *SubtypeBuilder) Build() Subtype
- func (b *SubtypeBuilder) Set(key string, value Reading) *SubtypeBuilder
- func (b *SubtypeBuilder) SetBool(key string, value bool) *SubtypeBuilder
- func (b *SubtypeBuilder) SetFloat64(key string, value float64) *SubtypeBuilder
- func (b *SubtypeBuilder) SetInt(key string, value int) *SubtypeBuilder
- func (b *SubtypeBuilder) SetInt64(key string, value int64) *SubtypeBuilder
- func (b *SubtypeBuilder) SetString(key, value string) *SubtypeBuilder
- func (b *SubtypeBuilder) SetUint(key string, value uint) *SubtypeBuilder
- func (b *SubtypeBuilder) SetUint64(key string, value uint64) *SubtypeBuilder
- func (b *SubtypeBuilder) WithContext(key, value string) *SubtypeBuilder
- func (b *SubtypeBuilder) WithContextMap(ctx map[string]string) *SubtypeBuilder
- func (b *SubtypeBuilder) WithItem(item ItemEntry) *SubtypeBuilder
- func (b *SubtypeBuilder) WithItems(items []ItemEntry) *SubtypeBuilder
- type Type
Constants ¶
const ( // Kubernetes measurement keys KeyVersion = "version" // GPU measurement keys KeyGPUDriver = "driver" KeyGPUModel = "model" KeyGPUCount = "gpu-count" // GPU hardware detection keys (NFD-based, no driver required) KeyGPUPresent = "gpu-present" KeyGPUDriverLoaded = "driver-loaded" KeyGPUDetectionSource = "detection-source" )
Measurement keys used by external packages.
Variables ¶
var Types = []Type{ TypeK8s, TypeGPU, TypeOS, TypeSystemD, TypeNodeTopology, TypeNetworkTopology, }
Types is the list of all supported measurement types.
Functions ¶
Types ¶
type AllowedScalar ¶
type AllowedScalar interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64 |
~bool |
~string
}
AllowedScalar is a constraint (compile-time) for what we allow as readings.
type ItemEntry ¶ added in v0.16.0
type ItemEntry struct {
Context map[string]string `json:"context,omitempty" yaml:"context,omitempty"`
Data map[string]Reading `json:"data,omitempty" yaml:"data,omitempty"`
}
ItemEntry is one element of a Subtype.Items list. It mirrors Subtype's scalar-value contract: Data holds Reading scalars; Context holds string-typed descriptive metadata. ItemEntry intentionally does NOT support nested Items — the scalar-only Reading model is preserved.
func (*ItemEntry) UnmarshalJSON ¶ added in v0.16.0
UnmarshalJSON custom unmarshaler for ItemEntry to handle Reading interface inside Data, mirroring Subtype's behavior.
type Measurement ¶
type Measurement struct {
Type Type `json:"type" yaml:"type"`
Subtypes []Subtype `json:"subtypes,omitempty" yaml:"subtypes,omitempty"`
}
Measurement represents collected data of a specific type with multiple subtypes. Each measurement contains a category (Type) and one or more Subtypes with their associated data.
func (*Measurement) GetSubtype ¶
func (m *Measurement) GetSubtype(name string) *Subtype
GetSubtype retrieves a subtype by name, returning nil if not found.
func (*Measurement) Merge ¶
func (m *Measurement) Merge(other *Measurement) error
Merge combines two measurements by adding or updating subtypes from other into m. If a subtype exists in both measurements, the data is merged (other's values take precedence). Returns an error if the measurements have different types.
func (*Measurement) Validate ¶
func (m *Measurement) Validate() error
Validate checks if the measurement is properly formed.
type MeasurementBuilder ¶
type MeasurementBuilder struct {
// contains filtered or unexported fields
}
MeasurementBuilder provides a fluent API for building Measurement instances.
func NewMeasurement ¶
func NewMeasurement(t Type) *MeasurementBuilder
NewMeasurement creates a new MeasurementBuilder with the given type.
func (*MeasurementBuilder) Build ¶
func (b *MeasurementBuilder) Build() *Measurement
Build constructs and returns the Measurement.
func (*MeasurementBuilder) WithSubtype ¶
func (b *MeasurementBuilder) WithSubtype(st Subtype) *MeasurementBuilder
WithSubtype adds a subtype to the measurement.
func (*MeasurementBuilder) WithSubtypeBuilder ¶
func (b *MeasurementBuilder) WithSubtypeBuilder(builder *SubtypeBuilder) *MeasurementBuilder
WithSubtypeBuilder adds a subtype using a SubtypeBuilder.
type Reading ¶
type Reading interface {
Any() any
String() string
json.Marshaler
json.Unmarshaler
yaml.Marshaler
yaml.Unmarshaler
// contains filtered or unexported methods
}
Reading is a *runtime* interface (so it can be stored in a map with mixed types).
type Scalar ¶
type Scalar[T AllowedScalar] struct { V T }
Scalar wraps an allowed scalar type. This is how we keep compile-time constraints while still using a runtime interface.
func (Scalar[T]) MarshalJSON ¶
MarshalJSON makes the JSON value be the underlying scalar (not an object wrapper).
func (Scalar[T]) MarshalYAML ¶
MarshalYAML makes the YAML value be the underlying scalar (not an object wrapper).
func (*Scalar[T]) UnmarshalJSON ¶
UnmarshalJSON unmarshals a JSON value into the underlying scalar.
type Subtype ¶
type Subtype struct {
Name string `json:"subtype,omitempty" yaml:"subtype,omitempty"`
Data map[string]Reading `json:"data,omitempty" yaml:"data,omitempty"`
Context map[string]string `json:"context,omitempty" yaml:"context,omitempty"`
Items []ItemEntry `json:"items,omitempty" yaml:"items,omitempty"`
}
Subtype represents a specific subcategory of measurement with associated data. Data contains the actual measurements as key-value pairs. Context provides additional metadata about the measurement environment. Items holds an ordered list of structured records (used when a subtype carries a homogeneous array such as a list of PFs); each entry follows the same scalar-only Reading discipline as Data. Data and Items are independent and may both be populated.
func (*Subtype) GetInt64 ¶
GetInt64 attempts to retrieve an int64 value, returning an error if not found or wrong type. Accepts int, int64, and float64 (JSON decoders deliver integers as float64); a float64 must be representable as an int64 without truncation.
func (*Subtype) GetString ¶
GetString attempts to retrieve a string value, returning an error if not found or wrong type.
func (*Subtype) UnmarshalJSON ¶
UnmarshalJSON custom unmarshaler for Subtype to handle Reading interface
func (*Subtype) UnmarshalYAML ¶
UnmarshalYAML custom unmarshaler for Subtype to handle Reading interface
func (*Subtype) Validate ¶
Validate checks if the subtype is properly formed. A Subtype must have a non-empty Name and carry at least one Data entry or one Items entry; Items alone is sufficient for subtypes whose payload is a list of structured records (e.g. a `pfs` subtype holding per-PF entries). The non-empty-Name invariant honors the OpenAPI `required: [subtype]` schema — the `omitempty` JSON/YAML tag elides the field on the wire only when it is intentionally being left out, never on a Validate'd value.
type SubtypeBuilder ¶
type SubtypeBuilder struct {
// contains filtered or unexported fields
}
SubtypeBuilder provides a fluent API for building Subtype instances.
func NewSubtypeBuilder ¶
func NewSubtypeBuilder(name string) *SubtypeBuilder
NewSubtypeBuilder creates a new SubtypeBuilder with the given name.
func (*SubtypeBuilder) Build ¶
func (b *SubtypeBuilder) Build() Subtype
Build constructs and returns the Subtype.
func (*SubtypeBuilder) Set ¶
func (b *SubtypeBuilder) Set(key string, value Reading) *SubtypeBuilder
Set adds or updates a key-value pair in the subtype data.
func (*SubtypeBuilder) SetBool ¶
func (b *SubtypeBuilder) SetBool(key string, value bool) *SubtypeBuilder
SetBool is a convenience method for adding bool values.
func (*SubtypeBuilder) SetFloat64 ¶
func (b *SubtypeBuilder) SetFloat64(key string, value float64) *SubtypeBuilder
SetFloat64 is a convenience method for adding float64 values.
func (*SubtypeBuilder) SetInt ¶
func (b *SubtypeBuilder) SetInt(key string, value int) *SubtypeBuilder
SetInt is a convenience method for adding int values.
func (*SubtypeBuilder) SetInt64 ¶
func (b *SubtypeBuilder) SetInt64(key string, value int64) *SubtypeBuilder
SetInt64 is a convenience method for adding int64 values.
func (*SubtypeBuilder) SetString ¶
func (b *SubtypeBuilder) SetString(key, value string) *SubtypeBuilder
SetString is a convenience method for adding string values.
func (*SubtypeBuilder) SetUint ¶
func (b *SubtypeBuilder) SetUint(key string, value uint) *SubtypeBuilder
SetUint is a convenience method for adding uint values.
func (*SubtypeBuilder) SetUint64 ¶
func (b *SubtypeBuilder) SetUint64(key string, value uint64) *SubtypeBuilder
SetUint64 is a convenience method for adding uint64 values.
func (*SubtypeBuilder) WithContext ¶ added in v0.16.0
func (b *SubtypeBuilder) WithContext(key, value string) *SubtypeBuilder
WithContext sets a single key/value entry in the subtype Context.
func (*SubtypeBuilder) WithContextMap ¶ added in v0.16.0
func (b *SubtypeBuilder) WithContextMap(ctx map[string]string) *SubtypeBuilder
WithContextMap merges the provided map into the subtype Context.
func (*SubtypeBuilder) WithItem ¶ added in v0.16.0
func (b *SubtypeBuilder) WithItem(item ItemEntry) *SubtypeBuilder
WithItem appends a single ItemEntry to the subtype Items list.
func (*SubtypeBuilder) WithItems ¶ added in v0.16.0
func (b *SubtypeBuilder) WithItems(items []ItemEntry) *SubtypeBuilder
WithItems appends a slice of ItemEntry to the subtype Items list.
type Type ¶
type Type string
Type represents the category of a measurement (e.g., Kubernetes, GPU, OS, SystemD).
Cardinality: most Types appear at most once per snapshot — one K8s measurement, one GPU measurement, etc. TypeNetworkTopology is the planned multi-instance exception (one Measurement per discovered hardware group); today we emit at most one to keep the existing find-first-by-Type consumers (constraints, recipe validation, diff indexing, fingerprint) working unchanged. Lifting that limit is a deliberate future step.