ateattr

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package ateattr is the single source of truth for substrate's ate.* telemetry attributes: the identity keys stamped on spans/logs, and the bounded value sets used as metric labels. Centralizing them keeps a key (and value) meaning the same thing across every signal and binary.

Index

Constants

View Source
const (
	AtespaceKey           = attribute.Key("ate.atespace")
	ActorNameKey          = attribute.Key("ate.actor.name")
	ActorUIDKey           = attribute.Key("ate.actor.uid")
	ActorContainerNameKey = attribute.Key("ate.actor.container.name")
	TemplateNameKey       = attribute.Key("ate.template.name")
	TemplateAtespaceKey   = attribute.Key("ate.template.atespace")
	ActorVersionKey       = attribute.Key("ate.actor.version")
)

Dotted ate.* matches the metric-instrument naming (atenet.*, atelet.*), not the ate.dev/ slash form, which is k8s labels only. name vs uid mirror the k8s object model that ResourceMetadata follows: ate.actor.name is the atespace-scoped addressable name, ate.actor.uid is the server-assigned globally-unique key. There is deliberately no ate.actor.id (an ambiguous term when both a name and a uid exist). atespace and template are their own top-level namespaces (ate.atespace, ate.template.*) rather than nested under actor: both are first-class resources that also appear in non-actor telemetry, so the keys must mean the same thing regardless of what a span is about. ActorContainerNameKey nests under actor for the mirror-image reason: it names a container the ActorTemplate declared, which exists only within an actor. It is deliberately not the registry's k8s.container.name or container.name, both of which the collector already assigns to the worker pod's own containers.

View Source
const (
	LogTraceIDField    = "trace_id"
	LogSpanIDField     = "span_id"
	LogTraceFlagsField = "trace_flags"
)

Trace-context fields for structured logs, per the OTel spec for non-OTLP log formats: these exact names, top-level in the record, lowercase hex. Not ate.* and not attributes - a collector maps them onto the log record's own TraceId/SpanId/flags fields. https://opentelemetry.io/docs/specs/otel/compatibility/logging_trace_context/

View Source
const (
	ActorStateResuming   = "resuming"
	ActorStateRunning    = "running"
	ActorStateSuspending = "suspending"
	ActorStateSuspended  = "suspended"
	ActorStatePausing    = "pausing"
	ActorStatePaused     = "paused"
	ActorStateCrashed    = "crashed"
	ActorStateDeleting   = "deleting"
	ActorStateReverting  = "reverting"
	ActorStateDeleted    = "deleted"
	ActorStateUnknown    = "unknown"
)

Values for ActorStateKey, mirroring ateapipb.ActorState with the ACTOR_STATE_ prefix dropped so the two cannot fork. ActorStateDeleted is the exception and has no enum counterpart: the record is gone, so no stored state can stand for it.

View Source
const (
	ActorOperationNameKey  = attribute.Key("ate.actor.operation.name")
	WorkerPoolNamespaceKey = attribute.Key("ate.workerpool.namespace")
	WorkerPoolNameKey      = attribute.Key("ate.workerpool.name")
	WorkerStateKey         = attribute.Key("ate.worker.state")
	SandboxClassKey        = attribute.Key("ate.sandbox.class")
	SnapshotKindKey        = attribute.Key("ate.snapshot.kind")
	SnapshotScopeKey       = attribute.Key("ate.snapshot.scope")
	SnapshotPhaseKey       = attribute.Key("ate.snapshot.phase")
	ImageCacheOutcomeKey   = attribute.Key("ate.imagecache.outcome")
	SchedulerOutcomeKey    = attribute.Key("ate.scheduler.outcome")
	RouterResumeKey        = attribute.Key("ate.router.resume")
	RouterOutcomeKey       = attribute.Key("ate.router.outcome")
	StatsSourceKey         = attribute.Key("ate.stats.source")
)

Metric-label keys: the only ate.* attributes allowed on metric datapoints, each with a small bounded value set. High-cardinality identity (actor name/uid, atespace) is absent by design; it belongs on spans and logs. ActorOperationNameKey follows the registry's *.operation.name pattern (db.operation.name, gen_ai.operation.name). WorkerStateKey stays worker-rooted rather than nesting under the pool so it can grow siblings. WorkerPoolNamespaceKey pairs with WorkerPoolNameKey: a WorkerPool is namespaced, so the name alone does not identify one. The snapshot keys are orthogonal: kind is which snapshot, scope is what content it covers, and phase is which step of the operation an observation timed. Naming one image within a snapshot is the registry's file.name, not an ate.* key of its own. ImageCacheOutcomeKey is rooted at the subsystem, not under actor: the layer pool is node state every actor shares. For the same reason it is the only ate.* label on its counter.

View Source
const (
	ActorEpochKey            = attribute.Key("ate.actor.epoch")
	StatsKindKey             = attribute.Key("ate.stats.kind")
	StatsMemoryUsageKey      = attribute.Key("ate.stats.memory.usage")
	StatsMemoryPeakKey       = attribute.Key("ate.stats.memory.peak")
	StatsMemoryWorkingSetKey = attribute.Key("ate.stats.memory.working_set")
	StatsCPUTimeKey          = attribute.Key("ate.stats.cpu.time")
)

Keys of the actor usage record. Logs only: the measurements are unbounded and the epoch is per activation. The measurement names follow the ate.actor.stats.* instruments and share their units, so a query works the same on both signals: the memory keys are bytes, StatsCPUTimeKey is seconds as a double.

ActorEpochKey identifies one activation of an actor, a Run or Restore, as the unix-nano time it began. It is the boundary of ate.stats.cpu.time, which restarts at zero with each activation.

View Source
const (
	StatsKindPeriodic = "periodic"
	StatsKindInitial  = "initial"
	StatsKindFinal    = "final"
)

Values for StatsKindKey. An initial or final sample brackets an activation; a periodic one is the timer's.

View Source
const (
	StatsSourceUnspecified = "unspecified"
	StatsSourceCgroup      = "cgroup"
	StatsSourceGuestAgent  = "guest-agent"
)

Values for StatsSourceKey, mirroring ateompb.StatsSource. The two sources do not measure the same thing (the cgroup source charges the sandbox runtime's overhead along with the workload, the guest-agent source sees only the workload's containers), so rollups must group by this key rather than sum across it.

View Source
const (
	// RouterResumeNone indicates the resume completed and found the actor already
	// running (steady-state route).
	RouterResumeNone = "none"
	// RouterResumeTriggered indicates this request won the singleflight lock and
	// completed a cold activation.
	RouterResumeTriggered = "triggered"
	// RouterResumeJoined indicates this request waited on another request's
	// singleflight resume, which completed a cold activation.
	RouterResumeJoined = "joined"
	// RouterResumeUnknown indicates the resume did not complete, so the router
	// cannot tell whether an activation ran. The resume failed, or the request
	// stopped first, or the direction never resumes an actor.
	RouterResumeUnknown = "unknown"
)

Values for RouterResumeKey.

View Source
const (
	ImageCacheOutcomeHit       = "hit"
	ImageCacheOutcomeMiss      = "miss"
	ImageCacheOutcomeError     = "error"
	ImageCacheOutcomeCancelled = "cancelled"
	ImageCacheOutcomeTimeout   = "timeout"
)

Values for ImageCacheOutcomeKey. A hit is a complete image record; a miss must pull. A failed lookup is neither: Error is the only one that carries an error.type, Cancelled and Timeout mean the caller gave up.

View Source
const (
	WorkerStateIdle          = "idle"
	WorkerStatePartial       = "partial"
	WorkerStateAtCapacity    = "at_capacity"
	WorkerStateUnschedulable = "unschedulable"
)

Values for WorkerStateKey. Unschedulable wins over occupancy.

View Source
const (
	OperationCreate  = "create"
	OperationResume  = "resume"
	OperationSuspend = "suspend"
	OperationPause   = "pause"
	OperationDelete  = "delete"
	OperationRevert  = "revert"
	OperationUnknown = "unknown"
)

Values for ActorOperationNameKey: the actor lifecycle operations ateapi serves.

View Source
const (
	SchedulerOutcomeAssigned     = "assigned"
	SchedulerOutcomeNoFreeWorker = "no_free_worker"
	SchedulerOutcomeError        = "error"
)

Values for SchedulerOutcomeKey. NoFreeWorker is a capacity signal, not a failure, so it is a distinct outcome rather than an error.type value; only the Error outcome carries an error.type.

View Source
const (
	SnapshotKindGolden = "golden"
	SnapshotKindLatest = "latest"
	SnapshotKindLocal  = "local"
	SnapshotKindBoot   = "boot"
)

Values for SnapshotKindKey, set by ateapi from its own resume branching, so the label is bounded at the producer: Local restores an in-node snapshot, Latest pulls the actor's durable snapshot from object storage, Golden pulls the template's golden image, Boot is a from-scratch start (not a restore). atelet derives the same values for its own histograms, where the kind is the snapshot a restore reads or a checkpoint writes; Boot never appears there.

View Source
const (
	SnapshotScopeFull         = "full"
	SnapshotScopeData         = "data"
	SnapshotScopeDataOnGolden = "data_on_golden"
	SnapshotScopeUnknown      = "unknown"
)

Values for SnapshotScopeKey, mirroring ateletpb.SnapshotScope. Checkpoints only ever capture Full or Data; DataOnGolden is restore-only.

View Source
const (
	SnapshotPhaseVolumeMount     = "volume_mount"
	SnapshotPhaseManifestFetch   = "manifest_fetch"
	SnapshotPhaseSandboxAssets   = "sandbox_assets"
	SnapshotPhaseDownload        = "download"
	SnapshotPhaseOCIUnpack       = "oci_unpack"
	SnapshotPhaseAteomRestore    = "ateom_restore"
	SnapshotPhaseAteomCheckpoint = "ateom_checkpoint"
	// Persist is one step with two destinations (upload for external, rename
	// for local); SnapshotKindKey already says which.
	SnapshotPhasePersist = "persist"
	SnapshotPhaseTotal   = "total"
)

Values for SnapshotPhaseKey. Phases overlap (the download runs concurrently with the asset fetch and OCI unpack), so they are independent observations, not a partition of Total: summing across them is meaningless.

View Source
const ActorStateKey = attribute.Key("ate.actor.state")

ActorStateKey is log-only. It is bounded, but it is only ever recorded beside actor identity, which no metric may carry.

View Source
const ErrorTypeKey = attribute.Key("error.type")

ErrorTypeKey is the OTel registry attribute, reused verbatim (not aliased into ate.*): failures are reported on the same instrument via this key, its absence meaning success, never as a parallel _failures counter.

View Source
const OTLPRelayKey = attribute.Key("ate.otlp.relay")

OTLPRelayKey is a resource attribute rather than a subject one: it describes how the emitting component reached the collector, not what the signal is about. Only the components that have a relay to take or miss carry it.

View Source
const ReservedNamespace = "ate."

ReservedNamespace is substrate's. A producer that merges untrusted fields into a record drops everything under it, so nothing a workload sets can read as platform-issued attribution downstream.

View Source
const SandboxClassUnknown = "unknown"

SandboxClassUnknown is the NormalizeSandboxClass fallback.

View Source
const TemplateUnknown = "unknown"

TemplateUnknown is the fallback for a template dimension the emitter cannot resolve. "unknown" is a legal atespace or template name, so a real object with that name collides with the fallback. Like ate.sandbox.class="unknown", the registry accepts that collision to keep the dimension bounded and non-empty.

Variables

AllOperations lists all registered bounded actor lifecycle operations.

Functions

func ActorAttributes

func ActorAttributes(a *ateapipb.Actor) []attribute.KeyValue

ActorAttributes is nil-safe; a nil Actor yields zero-valued attributes.

func ActorLogAttrs

func ActorLogAttrs(a resources.ActorAttribution) []slog.Attr

ActorLogAttrs is the same identity for a component's own slog record, which needs no envelope: a collector lifts flat keys straight onto the record's OTLP attributes. It must agree with ActorLogLabels key for key, or joining a component record to the actor lifecycle stream takes two spellings.

func ActorLogLabels

func ActorLogLabels(a resources.ActorAttribution, containerName string) map[string]string

ActorLogLabels returns the actor identity stamped on every actor log record. A string map because GKE promotes the record's label group into LogEntry.labels, which is string-valued. An empty containerName omits the key rather than emitting it empty, so a consumer filtering on it gets container output only.

func ActorMetricAttributes

func ActorMetricAttributes(a *ateapipb.Actor, sandboxClass, operationName string) []attribute.KeyValue

ActorMetricAttributes returns the metric labels for an Actor. High-cardinality attributes (atespace, actor name, actor uid) are omitted. The worker-pool pair is omitted while the actor holds no assignment, so a crash before the actor reaches a worker reports no pool rather than an empty-string one.

func ActorRefAttributes

func ActorRefAttributes(actorRef resources.ActorRef) []attribute.KeyValue

ActorRefAttributes returns the subset knowable before the Actor record resolves: only the (atespace, name) the request addresses. The uid and version are server-assigned and unknown until the record loads, so they are omitted.

func ActorRefLogAttrs

func ActorRefLogAttrs(actorRef resources.ActorRef) []slog.Attr

ActorRefLogAttrs is ActorLogAttrs for a record written before the Actor resolves, mirroring ActorRefAttributes on the span side. The uid is unknown until the record loads, so it is omitted rather than emitted empty.

func ActorStateValue added in v0.2.0

func ActorStateValue(state ateapipb.ActorState) string

ActorStateValue maps the committed state onto its label value, so a producer reports the state the store holds rather than one it names by hand.

func NormalizeOperationName

func NormalizeOperationName(op string) string

NormalizeOperationName ensures op is one of the bounded lifecycle operations. Any unlisted or empty operation maps to OperationUnknown.

func NormalizeSandboxClass

func NormalizeSandboxClass(class string) string

NormalizeSandboxClass bounds the label: atelet reads the class from a snapshot manifest in object storage that nothing validates on the way in. Empty reports as unknown rather than the gvisor default, so a manifest problem stays visible.

func NormalizeTemplateDimension added in v0.2.0

func NormalizeTemplateDimension(dim string) string

NormalizeTemplateDimension returns dim, or TemplateUnknown when dim is empty. Only the router calls it today. The other metrics that carry ate.template.* emit the raw value.

func SandboxClassAttribute added in v0.2.0

func SandboxClassAttribute(class string) attribute.KeyValue

SandboxClassAttribute sets ate.sandbox.class. No source of the class is validated, thus an emitter that sets the attribute must set it through this helper and not through SandboxClassKey.

To omit the attribute while the class is unknown is a different choice, and two emitters make it: recordSchedulerAssignment and snapshotOp.attrs.

func SnapshotScopeValue

func SnapshotScopeValue(scope ateletpb.SnapshotScope) string

SnapshotScopeValue maps the wire enum onto its label value, shared so ateapi (which sets the scope) and atelet (which receives it) cannot drift. An unrecognized scope reports as unknown rather than stringified, so no wire value can widen the label set.

func WorkerPoolAttributes

func WorkerPoolAttributes(namespace, name string) []attribute.KeyValue

WorkerPoolAttributes returns the namespaced identity of a WorkerPool. A WorkerPool is namespaced, so half the pair identifies no pool: either key missing drops both, rather than emit an empty-string series that merges same-named pools and joins to nothing.

This is for the actor-centric instruments, where an unknown pool is omitted. Pool-centric ones that record a deliberate zero-valued series for "no pool matched" build the pair themselves.

Types

This section is empty.

Jump to

Keyboard shortcuts

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