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
- Variables
- func ActorAttributes(a *ateapipb.Actor) []attribute.KeyValue
- func ActorLogAttrs(a resources.ActorAttribution) []slog.Attr
- func ActorLogLabels(a resources.ActorAttribution, containerName string) map[string]string
- func ActorMetricAttributes(a *ateapipb.Actor, sandboxClass, operationName, reason string) []attribute.KeyValue
- func ActorRefAttributes(actorRef resources.ActorRef) []attribute.KeyValue
- func ActorRefLogAttrs(actorRef resources.ActorRef) []slog.Attr
- func FailureAttributes(reason string) []attribute.KeyValue
- func FailureDomain(reason string) string
- func FailureLogAttrs(reason string) []slog.Attr
- func FailureReason(err error) string
- func NormalizeOperationName(op string) string
- func NormalizeSandboxClass(class string) string
- func SnapshotScopeValue(scope ateletpb.SnapshotScope) string
- func WorkerPoolAttributes(namespace, name string) []attribute.KeyValue
Constants ¶
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.
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/
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") SchedulingConstraintKey = attribute.Key("ate.scheduling.constraint") RouterResumeKey = attribute.Key("ate.router.resume") RouterOutcomeKey = attribute.Key("ate.router.outcome") FailureReasonKey = attribute.Key("ate.failure.reason") FailureDomainKey = attribute.Key("ate.failure.domain") 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.
const ( FailureDomainInfrastructure = "infrastructure" FailureDomainWorkload = "workload" FailureDomainUnknown = "unknown" )
Values for FailureDomainKey. A strict function of the reason, so it costs no series. Emitted rather than derived downstream: a component ahead of ateapi can report a reason this build rejects, which ExtractReason turns into Unknown, and a consumer matching on the reason would file it as infrastructure.
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.
const ( ConstraintNone = "none" ConstraintRequiredNodes = "required_nodes" ConstraintSelector = "selector" )
Values for SchedulingConstraintKey.
const ( ReasonCorruptedAssignment = string(ateerrors.ReasonCorruptedAssignment) ReasonWorkerReassigned = string(ateerrors.ReasonWorkerReassigned) ReasonWorkerPodGone = string(ateerrors.ReasonWorkerPodGone) ReasonUnknown = string(ateerrors.ReasonUnknown) )
Control-plane failure reasons for ate.actor.crashes metric.
const ( // RouterResumeNone indicates the actor was already running (steady-state route). RouterResumeNone = "none" // RouterResumeTriggered indicates this request won the singleflight lock and initiated cold activation. RouterResumeTriggered = "triggered" // RouterResumeJoined indicates this request parked on an in-flight singleflight resume. RouterResumeJoined = "joined" )
Values for RouterResumeKey.
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.
const ( WorkerStateIdle = "idle" WorkerStateAssigned = "assigned" )
Values for WorkerStateKey. Only idle and assigned are representable today; starting and unhealthy workers are not modeled in the cache.
const ( OperationCreate = "create" OperationResume = "resume" OperationSuspend = "suspend" OperationPause = "pause" OperationDelete = "delete" OperationUnknown = "unknown" )
Values for ActorOperationNameKey: the actor lifecycle operations ateapi serves.
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.
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.
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.
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.
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.
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.
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.
const SandboxClassUnknown = "unknown"
SandboxClassUnknown is the NormalizeSandboxClass fallback.
Variables ¶
var AllOperations = []string{ OperationCreate, OperationResume, OperationSuspend, OperationPause, OperationDelete, }
AllOperations lists all registered bounded actor lifecycle operations.
Functions ¶
func ActorAttributes ¶
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, reason 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 ¶
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 ¶
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 FailureAttributes ¶
FailureAttributes returns the reason and its domain together, so no producer can emit half the pair. Same rule as WorkerPoolAttributes.
func FailureDomain ¶
FailureDomain classifies a reason value. An unrecognized reason reports FailureDomainUnknown rather than infrastructure, so a taxonomy gap stays visible instead of inflating one side.
func FailureLogAttrs ¶
FailureLogAttrs is FailureAttributes for a slog record.
func FailureReason ¶
FailureReason classifies err onto the bounded ateerrors taxonomy, reading the wrapped Reason or the AIP-193 ErrorInfo detail. An error carrying neither reports ReasonUnknown rather than anything derived from its message, which is what keeps the label bounded.
func NormalizeOperationName ¶
NormalizeOperationName ensures op is one of the bounded lifecycle operations. Any unlisted or empty operation maps to OperationUnknown.
func NormalizeSandboxClass ¶
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 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 ¶
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.