Overview
- System metrics: Node-level statistics via
ActorSystem.Metric. - Per-actor metrics: Actor-level statistics via
pid.Metric. - Event stream: System and cluster events (lifecycle, membership, dead letters).
- OpenTelemetry: Metrics exported when
WithMetricsis used. - Tracing: Zero-instrumentation actor traces via goakt-ebpf.
System metrics
ActorSystem.Metric(ctx) returns a *Metric struct with node-level statistics. Returns nil when the actor system is
not started.
- DeadlettersCount: Type:
int64. Description: Total messages dropped to dead letters on this node. - ActorsCount: Type:
int64. Description: Total number of live actors on this node. - Uptime: Type:
int64. Description: Seconds since the actor system started. - MemoryUsed: Type:
uint64. Description: Used memory in bytes (host). - MemorySize: Type:
uint64. Description: Total memory in bytes (host). - MemoryAvailable: Type:
uint64. Description: Available memory in bytes (host).
System metrics
Per-actor metrics
pid.Metric(ctx) returns an *ActorMetric struct with actor-level statistics. Returns nil when the actor is not
running. For remote actors, metrics are fetched via remoting; the same fields are available.
- ProcessedCount: Type:
uint64. Description: Messages handed to the handler since the last restart (excludes PostStart; a message is counted when its handling starts, failed ones included). - ChidrenCount: Type:
uint64. Description: Number of direct child actors. - RestartCount: Type:
uint64. Description: Cumulative restarts, by supervision or byRestart/ReSpawn. - Uptime: Type:
int64. Description: Seconds since the actor, or its latest incarnation, started. - LatestProcessedDuration: Type:
time.Duration. Description: Time elapsed since the most recent message started processing (how long the actor has been idle). - StashSize: Type:
uint64. Description: Current number of stashed messages. - DeadlettersCount: Type:
uint64. Description: Messages addressed to this actor that went to dead letters, including those it rejected withUnhandled. - FailureCount: Type:
uint64. Description: Cumulative failures the supervisor acted on (suspensions and resumed failures); survives restarts. - ReinstateCount: Type:
uint64. Description: Cumulative reinstatements (suspended → resumed). - UnhandledCount: Type:
uint64. Description: Cumulative messages the actor rejected withReceiveContext.Unhandled.
Per-actor metrics
Event stream
The event stream publishes system and cluster events (lifecycle, membership, dead letters). It is separate from application-level PubSub. See Event Streams for full documentation.Event stream
ActorStarted, ActorStopped, ActorChildCreated, ActorPassivated, ActorRestarted, ActorSuspended,
ActorReinstated, Deadletter, NodeJoined, NodeLeft.
Dead letters
Messages sent to stopped or non-existent actors are captured by the dead-letter actor and published to the event stream. TheDeadletter payload includes sender, receiver, message, and reason. Subscribe to the event stream to observe or log
dead letters.
OpenTelemetry
WhenWithMetrics() is passed at actor system creation, the framework registers OpenTelemetry observable counters. You
must initialize the OpenTelemetry SDK (MeterProvider, exporter) before starting the actor system; otherwise metrics are
not exported.
System-level instruments
Attributes:actor.system.
- actorsystem.deadletters.count: Type: Int64ObservableCounter. Description: Total dead letters on this node.
- actorsystem.actors.count: Type: Int64ObservableGauge. Description: Live actors on this node.
- actorsystem.grains.count: Type: Int64ObservableGauge. Description: Grains activated on this node.
- actorsystem.uptime: Type: Int64ObservableGauge (s). Description: Actor system uptime in seconds.
- actorsystem.peers.count: Type: Int64ObservableGauge. Description: Connected peers (cluster mode).
Scheduler instruments
Attributes:actor.system.
- scheduler.scheduled.count: Type: Int64ObservableCounter. Description: Messages successfully scheduled for later delivery.
- scheduler.cancelled.count: Type: Int64ObservableCounter. Description: Scheduled messages successfully cancelled.
Cluster membership instruments
Attributes:actor.system. Registered only when the actor system runs in cluster mode.
- cluster.members.joined.count: Type: Int64ObservableCounter. Description: Members this node has seen join the cluster.
- cluster.members.left.count: Type: Int64ObservableCounter. Description: Members this node has seen leave the cluster.
Each node reports the churn it observed, so a three node cluster reports a single join on three series. Rate either
counter to alert on membership instability;
actorsystem.peers.count gives the current membership the churn resolves
to.Actor lifecycle instruments
Attributes:actor.system, actor.kind.
These three totals count events that remove an actor from the tree, so they are reported by the actor system rather than
by a PID, one series per actor kind. System actors (guardians, the dead-letter actor, topic actors) are excluded.
- actor.spawned.count: Type: Int64ObservableCounter. Description: Actors of this kind whose spawn completed.
- actor.stopped.count: Type: Int64ObservableCounter. Description: Actors of this kind that were shut down.
- actor.passivated.count: Type: Int64ObservableCounter. Description: Actors of this kind that passivated.
actor.stopped.count counts terminal stops only. The teardown a restart performs before re-initializing an actor is
reported by actor.restart.count, and a passivation is reported by actor.passivated.count, so no lifecycle event is
counted twice.Per-actor instruments
Attributes:actor.system, actor.name, actor.kind, actor.address by default, or actor.system and actor.kind
under WithLowCardinalityMetrics.
Per-actor metrics are collected by a single callback that walks the actor tree on every scrape, so the number of meter
registrations stays constant regardless of the actor population. An actor appears in scrapes once it is running and has
processed its PostStart message; suspended, stopping, and passivating actors are omitted until they are running again.
- actor.children.count: Type: Int64ObservableGauge. Description: Current child actors.
- actor.stash.size: Type: Int64ObservableGauge. Description: Messages stashed.
- actor.deadletters.count: Type: Int64ObservableCounter. Description: Dead letters addressed to this actor, per message type.
- actor.restart.count: Type: Int64ObservableCounter. Description: Restarts.
- actor.last.received.duration: Type: Int64ObservableGauge (ms). Description: Time since the last message started processing.
- actor.processed.count: Type: Int64ObservableCounter. Description: Messages processed.
- actor.uptime: Type: Int64ObservableGauge (s). Description: Actor uptime in seconds.
- actor.failure.count: Type: Int64ObservableCounter. Description: Failures.
- actor.reinstate.count: Type: Int64ObservableCounter. Description: Reinstatements.
- actor.unhandled.count: Type: Int64ObservableCounter. Description: Messages rejected with
Unhandled. - actor.mailbox.size: Type: Int64ObservableGauge. Description: Messages waiting in the mailbox.
actor.deadletters.count carries one extra attribute, message.type, naming the type of the dropped message, and is
reported once per message type the actor dropped. An actor that has dropped nothing reports a single zero without the
attribute. To get an actor’s total across all types, sum the series:
Per-actor instruments
actor.mailbox.size is the one instrument reported outside the gate described above. A suspended or restarting actor
still emits it, and only it, because a backlog piling up behind an actor that has stopped consuming is exactly the
condition the metric exists to expose. It counts user messages that are enqueued and not yet dispatched, so it
excludes the message being processed, the stashed messages reported by actor.stash.size, and the internal
control-plane queue.Average time a message waits in the mailbox
GoAkt records no mailbox wait histogram: measuring one would mean timestamping every message on the message path. The average wait follows from Little’s law instead, dividing the queue length by the rate at which the actor drains it:Average time a message waits in the mailbox
Reporting one series per actor kind
By default each instrument above produces one time series per live actor. That is precise, but the series count grows with the actor population, which becomes expensive to store and query once a system runs thousands of actors.WithLowCardinalityMetrics reports the same instruments once per actor kind instead. The scrape aggregates the live
actors of each kind and observes each instrument once, carrying only actor.system and actor.kind:
Reporting one series per actor kind
- actor.children.count: Reduction: sum. Meaning per kind: Children held by actors of this kind.
- actor.stash.size: Reduction: sum. Meaning per kind: Stashed messages across the kind.
- actor.restart.count: Reduction: sum. Meaning per kind: Restarts across the kind.
- actor.processed.count: Reduction: sum. Meaning per kind: Messages processed by the kind.
- actor.failure.count: Reduction: sum. Meaning per kind: Failures across the kind.
- actor.reinstate.count: Reduction: sum. Meaning per kind: Reinstatements across the kind.
- actor.unhandled.count: Reduction: sum. Meaning per kind: Unhandled messages across the kind.
- actor.deadletters.count: Reduction: sum per kind and message type. Meaning per kind: Drops by the kind, still broken down by type.
- actor.uptime: Reduction: max. Meaning per kind: Age of the oldest live actor of the kind.
- actor.last.received.duration: Reduction: min. Meaning per kind: Time since the kind last processed a message.
- actor.mailbox.size: Reduction: sum. Meaning per kind: Messages waiting across the kind.
The two time gauges cannot be summed. The maximum uptime answers how long the kind has been running, and the minimum
time since the last received message answers whether the kind is still active.
PostStart contribute, so a kind whose actors are
all suspended drops out of the series until one resumes. actor.mailbox.size is the exception it is in the default mode
too: every actor of the kind adds its backlog to the sum whatever its lifecycle state, so a kind whose actors are all
suspended keeps reporting that one instrument while the others go quiet. A kind that has dropped nothing reports a
single zero for actor.deadletters.count without the message.type attribute, exactly as an actor does in the default
mode.
The system-level instruments and the actor lifecycle instruments already report one series per system and per kind, so
they are identical in both modes.
Example
Example