Skip to main content

Metrics

Nexus does not ship a Prometheus endpoint or a metrics registry. It accepts a PSR-14 EventDispatcherInterface at boot and fires events as actors start, stop, fail, and process messages — your application code subscribes to those events and publishes counters however it likes.

What Nexus fires​

ActorSystem::create() accepts an optional EventDispatcherInterface. If you pass one, Nexus dispatches events to it. If you pass null, the default NullDispatcher is used and nothing is emitted.

Core actor system events​

The actor cell dispatches no structured events today — lifecycle transitions (start, stop, failure) are delivered as Signal values to the actor's own onSignal() handler, not to the PSR-14 dispatcher. Use the signal handler to emit your own metrics:

src/Actors/InstrumentedActor.php
use Monadial\Nexus\Core\Actor\Behavior;
use Monadial\Nexus\Core\Lifecycle\PreStart;
use Monadial\Nexus\Core\Lifecycle\PostStop;

$behavior = Behavior::receive(
static fn($ctx, $msg) => Behavior::same(),
)->onSignal(static function ($ctx, $signal) use ($metrics): Behavior {
if ($signal instanceof PreStart) {
$metrics->increment('actor.started');
}

if ($signal instanceof PostStop) {
$metrics->increment('actor.stopped');
}

return Behavior::same();
});

Persistence metrics​

nexus-persistence does not fire PSR-14 events. Persistence metrics — events persisted, recovery duration, snapshot taken — must be tracked inside the actor itself by wrapping the effect chain with a side-effect callback:

src/Actors/OrderActor.php
use Monadial\Nexus\Persistence\EventSourced\Effect;

// Inside the command handler:
return Effect::persist($orderPlaced)
->thenRun(static function ($state) use ($metrics): void {
$metrics->increment('persistence.events_persisted_total');
});

Prometheus exporter recipe​

Nexus has no built-in Prometheus integration. The recipe below is entirely application code — nothing is part of the framework.

Step 1 — Install a Prometheus client:

terminal
composer require promphp/prometheus_client_php

Step 2 — Wire a listener at boot:

src/Bootstrap/MetricsBootstrap.php
use Prometheus\CollectorRegistry;
use Prometheus\Storage\InMemory;
use Symfony\Component\EventDispatcher\EventDispatcher;

$registry = new CollectorRegistry(new InMemory());
$counter = $registry->getOrRegisterCounter(
'nexus', 'messages_processed_total', 'Messages processed', ['actor'],
);
$dispatcher = new EventDispatcher();

$system = ActorSystem::create(
'my-app',
new SwooleRuntime(),
eventDispatcher: $dispatcher,
);

Step 3 — Expose /metrics via a route:

src/Http/MetricsController.php
use Prometheus\RenderTextFormat;

$app->get('/metrics', static function () use ($registry): Response {
$renderer = new RenderTextFormat();
$output = $renderer->render($registry->getMetricFamilySamples());

return new Response(200, ['Content-Type' => RenderTextFormat::MIME_TYPE], $output);
});

What to instrument​

Signal / eventSuggested counter / gauge
PreStartactor.started_total
PostStopactor.stopped_total
ChildFailedactor.failures_total{actor, exception}
Terminated (death watch)actor.terminated_total
DeadLetter receivedactor.dead_letters_total
Effect::persist()->thenRun()persistence.events_persisted_total
Mailbox overflow (catch in handler)mailbox.overflow_total{actor}

Honest assessment​

The PSR-14 hook is the correct extension point, but the existing event surface is limited: mailbox metrics require in-handler counters, and there is no per-actor message-rate counter emitted by the framework. Contributions to nexus-core that add structured events are welcome; see Contributing.

See also​