Installing Requizon
Require the package, migrate, register the provider and narrow the gate. Recording starts on the next request.
Requizon is a Laravel package with its own routes, views and assets, in the same shape as Horizon. Installing it takes a Composer registry, a migration and one service provider. There is nothing to change in the code that makes HTTP calls: from the next request onwards, every call through Laravel's HTTP client is recorded.
Requirements#
- PHP 8.2 or newer
- Laravel 12 or 13
-
MySQL 8.0.20 or newer, or a compatible MariaDB. The hourly rollup uses
INSERT ... ON DUPLICATE KEY UPDATEwith row aliases, andrequizon:aggregaterefuses to run on any other driver. Recording itself is a plain insert, so the tables can live on a separate MySQL connection if your application's default database is something else. - The Laravel scheduler running on at least one server (
php artisan schedule:runevery minute)
1. Authenticate Composer#
Requizon is distributed through a private Composer registry. Your license key is issued through Anystack at checkout. Run this once on every machine that installs the package, including CI and build servers:
composer config --global --auth http-basic.requizon.composer.sh \
you@example.com \
YOUR-LICENSE-KEY
The username is the email address the license belongs to and the key is the password. On servers, supply the same
pair through COMPOSER_AUTH instead of committing an auth.json:
export COMPOSER_AUTH='{"http-basic":{"requizon.composer.sh":{"username":"you@example.com","password":"YOUR-LICENSE-KEY"}}}'
2. Require the package and migrate#
Add the registry to your application's composer.json:
{
"repositories": [
{ "type": "composer", "url": "https://requizon.composer.sh" }
]
}
Then require Requizon and run the migrations:
composer require boring-o11y/requizon
php artisan migrate
Package discovery registers Requizon's own service provider, which installs the recording middleware and the dashboard routes. The migrations create three tables:
| Table | Holds |
|---|---|
http_requests |
One row per transfer: API, host, path, status, duration, failure, redacted parameters, and the response body of a failure. Kept for 14 days by default. |
http_request_stats |
The hourly rollup the dashboard reads, keyed by API, host, path and hour. Kept for a year. |
http_request_outcome_stats |
The same buckets broken down by status code and failure type, for the responses charts. |
Both migrations skip a table that already exists. An application that was recording outbound calls into
http_requests before it adopted Requizon keeps its tables, and rolling back leaves them in place,
because Requizon only drops tables it created itself.
3. Publish the provider and define the gate#
php artisan vendor:publish --tag=requizon-provider
This writes app/Providers/RequizonServiceProvider.php. Register it in
bootstrap/providers.php, since publishing a file does not register it:
return [
App\Providers\AppServiceProvider::class,
App\Providers\RequizonServiceProvider::class,
];
Then narrow the gate to whoever should see your outbound traffic:
namespace App\Providers;
use BoringO11y\Requizon\RequizonApplicationServiceProvider;
use Illuminate\Support\Facades\Gate;
class RequizonServiceProvider extends RequizonApplicationServiceProvider
{
protected function gate(): void
{
Gate::define('viewRequizon', fn ($user) => $user->hasRole('administrator'));
}
}
In the local environment the dashboard is open to everyone. Everywhere else it asks the gate, and the
published gate returns false until you change it. A forgotten install is a dashboard nobody can reach,
which is the failure you want.
The same provider's boot() method is where Requizon's callbacks go: the
failure detector for APIs that answer
200 OK with an error, and the API and
path resolvers. The published stub has the detector
commented out, ready to fill in.
4. Make sure the scheduler runs#
Requizon registers two commands on Laravel's scheduler: requizon:aggregate every five minutes, which
builds the rollup the dashboard reads, and requizon:prune once a day. If
schedule:run is already in your crontab there is nothing to add. If it is not, calls are recorded but
the dashboard stays empty:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
To run the commands on your own schedule instead, see Retention and scheduling.
Checking it works#
php artisan about gains a Requizon section:
Requizon .............................................................
Instrumentation ................................... Laravel HTTP client
Dashboard ............................................... /requizon
Then make an outbound call:
php artisan tinker --execute="Http::get('https://api.github.com/zen')"
The overview at /requizon and its charts read the hourly rollup, and requizon:aggregate
only rolls up hours that have ended, so a call made now reaches the overview after the hour turns. The requests
list reads the detail table directly, so the call is visible straight away at
/requizon/api.github.com/requests. Unconfigured hosts name themselves; to group several hosts under
one vendor, see Naming APIs.
Before you deploy#
Recording covers every host your application calls, so read these two before the first production deploy rather than after:
- Ignore your telemetry backends. An exporter that ships logs or metrics over HTTP otherwise records its own traffic. See ignoring hosts.
- Know what is stored. Request parameters are redacted by name, but the response body of a failed call is kept as-is. See Redaction and stored data.
And in your own test suite, set REQUIZON_ENABLED=false in phpunit.xml unless you want every
Http::fake() response written to http_requests.