Skip to content

PHP SDK

The Nadi PHP SDK provides error monitoring for any PHP application. It's the foundation for framework-specific SDKs like Laravel and WordPress.

Requirements

  • PHP 8.1 or higher
  • Composer
  • JSON extension
  • cURL extension (for HTTP transporter)

Installation

Install via Composer:

bash
composer require nadi-pro/nadi-php

Quick Start

Initialize the Client

php
<?php

require_once 'vendor/autoload.php';

use Nadi\Client;

$client = new Client([
    'transporter' => 'file',
    'storagePath' => '/var/log/nadi',
]);

Capture Exceptions

php
try {
    // Your code
    throw new Exception('Something went wrong');
} catch (Exception $e) {
    $client->captureException($e);
}

Set Up Global Exception Handler

php
$client->registerErrorHandler();
$client->registerExceptionHandler();
$client->registerShutdownHandler();

Or use the convenience method:

php
$client->registerHandlers();

Configuration

Full Configuration Options

php
$client = new Client([
    // Transporter (recommended: file + Shipper)
    'transporter' => 'file',
    'storagePath' => '/var/log/nadi',

    // Optional
    'environment' => getenv('APP_ENV') ?: 'production',
    'release' => getenv('APP_VERSION'),

    // HTTP transporter settings (only needed with 'http' transporter)
    // 'transporter' => 'http',
    // 'apiKey' => getenv('NADI_API_KEY'),
    // 'appKey' => getenv('NADI_APP_KEY'),
    // 'endpoint' => 'https://nadi.pro/api/',
    // 'timeout' => 5,

    // Sampling
    'samplingRate' => 1.0,
    'samplingStrategy' => 'fixed_rate',

    // Context
    'tags' => [
        'server' => gethostname(),
    ],
    'extra' => [],

    // Filtering
    'scrubFields' => ['password', 'secret', 'token'],
]);

Credentials in nadi.yaml

API credentials (apiKey and appKey) are configured in nadi.yaml for the Shipper agent, not in your application code. See Shipper Configuration for details.

Environment Variables

VariableDescriptionDefault
NADI_ENVIRONMENTEnvironment nameproduction
NADI_STORAGE_PATHLog directory/var/log/nadi
NADI_TRANSPORTERTransport methodfile
NADI_SAMPLING_RATESampling rate (0-1)1.0

HTTP Transporter Only

NADI_API_KEY and NADI_APP_KEY environment variables are only needed when using the http transporter. For the recommended file transporter, credentials are configured in nadi.yaml for the Shipper agent.

Basic Usage

Capturing Exceptions

php
try {
    $this->processOrder($order);
} catch (Exception $e) {
    $client->captureException($e);
    throw $e; // Re-throw if needed
}

Capturing Messages

php
// Simple message
$client->captureMessage('User completed checkout');

// With level
$client->captureMessage('Low inventory warning', 'warning');

// With context
$client->captureMessage('Order processed', 'info', [
    'order_id' => $order->id,
    'total' => $order->total,
]);

Available levels: debug, info, warning, error, fatal

Adding Context

php
// Set user information
$client->setUser([
    'id' => $user->id,
    'email' => $user->email,
    'name' => $user->name,
]);

// Set tags
$client->setTag('subscription', 'premium');
$client->setTags([
    'feature' => 'checkout',
    'version' => '2.0',
]);

// Set extra data
$client->setExtra('cart_items', count($cart->items));
$client->setExtras([
    'cart_total' => $cart->total,
    'discount_code' => $cart->discountCode,
]);
php
// Add a breadcrumb
$client->addBreadcrumb('Page loaded', 'navigation', [
    'url' => $_SERVER['REQUEST_URI'],
]);

// Add before an error
$client->addBreadcrumb('Processing payment', 'action', [
    'gateway' => 'stripe',
    'amount' => $amount,
]);

try {
    $this->chargeCard($card, $amount);
} catch (PaymentException $e) {
    $client->captureException($e);
}

Event Lifecycle

Before Capture Hook

Modify events before they're captured:

php
$client->beforeCapture(function (array $event, array $hint) {
    // Add custom data
    $event['extra']['request_id'] = uniqid();

    // Filter certain events
    if ($hint['exception'] instanceof IgnorableException) {
        return null; // Don't capture
    }

    return $event;
});

After Capture Hook

Perform actions after capture:

php
$client->afterCapture(function (array $event) {
    // Log that event was captured
    error_log('Nadi: Captured event ' . $event['event_id']);
});

Scopes

Global Scope

Set context for all events:

php
$client->configureScope(function ($scope) {
    $scope->setTag('server', gethostname());
    $scope->setUser(['id' => $userId]);
});

Temporary Scope

Set context for a specific operation:

php
$client->withScope(function ($scope) use ($client, $order) {
    $scope->setTag('operation', 'order_processing');
    $scope->setExtra('order_id', $order->id);

    $client->captureMessage('Processing order');
});
// Scope is cleared after the closure

Integration Examples

Vanilla PHP

php
<?php

require_once 'vendor/autoload.php';

use Nadi\Client;

$nadi = new Client([
    'transporter' => 'file',
    'storagePath' => '/var/log/nadi',
]);

$nadi->registerHandlers();

// Your application code

With a Router

php
$router->setErrorHandler(function (Throwable $e) use ($nadi) {
    $nadi->captureException($e);
    // Display error page
});

In a Controller

php
class PaymentController
{
    private Client $nadi;

    public function __construct(Client $nadi)
    {
        $this->nadi = $nadi;
    }

    public function charge(Request $request)
    {
        try {
            return $this->processPayment($request);
        } catch (PaymentException $e) {
            $this->nadi->captureException($e, [
                'extra' => ['request_id' => $request->id],
            ]);
            throw $e;
        }
    }
}

What's Captured

Each error event includes:

DataDescription
ExceptionType, message, code
Stack TraceFull trace with file/line info
ContextTags, extra data, user
RequestURL, method, headers (if available)
ServerPHP version, OS, hostname
TimestampWhen the error occurred

Next Steps

Released under the MIT License.