Naijacloud
Docs

PHP and Laravel

On Laravel, install the package and add your DSN to .env; there is nothing else to register. Any other PHP app, from Symfony to WordPress, calls init() once in its front controller.

6 min read

Laravel

Install

Install
bash
composer require naijacloud/argus-laravel

Laravel 10 to 13, on a patched PHP: 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer. Those releases fix php2shell (CVE-2026-109618 and CVE-2026-109619), and Composer refuses older ones. The package is discovered automatically: there is no provider to register.

Set up

In your .env file:

.env
bash
ARGUS_DSN=https://<public key>@argus-in.naijacloud.com/<project id>

A Naijacloud service gets the DSN from its Send errors to Argus switch, so there you can leave .env alone. Without a DSN the package does nothing, so local development and CI need no changes.

Send a test event

Send a test event
bash
php artisan argus:test

It sends one test event and says whether Argus accepted it, or why not. Use --dsn= to test a different DSN. If your config is cached, run php artisan config:clear first.

What it captures

With only the DSN set:

  • Exceptions, through Laravel's own handler: whatever Laravel reports reaches Argus, and whatever it doesn't (validation errors, 404s, your dontReport list) doesn't. report($e) works too.
  • Each error's context: the route (GET /orders/{order}), the signed-in user's id, the URL without its query string, and breadcrumbs of the queries, logs and HTTP calls before it.
  • Request traces, with a child span for each database query (with ? placeholders, never the bound values) and each Http:: call.
  • Queued jobs, each in a span that continues the trace of the request that dispatched it. A failed job is reported with its class, queue and connection.

Under PHP-FPM, everything is sent after the response has reached the visitor, within a 2-second budget. Octane and queue workers send after each request or job, and start each one with a clean scope.

Logs

The argus log channel is defined for you. Add it to your stack in .env:

.env
bash
LOG_STACK=single,argus

Every Log::info(), Log::warning() and so on then also reaches Argus Logs, with its context as attributes. On Laravel 10, or with your own config/logging.php, add 'argus' to your stack channel's channels. ARGUS_LOG_LEVEL sets the lowest level sent (default debug).

Scheduled tasks

Create a cron monitor in Argus, then name its slug on the task:

routes/console.php
php
Schedule::command('invoices:send')->daily()->argusMonitor('nightly-invoices');

Argus hears when the task starts, and whether it succeeded or failed, with its exit code.

In your code

The Argus facade covers errors, metrics, traces, cron check-ins and flags:

Facade
php
use NaijaCloud\Argus\Laravel\Facades\Argus; Argus::captureException($e, ['tags' => ['provider' => 'paystack']]); Argus::captureMessage('Webhook signature mismatch', 'warning'); Argus::setTag('tenant', $tenant->slug); Argus::count('orders.placed', 1, ['method' => 'card']); Argus::distribution('checkout.ms', $elapsedMs, [], 'ms'); Argus::trace('charge card', fn () => $paystack->charge($order)); Argus::withMonitor('import-rates', fn () => $this->importRates()); if (Argus::isOn('new-checkout', (string) $user->id)) { // … }

Release, environment and privacy

.envDefault
ARGUS_RELEASESENTRY_RELEASE
ARGUS_ENVIRONMENTSENTRY_ENVIRONMENT, else APP_ENV
ARGUS_SERVICE_NAMEAPP_NAME
ARGUS_TRACES_SAMPLE_RATE1
ARGUS_SEND_DEFAULT_PIIfalse: only the user's id is sent

Passwords, tokens, secrets, card numbers, BVNs, Authorization headers and JWTs become [Filtered]; cookies, request bodies and query strings are never sent. To change or drop events, publish the config with php artisan vendor:publish --tag=argus-config and set before_send to a [class, method] pair, so config:cache still works:

config/argus.php
php
'before_send' => [App\Support\ArgusFilters::class, 'beforeSend'],

Already on Sentry

Keep sentry/sentry-laravel. In your .env file, change one line:

.env
bash
SENTRY_LARAVEL_DSN=https://<public key>@argus-in.naijacloud.com/<project id>

Any PHP app

Install

Install
bash
composer require naijacloud/argus

A patched PHP, as above: 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer. It uses ext-curl when it's loaded, and PHP's own https:// streams when it isn't.

Set up

As early as possible in your front controller, such as public/index.php:

public/index.php
php
require __DIR__ . '/vendor/autoload.php'; \NaijaCloud\Argus\init([ 'dsn' => 'https://<public key>@argus-in.naijacloud.com/<project id>', // or set ARGUS_DSN 'release' => '1.4.2', ]);

init() with no dsn reads ARGUS_DSN, then SENTRY_DSN.

Send a test event

Send a test event
php
\NaijaCloud\Argus\init(['debug' => true]); \NaijaCloud\Argus\Argus::captureMessage('Argus test event'); var_dump(\NaijaCloud\Argus\Argus::flush()); // true when Argus accepted it

With debug on, a refused key or a rate limit is written to the PHP error log.

What it captures

  • Uncaught exceptions, as fatal. PHP still prints its usual message and exits as it would without Argus.
  • PHP warnings and errors, once per file and line. Calls silenced with @ are skipped; deprecations and notices become breadcrumbs.
  • Fatal errors at shutdown, including running out of memory.
  • Your own handlers are kept. Argus calls them after it records the error.

Everything is queued while the request runs and sent at shutdown, after fastcgi_finish_request() when PHP-FPM provides it, so the visitor never waits. Long-running workers should call Argus::flush() and Argus::clearScope() after each job.

Errors, logs, metrics and traces

Errors, logs, metrics and traces
php
use NaijaCloud\Argus\Argus; use NaijaCloud\Argus\Span; try { $paystack->charge($order); } catch (\Throwable $e) { Argus::captureException($e, ['tags' => ['provider' => 'paystack']]); } Argus::setUser(['id' => $user->id]); Argus::logs()->info('order placed', ['orderId' => 'ord_81', 'total' => 18500]); Argus::metrics()->count('orders.placed', 1, ['method' => 'card']); Argus::metrics()->gauge('queue.depth', count($jobs)); Argus::trace('charge card', function (Span $span) use ($order, $paystack) { $span->setAttribute('provider', 'paystack'); return $paystack->charge($order); });

Using PSR-3 or Monolog? new \NaijaCloud\Argus\Log\PsrLogger() and new \NaijaCloud\Argus\Log\MonologHandler() write to Argus Logs. To continue a trace from an incoming request, call Argus::continueTrace($_SERVER['HTTP_TRACEPARENT'] ?? null), and send Argus::traceparent() as a traceparent header on outgoing calls.

Cron check-ins and feature flags

Cron check-ins and feature flags
php
// Create the monitor in Argus first. Argus::cron()->withMonitor('nightly-invoices', fn () => sendInvoices()); // or by hand: Argus::cron()->checkIn('nightly-invoices', 'start'); Argus::cron()->checkIn('nightly-invoices', 'ok'); // or 'error', or an exit code if (Argus::flags()->isOn('new-checkout', (string) $user->id)) { // … } $theme = Argus::flags()->variant('theme', (string) $user->id, 'light');

Check-ins are sent immediately, not at shutdown. A flag check waits at most flags_timeout_ms (1 second); answers are cached for 30 seconds per user, and if Argus can't be reached you get the fallback you passed.

Release, environment and privacy

init() reads ARGUS_RELEASE and ARGUS_ENVIRONMENT, then SENTRY_RELEASE and SENTRY_ENVIRONMENT; the environment is production when none is set. The same filtering as on Laravel is on by default, and the user's IP address is not sent unless you set 'send_default_pii' => true. before_send changes an event, or drops it when it returns null:

before_send
php
\NaijaCloud\Argus\init([ 'before_send' => fn (array $event): ?array => str_contains($event['message'] ?? '', 'healthcheck') ? null : $event, ]);

Already on Sentry

Keep sentry/sentry. In your \Sentry\init call, change the dsn line:

\Sentry\init
php
'dsn' => 'https://<public key>@argus-in.naijacloud.com/<project id>',