actorevent

package
v0.4.0 Latest Latest
Warning

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

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

Documentation

Overview

Package actorevent emits the actor events: the lifecycle events and the usage samples. Log writes each record as an OTLP event when the logs exporter is on, and on stdout otherwise, or in both places when asked to. Both forms are built from the same call, so they cannot drift. Ordinary component logs stay on stdout.

This is not an slog bridge. A bridge would put every component record on the wire, cannot set EventName, and would loop, because serverboot routes OTel SDK errors through slog.

serverboot.InitLogging pairs this with a batching processor. These records sit on the actor resume path, so exporting inside Log would put a blocking gRPC call there and make a slow collector look like control-plane latency.

Index

Constants

View Source
const ScopeName = "github.com/agent-substrate/substrate/internal/actorevent"

ScopeName is the instrumentation scope of every actor event. A consumer selects a stream by event name.

Variables

View Source
var (
	StateChanged = Event{
		Name:     "ate.actor.state_changed",
		Body:     "Actor state changed",
		Severity: log.SeverityInfo,
		Keys: append(append([]string{}, identityKeys...),
			string(ateattr.ActorOperationNameKey),
			string(ateattr.ActorStateKey)),
	}

	Crashed = Event{
		Name:     "ate.actor.crashed",
		Body:     "Actor crashed",
		Severity: log.SeverityError,
		Keys: append(append([]string{}, identityKeys...),
			string(ateattr.ActorOperationNameKey),
			string(ateattr.ActorStateKey)),
	}

	UsageSampled = Event{
		Name:     "ate.actor.usage_sampled",
		Body:     "Actor usage sampled",
		Severity: log.SeverityInfo,
		Keys: append(append([]string{}, identityKeys...),
			string(ateattr.WorkerPoolNamespaceKey),
			string(ateattr.WorkerPoolNameKey),
			string(ateattr.SandboxClassKey),
			string(ateattr.StatsSourceKey),
			string(ateattr.StatsKindKey),
			string(ateattr.ActorEpochKey)),

		Conditional: []string{
			string(ateattr.StatsMemoryUsageKey),
			string(ateattr.StatsMemoryPeakKey),
			string(ateattr.StatsMemoryWorkingSetKey),
			string(ateattr.StatsCPUTimeKey),
		},
	}
)

Three names. A crash is its own because it has a different severity; there is no name per state, because ate.actor.state already says which transition happened. UsageSampled is the ateoms' measurement record.

Functions

func BuildRecord

func BuildRecord(ev Event, t time.Time, attrs []slog.Attr) log.Record

BuildRecord turns the stdout record into its OTLP form. Attributes carry everything machine-readable, so the body stays the display string.

It sets no trace context: the SDK lifts that from ctx onto the record's own TraceId/SpanId fields.

func Log

func Log(ctx context.Context, ev Event, attrs []slog.Attr)

Log records ev through the process-wide provider.

func LogAt added in v0.3.0

func LogAt(ctx context.Context, ev Event, t time.Time, attrs []slog.Attr)

LogAt records ev at t through the process-wide provider.

func SetConsole added in v0.4.0

func SetConsole(on bool)

SetConsole sets whether an actor event's stdout record is also written when its OTLP event is: OTEL_LOGS_EXPORTER=otlp,console. Call it once at startup.

Types

type AsyncHandler added in v0.4.0

type AsyncHandler struct {
	// contains filtered or unexported fields
}

AsyncHandler writes records through another handler from its own goroutine, so a slow stdout cannot block the caller. When the queue is full it drops the record and counts it, and the writer reports the count through that same handler once it catches up, so a level that silences the default logger cannot hide the loss.

func NewAsyncHandler added in v0.4.0

func NewAsyncHandler(inner slog.Handler, capacity int) *AsyncHandler

NewAsyncHandler starts the writer. capacity is how many records may wait.

func (*AsyncHandler) Close added in v0.4.0

func (h *AsyncHandler) Close()

Close writes the queued records and stops the writer. A record handled after Close is written on the caller's goroutine.

func (*AsyncHandler) Enabled added in v0.4.0

func (h *AsyncHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports the inner handler's level.

func (*AsyncHandler) Handle added in v0.4.0

func (h *AsyncHandler) Handle(ctx context.Context, r slog.Record) error

Handle queues r and returns at once.

func (*AsyncHandler) WithAttrs added in v0.4.0

func (h *AsyncHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs shares the queue with h.

func (*AsyncHandler) WithGroup added in v0.4.0

func (h *AsyncHandler) WithGroup(name string) slog.Handler

WithGroup shares the queue with h.

type Emitter

type Emitter struct {
	// contains filtered or unexported fields
}

Emitter writes the OTLP event through one log.Logger. Tests construct one directly, so emit needs no global provider and can run in parallel.

func NewEmitter

func NewEmitter(lp log.LoggerProvider) *Emitter

NewEmitter writes under ScopeName, with the stdout record through slog.Default().

func NewEmitterTo added in v0.4.0

func NewEmitterTo(lp log.LoggerProvider, stdout slog.Handler) *Emitter

NewEmitterTo is NewEmitter with the stdout record through stdout, for a stream whose stdout record must not follow --log-level or block the caller.

func (*Emitter) Log

func (e *Emitter) Log(ctx context.Context, ev Event, attrs []slog.Attr)

Log is LogAt with time.Now(), for an event that happens as it is written.

func (*Emitter) LogAt added in v0.3.0

func (e *Emitter) LogAt(ctx context.Context, ev Event, t time.Time, attrs []slog.Attr)

LogAt writes ev as an OTLP event when the logs exporter takes it, and on stdout otherwise, or both with SetConsole(true). t is when the thing happened, such as a usage sample's read time, so the stdout record is built here rather than through slog.LogAttrs, which would take its own reading. With slog.Default() as the stdout handler, it follows --log-level.

type Event

type Event struct {
	Name        string
	Body        string
	Severity    log.Severity
	Keys        []string
	Conditional []string
}

Event is one name in the closed vocabulary. Name is the LogRecord's own event name field, not an attribute. Body and Severity live here rather than at a call site, so the stdout and OTLP forms of a record cannot differ.

Keys is the attribute set the name promises on every record. Conditional holds the keys that are present exactly when the registry's condition holds, and absent otherwise: absence means not measured, zero means measured as zero. The tests hold both lists in step with the registry, and a caller cannot widen the record.

func (Event) Level

func (ev Event) Level() slog.Level

Level is the stdout level for this event. slog has four levels to OTel's twenty-four, so a sub-level collapses onto the range it sits in.

Jump to

Keyboard shortcuts

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