Abrova
☰ Docs menu · Laravel SDK

Laravel SDK

Server-side error tracking for Laravel with auto-discovery, middleware, query tracking, Monolog channel, and performance monitoring.

Laravel 0.2.4PHP 8.1+Laravel 10–12Last updated: 27 Oct 2026
Server-Side Error Tracking

Comprehensive error monitoring for Laravel applications

Automatic Exception Capture

Integrates with Laravel exception handler via reportable()

Laravel Middleware

Built-in HTTP middleware for request/response tracking

Breadcrumbs

Track events leading up to an error for better context

Database Query Tracking

Automatic breadcrumbs and slow query detection via QueryExecuted

User Context

Associate errors with authenticated Laravel users automatically

Monolog Integration

Use Log::channel('abrovatrace') for structured logging

Performance Monitoring

Track HTTP requests, DB queries, and custom operations

Installation#

The package comes from Abrova Center. Two steps:

1. Add the Abrova repository to your composer.json:

json
"repositories": [
    { "type": "composer", "url": "https://center.abrova.ir/api/packages/abrova/composer" }
]

2. Install the package:

bash
composer require abrova-trace/laravel-sdk

Publish the configuration file:

bash
php artisan vendor:publish --tag=abrovatrace-config

Quick Start#

Add your credentials to .env:

bash
ABROVATRACE_API_KEY=ab_live_your_api_key_here
ABROVATRACE_SERVER_SECRET=ab_srv_your_server_secret_here
ABROVATRACE_ENVIRONMENT=production
ABROVATRACE_RELEASE=1.0.0
Auto-Discovery.

The SDK uses Laravel package auto-discovery. No manual registration of service providers or facades is needed. The facade is AbrovaTrace\Laravel\AbrovaTraceFacade (auto-aliased as AbrovaTrace). The SDK stays inactive until both ABROVATRACE_API_KEY and ABROVATRACE_SERVER_SECRET are set.

Capture Errors#

Automatic Capture

All unhandled exceptions are automatically captured via Laravel's exception handler. No code changes needed.

The exception is still written to your application's own log (laravel.log or your configured log channels), so you do not need to change your logging setup. Versions before 0.2.3 stopped Laravel's default logging for captured exceptions.

Manual Capture

php
use AbrovaTrace\Laravel\AbrovaTraceFacade as AbrovaTrace;

// Capture an exception
try {
    riskyOperation();
} catch (\Throwable $e) {
    AbrovaTrace::captureException($e, [
        'extra' => ['userId' => 123, 'feature' => 'checkout'],
    ]);
}

// Capture a message
AbrovaTrace::captureMessage('User completed checkout', [
    'extra' => ['orderId' => 'ORD-456'],
]);

// With a level and tags ('debug', 'info' (default), 'warning', 'error')
AbrovaTrace::captureMessage('Payment retried', [
    'level' => 'warning',
    'tags' => ['feature' => 'checkout'],
]);

The same exception is reported once. If you capture it with captureException() and then rethrow it, the automatic capture does not send it a second time (since 0.2.3).

Where messages show up.

Messages appear in the Console under Abrova Trace → Messages, with their level, platform, extra data and breadcrumbs. They never create an issue. 'warn' is sent as warning; 'fatal', 'critical', 'alert' and 'emergency' as error; 'trace' as debug; anything else as info. Use messages for things your app reports on purpose ("checkout started", "sync finished"); for high-volume diagnostics use Logs.

Breadcrumbs track events leading up to an error. HTTP requests and database queries are tracked automatically.

Manual Breadcrumbs

php
use AbrovaTrace\Laravel\AbrovaTraceFacade as AbrovaTrace;
use AbrovaTrace\Laravel\Models\Breadcrumb;

// HTTP breadcrumb
AbrovaTrace::addBreadcrumb(Breadcrumb::http('POST', '/api/orders', 201, 150.5));

// Database breadcrumb
AbrovaTrace::addBreadcrumb(Breadcrumb::database('SELECT * FROM users WHERE id = ?', 12.5));

// User action breadcrumb
AbrovaTrace::addBreadcrumb(Breadcrumb::user('clicked_checkout', ['cartTotal' => 99.99]));

// Custom breadcrumb
AbrovaTrace::addBreadcrumb(Breadcrumb::custom('Cache cleared', 'cache', ['keys' => 15]));
Automatic Breadcrumbs.

The SDK automatically records HTTP request/response breadcrumbs via middleware and database query breadcrumbs via the QueryExecuted event listener. No manual setup required.

User Context#

User context is automatically extracted from authenticated users via middleware. You can also set it manually:

php
AbrovaTrace::setUser([
    'id' => 123,
    'email' => 'user@example.com',
    'username' => 'john_doe',
]);

Scoped Context#

Use scoped context to isolate user and request context per operation. Both are automatically restored afterward (breadcrumbs added inside the closure are kept). The closure receives the SDK instance.

php
AbrovaTrace::withScope(function ($scope) {
    $scope->setUser(['id' => 456]);
    $scope->setRequestContext(['operation' => 'bulk_import']);
    $scope->addBreadcrumb(Breadcrumb::custom('Starting import', 'import'));

    // Errors captured here include this context
    AbrovaTrace::captureException(new \RuntimeException('Import failed'));
});
// Context is restored after the closure

Laravel Middleware#

The middleware is automatically registered on web and api groups. It provides:

  • Request Tracking — Records the incoming request as a breadcrumb (method and path) and sets request context (method, URL, path, route, IP, user agent)
  • Response Tracking — Records response breadcrumb with status code and duration
  • User Extraction — Automatically sets user context (id, email, name) from the authenticated user (middleware.track_user)
  • Performance Spans — Creates an HTTP performance span for every request (when performance.enabled is true)

To customize ignored paths, edit config/abrovatrace.php:

php
'middleware' => [
    'enabled' => true,
    'ignored_paths' => [
        'health',
        'api/health',
        '_debugbar/*',
        'telescope/*',
    ],
],

Database Query Tracking#

Database queries are automatically tracked via Laravel's QueryExecuted event (performance.track_db_queries). Every query becomes a breadcrumb; queries at or above the threshold (default 500ms) also generate performance spans.

php
// config/abrovatrace.php
'performance' => [
    'enabled' => true,
    'track_db_queries' => true,
    'slow_query_threshold_ms' => 100,  // Span for queries taking 100ms or more
],

Monolog Log Channel#

Send logs to AbrovaTrace using Laravel's built-in logging system:

php
// config/logging.php
'channels' => [
    'abrovatrace' => [
        'driver' => 'custom',
        'via' => AbrovaTrace\Laravel\Logging\AbrovaTraceLogChannel::class,
    ],
],
php
use Illuminate\Support\Facades\Log;

Log::channel('abrovatrace')->info('User signed up', ['userId' => 123]);
Log::channel('abrovatrace')->error('Payment failed', ['orderId' => 'ORD-456']);
Log::channel('abrovatrace')->warning('Rate limit approaching', ['remaining' => 5]);
Stack Channel.

You can add abrovatrace to a stack channel to send logs to multiple destinations simultaneously.

See Laravel SDK Logging for batching behavior, log levels, and manual flush.

Performance Tracking#

php
use AbrovaTrace\Laravel\AbrovaTraceFacade as AbrovaTrace;
use AbrovaTrace\Laravel\Performance\PerformanceSpan;

// Track a custom operation with automatic timing
$result = AbrovaTrace::trackOperation('cache.rebuild', function () {
    return rebuildCache();
}, ['tags' => ['cache' => 'products']]);

// Manual performance span
AbrovaTrace::reportPerformanceSpan(PerformanceSpan::custom([
    'operation' => 'email.send',
    'durationMs' => 250.5,
    'startTime' => now()->subMilliseconds(250),
    'tags' => ['mailer' => 'smtp'],
]));

Configuration Options#

php
// config/abrovatrace.php
return [
    'api_key' => env('ABROVATRACE_API_KEY', ''),
    'server_secret' => env('ABROVATRACE_SERVER_SECRET', ''),
    'enabled' => env('ABROVATRACE_ENABLED', true),
    'environment' => env('ABROVATRACE_ENVIRONMENT', env('APP_ENV', 'production')),
    'release' => env('ABROVATRACE_RELEASE', '0.1.0'),
    'sample_rate' => env('ABROVATRACE_SAMPLE_RATE', 1.0),
    'before_send' => null, // set a closure from a service provider
    'debug' => env('ABROVATRACE_DEBUG', false),
    'timeout' => env('ABROVATRACE_TIMEOUT', 5),
    'max_breadcrumbs' => 50,
];
OptionTypeRequiredDescription
api_keystringYesYour project API key (ab_live_xxx)
server_secretstringYesYour server secret (ab_srv_xxx)
enabledbooleanNoEnable/disable tracking (default: true)
environmentstringNoEnvironment name (default: APP_ENV, else "production")
releasestringNoApp version identifier (default: "0.1.0")
sample_ratefloatNoSample rate for errors and messages, 0.0-1.0 (default: 1.0)
before_sendcallableNoReceives each error (AbrovaTraceError) or message (AbrovaTraceMessage); return it (or a modified one) to send, null to drop. Set it from a service provider, since a closure cannot live in a cached config
debugbooleanNoEnable debug logging (default: false)
timeoutintegerNoHTTP timeout in seconds (default: 5, max: 30)
max_breadcrumbsintegerNoMax breadcrumbs to keep, 0-100 (default: 50)

Ignored Exceptions#

The SDK ships with sensible defaults for exceptions Laravel apps typically don't want as errors. By default these are not reported:

  • AuthenticationException — unauthenticated requests
  • ValidationException — form validation failures
  • NotFoundHttpException — 404s
  • All 4xx HTTP exceptions

Customize via config/abrovatrace.php:

php
'exception_handler' => [
    'ignored_exceptions' => [
        \App\Exceptions\BusinessException::class,
    ],
    'report_4xx' => true,
],

The ignored_exceptions list you set replaces the default one, so keep the default entries you still want ignored.

Why exclude 4xx by default.

4xx responses are client errors — duplicating them as exceptions makes the error feed noisy. Flip report_4xx to true if you genuinely want them captured (e.g. for analytics).

API Reference#

AbrovaTrace Facade

  • captureException($e, $options?) — Capture an exception
  • captureMessage($msg, $options?) — Send a message to Abrova Trace → Messages ($options: level, extra, tags)
  • addBreadcrumb($breadcrumb) — Add a breadcrumb
  • setUser($user) — Set user context
  • setRequestContext($context) — Set request context
  • withScope($callback) — Run code with isolated user/request context
  • log($message, $level?, $metadata?) — Send a log entry (user id comes from setUser())
  • trace(), logDebug(), info(), warn(), logError(), fatal() — Log at a level ($message, $metadata?)
  • trackOperation($name, $callback, $options?) — Track operation with auto-timing ($options: operationType, tags)
  • reportPerformanceSpan($span) — Report a performance span
  • flush() — Flush buffered logs and performance spans (also runs automatically at shutdown)
  • isEnabled() — Check if SDK is enabled
  • getStats() — Get SDK statistics

Breadcrumb Helpers

  • Breadcrumb::http($method, $url, $status?, $duration?) — HTTP request breadcrumb
  • Breadcrumb::database($query, $duration, $error?) — Database query breadcrumb
  • Breadcrumb::user($action, $data?) — User action breadcrumb
  • Breadcrumb::navigation($from, $to, $method?) — Navigation breadcrumb
  • Breadcrumb::custom($message, $category, $data?) — Custom breadcrumb

Requirements#

  • PHP — >= 8.1
  • Laravel — 10.x / 11.x / 12.x
  • Guzzle — >= 7.0 (ships with Laravel)

Complete Example#

php
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Log;
use AbrovaTrace\Laravel\AbrovaTraceFacade as AbrovaTrace;
use AbrovaTrace\Laravel\Models\Breadcrumb;

Route::get('/users/{id}', function ($id) {
    // Add a breadcrumb (DB queries are tracked automatically)
    AbrovaTrace::addBreadcrumb(Breadcrumb::user('view_user', [
        'userId' => $id,
    ]));

    try {
        $user = User::findOrFail($id);
        return response()->json($user);
    } catch (\Throwable $e) {
        AbrovaTrace::captureException($e, [
            'extra' => ['userId' => $id],
        ]);
        return response()->json(['error' => 'User not found'], 404);
    }
});

// Log via Monolog channel
Route::post('/orders', function (Request $request) {
    $order = Order::create($request->validate([
        'total' => 'required|numeric',
    ]));

    Log::channel('abrovatrace')->info('Order created', [
        'orderId' => $order->id,
        'amount' => $order->total,
    ]);

    // Track performance of external API call
    $result = AbrovaTrace::trackOperation('payment.process', function () use ($order) {
        return PaymentGateway::charge($order);
    });

    return response()->json($result);
});

Best Practices#

Use Environment Variables

Store API key and server secret in .env, never commit credentials

Leverage Auto-Discovery

The service provider registers automatically — no manual provider registration needed

Use the Monolog Channel

Send structured logs via Log::channel('abrovatrace') for centralized logging

Set User Context

User context is auto-extracted from Auth, but set it manually for API token auth

Add Breadcrumbs

HTTP and DB breadcrumbs are automatic — add custom breadcrumbs for business logic

Configure Ignored Paths

Exclude health checks and debug routes from middleware tracking

Track Slow Queries

Set slow_query_threshold_ms to catch performance regressions early

Use trackOperation()

Wrap external API calls and expensive operations for performance monitoring

Was this page helpful?
Report a problem