Skip to main content

Monitor

Monitor gives a Laravel application control points: the operations where a failure matters, declared in code as a contract. A control point says what it is called, which domain it belongs to, which failures it expects and what to return instead, which policies bound it, which limits it should stay within, and who is told when something it did not expect gets out. Every run ends in one outcome, succeeded, recovered, escalated or refused, and every transition is written as a record with the same fields.

Because the declaration is data, the rest of the package can read it: monitor:points lists every point and checks the declarations in CI, Monitor::fake() asserts on outcomes by name, an optional store keeps outcomes queryable, and an MCP server lets an agent ask the application what its control points are and what happened at them. The same convention ships as guidelines for Laravel Boost, so an agent adding a critical operation is told once, by the package.

// A critical operation as a try/catch: no name, no attempt count, no trace, null means declined.
try {
DB::beginTransaction();
$charge = $this->stripe->charge($amount);
DB::commit();
} catch (CardDeclined $e) {
DB::rollBack();
Log::warning('card declined: '.$e->getMessage());
return null;
} catch (\Throwable $e) {
DB::rollBack();
Log::error($e);
throw $e;
}

// The same operation as a control point.
return Monitor::control('payment.charge', $this)
->with(['invoice' => $invoice->id, 'amount' => $amount])
->profile('external') // retry, breaker and duration limit from config
->transaction(retries: 2)
->ensure(fn (ChargeResult $r): bool => $r->settled, 'charge must be settled')
->recover(CardDeclined::class, fn (CardDeclined $e) => ChargeResult::declined($e->code))
->escalate(PagePayments::class)
->run(fn () => $this->stripe->charge($amount));

The declaration says what the operation tolerates, what it tries again, when it stops calling the gateway, what counts as success, and who is paged. It produces one log record per transition with point, domain, status, run_id and trace_id as fields.