Skip to content

Context & Metadata ​

Enrich error reports with contextual information to make debugging easier.

Overview ​

Context provides additional information about the state of your application when an error occurred. This includes:

  • Tags - Key-value pairs for filtering and searching
  • Extra - Arbitrary additional data
  • User - Information about the affected user
  • Request - HTTP request details

Tags ​

Tags are indexed key-value pairs that you can use to filter and search errors in the dashboard.

Setting Tags ​

php
use Nadi\Laravel\Facades\Nadi;

// Set a single tag
Nadi::setTag('subscription', 'premium');

// Set multiple tags
Nadi::setTags([
    'feature' => 'checkout',
    'region' => 'us-east',
    'version' => '2.1.0',
]);

Default Tags ​

Set tags that apply to all events in config/nadi.php:

php
'tags' => [
    'server' => gethostname(),
    'version' => config('app.version'),
],

Common Tag Patterns ​

php
// Feature flags
Nadi::setTag('feature_flag', 'new_checkout_enabled');

// A/B testing
Nadi::setTag('experiment', 'pricing_v2');

// Tenant/customer identification
Nadi::setTag('tenant_id', $tenant->id);

// API version
Nadi::setTag('api_version', 'v2');

Tag Best Practices

  • Keep tag names consistent (use snake_case)
  • Use tags for values you'll filter by
  • Avoid high-cardinality values (like user IDs)
  • Keep tag values short

Extra Data ​

Extra data contains arbitrary information attached to events. Unlike tags, extra data is not indexed but provides detailed context.

Setting Extra Data ​

php
use Nadi\Laravel\Facades\Nadi;

// Set a single extra value
Nadi::setExtra('order_id', $order->id);

// Set multiple extra values
Nadi::setExtras([
    'cart_items' => $cart->items->count(),
    'cart_total' => $cart->total(),
    'payment_method' => $order->payment_method,
]);

Complex Data Structures ​

php
Nadi::setExtra('order_details', [
    'id' => $order->id,
    'items' => $order->items->map(fn($item) => [
        'product_id' => $item->product_id,
        'quantity' => $item->quantity,
        'price' => $item->price,
    ])->toArray(),
    'shipping' => [
        'method' => $order->shipping_method,
        'address' => $order->shipping_address,
    ],
]);

Default Extra Data ​

Set extra data for all events in config/nadi.php:

php
'extra' => [
    'deployment_id' => env('DEPLOYMENT_ID'),
],

Request Context ​

The SDK automatically captures request information:

DataDescription
URLFull request URL
MethodHTTP method (GET, POST, etc.)
HeadersRequest headers (filtered)
QueryQuery string parameters
BodyRequest body (filtered)
IPClient IP address

Configuring Request Capture ​

php
// config/nadi.php
'capture_request_body' => true,
'max_request_body_size' => 10240, // 10KB

'scrub_fields' => [
    'password',
    'password_confirmation',
    'credit_card',
    'cvv',
],

'scrub_headers' => [
    'Authorization',
    'Cookie',
],

Adding Custom Request Data ​

php
use Nadi\Laravel\Facades\Nadi;

Nadi::setRequestContext([
    'custom_header' => request()->header('X-Custom-Header'),
    'trace_id' => request()->header('X-Trace-ID'),
]);

Scopes ​

Scopes allow you to set context that applies to all events within a certain scope.

Global Scope ​

Context set globally applies to all subsequent events:

php
use Nadi\Laravel\Facades\Nadi;

// In a middleware or service provider
Nadi::configureScope(function ($scope) {
    $scope->setTag('request_id', request()->id());
    $scope->setExtra('session_id', session()->getId());
});

Temporary Scope ​

Set context for a specific operation:

php
use Nadi\Laravel\Facades\Nadi;

Nadi::withScope(function ($scope) {
    $scope->setTag('operation', 'payment_processing');
    $scope->setExtra('gateway', 'stripe');

    // Errors in this closure include the scoped context
    $this->processPayment($order);
});
// Context is cleared after the closure

Middleware Integration ​

Set context in middleware for consistent tagging:

php
namespace App\Http\Middleware;

use Nadi\Laravel\Facades\Nadi;

class NadiContextMiddleware
{
    public function handle($request, $next)
    {
        Nadi::configureScope(function ($scope) use ($request) {
            // Request identification
            $scope->setTag('request_id', $request->id());

            // Feature context
            if ($request->route()) {
                $scope->setTag('route', $request->route()->getName());
            }

            // User context (if authenticated)
            if ($request->user()) {
                $scope->setUser([
                    'id' => $request->user()->id,
                    'email' => $request->user()->email,
                ]);
            }

            // Tenant context (multi-tenant apps)
            if ($tenant = $request->route('tenant')) {
                $scope->setTag('tenant_id', $tenant->id);
            }
        });

        return $next($request);
    }
}

Register the middleware:

php
// app/Http/Kernel.php
protected $middleware = [
    // ...
    \App\Http\Middleware\NadiContextMiddleware::class,
];

Environment Context ​

Automatically captured environment information:

DataDescription
PHP VersionRuntime version
Laravel VersionFramework version
Server OSOperating system
Server NameHostname
Memory LimitPHP memory limit

Adding Custom Environment Data ​

php
use Nadi\Laravel\Facades\Nadi;

Nadi::setContext('runtime', [
    'php_version' => PHP_VERSION,
    'laravel_version' => app()->version(),
    'memory_limit' => ini_get('memory_limit'),
    'max_execution_time' => ini_get('max_execution_time'),
]);

Git Context ​

If your deployment includes Git information, Nadi captures:

  • Commit hash
  • Branch name (if available)

Set via environment variable:

env
NADI_RELEASE=abc123def456

Or programmatically:

php
// AppServiceProvider.php
Nadi::setRelease(trim(exec('git rev-parse HEAD')));

Clearing Context ​

Reset context when needed:

php
use Nadi\Laravel\Facades\Nadi;

// Clear specific context
Nadi::setUser(null);
Nadi::setTags([]);
Nadi::setExtras([]);

// Clear all context
Nadi::clearScope();

Context in Queue Jobs ​

Context is not automatically carried to queue jobs. Set context within the job:

php
class ProcessOrder implements ShouldQueue
{
    public function handle()
    {
        Nadi::configureScope(function ($scope) {
            $scope->setTag('job', 'process_order');
            $scope->setExtra('order_id', $this->order->id);
        });

        $this->process();
    }
}

Next Steps ​

Released under the MIT License.