Requizon

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 UPDATE with row aliases, and requizon:aggregate refuses 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:run every 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 provider does two jobs

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.

Common questions

Do I have to change my HTTP calls to use Requizon?

No. Requizon installs its recording middleware on Laravel's HTTP client factory, so every call made through the Http facade is recorded, Http::pool() included. There is nothing to add at the call site.

Why does the Requizon dashboard return 403 in production?

Outside the local environment the dashboard asks the viewRequizon gate, and the gate denies everyone until you override it in the published App\Providers\RequizonServiceProvider. Also check that the provider is registered in bootstrap/providers.php: without it no gate is defined and the dashboard stays local-only.

Why is the Requizon dashboard empty after installing?

The dashboard reads an hourly rollup that requizon:aggregate builds every five minutes through Laravel's scheduler. If schedule:run is not running on the server, calls are recorded but never aggregated, so the overview shows nothing. The aggregate also only rolls up hours that have ended, so a fresh install shows its first calls on the overview after the hour turns. The requests list for an API reads the detail table and shows them immediately.

Install Requizon today.

Checkout ends with your license key, and the installation guide takes it from there.