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
  • One of MySQL 8.0.19+, MariaDB 10.5+, PostgreSQL 9.5+ or SQLite 3.24+. The hourly rollup upserts its buckets, and those are the versions where each database got an upsert. The tables can live on a separate connection if you would rather keep them out of your application's database.
  • 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
requizon_http_requests One row per transfer: API, host, path, status, duration, failure, the redacted query and body parameters, the headers you have asked for, and the response body of a failure. Kept for 14 days by default.
requizon_http_request_stats The hourly rollup the dashboard reads, keyed by API, host, path and hour. Kept for a year.
requizon_http_request_outcome_stats The same buckets broken down by status code and failure type, for the responses charts.

The requizon_ prefix is there so none of the three can collide with a table your application already owns. Rolling the migrations back drops those three and nothing else.

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 still recorded and shown, but the dashboard slows down as the unrolled rows pile up, and nothing is ever pruned:

* * * * * 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')"

It is on the overview at /requizon straight away, counted from the detail rows until the next requizon:aggregate rolls it up, and in the requests list 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. Parameters and headers are redacted by name, and the response body of a failed call is redacted when Requizon can parse it into names and stored as it came when it cannot. 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 requizon_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?

Calls appear as soon as they are recorded, so an empty dashboard means nothing has been recorded. Check that the call went through Laravel's HTTP client rather than an SDK with its own Guzzle client, that its host is not in ignore_hosts, and that REQUIZON_ENABLED is not false. The scheduler is not needed to see calls: the dashboard counts whatever requizon:aggregate has not rolled up yet straight from the detail rows, though without schedule:run it slows down as those rows pile up.

Install Requizon today.

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