measurement

package
v0.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

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

View Source
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

Types is the list of all supported measurement types.

Functions

func FilterOut

func FilterOut(readings map[string]Reading, keys []string) map[string]Reading

FilterOut returns a new map with keys filtered out based on the provided patterns. Supports wildcard patterns:

  • "prefix*" matches keys starting with "prefix"
  • "*suffix" matches keys ending with "suffix"
  • "*contains*" matches keys containing "contains"
  • "exact" matches keys exactly

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

func (ie *ItemEntry) UnmarshalJSON(data []byte) error

UnmarshalJSON custom unmarshaler for ItemEntry to handle Reading interface inside Data, mirroring Subtype's behavior.

func (*ItemEntry) UnmarshalYAML added in v0.16.0

func (ie *ItemEntry) UnmarshalYAML(node *yaml.Node) error

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

func Bool

func Bool(v bool) Reading

func Float64

func Float64(v float64) Reading

func Int

func Int(v int) Reading

Convenience constructors for each allowed scalar type.

func Int64

func Int64(v int64) Reading

func Str

func Str(v string) Reading

func ToReading

func ToReading(v any) Reading

ToReading creates a Reading from any allowed scalar type. If the type is not allowed, it returns a string representation.

func Uint

func Uint(v uint) Reading

func Uint64

func Uint64(v uint64) Reading

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]) Any

func (s Scalar[T]) Any() any

func (Scalar[T]) MarshalJSON

func (s Scalar[T]) MarshalJSON() ([]byte, error)

MarshalJSON makes the JSON value be the underlying scalar (not an object wrapper).

func (Scalar[T]) MarshalYAML

func (s Scalar[T]) MarshalYAML() (any, error)

MarshalYAML makes the YAML value be the underlying scalar (not an object wrapper).

func (Scalar[T]) String

func (s Scalar[T]) String() string

String returns the string representation of the underlying scalar value.

func (*Scalar[T]) UnmarshalJSON

func (s *Scalar[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals a JSON value into the underlying scalar.

func (*Scalar[T]) UnmarshalYAML

func (s *Scalar[T]) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML unmarshals a YAML 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) Get

func (st *Subtype) Get(key string) Reading

Get retrieves a reading by key, returning nil if not found.

func (*Subtype) GetInt64

func (st *Subtype) GetInt64(key string) (int64, error)

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

func (st *Subtype) GetString(key string) (string, error)

GetString attempts to retrieve a string value, returning an error if not found or wrong type.

func (*Subtype) Has

func (st *Subtype) Has(key string) bool

Has checks if a key exists in the subtype data.

func (*Subtype) UnmarshalJSON

func (st *Subtype) UnmarshalJSON(data []byte) error

UnmarshalJSON custom unmarshaler for Subtype to handle Reading interface

func (*Subtype) UnmarshalYAML

func (st *Subtype) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML custom unmarshaler for Subtype to handle Reading interface

func (*Subtype) Validate

func (st *Subtype) Validate() error

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.

const (
	TypeK8s             Type = "K8s"
	TypeGPU             Type = "GPU"
	TypeOS              Type = "OS"
	TypeSystemD         Type = "SystemD"
	TypeNodeTopology    Type = "NodeTopology"
	TypeNetworkTopology Type = "NetworkTopology"
)

func ParseType

func ParseType(s string) (Type, bool)

ParseType parses a string into a measurement Type. Returns the Type and true if parsing succeeds, or empty Type and false if the string is invalid.

func (Type) String

func (mt Type) String() string

String returns the string representation of the measurement Type.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL