Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Spy Laravel Package

farayaz/laravel-spy

Zero-config Laravel package to spy on outgoing HTTP calls. Automatically logs Laravel Http facade and Guzzle requests with URL, method, headers, payload, response/status, and duration. Includes configurable logging and obfuscation for sensitive data.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require farayaz/laravel-spy
    

    The package auto-discovers and requires no manual bootstrapping.

  2. Publish Configuration and Migrations:

    php artisan vendor:publish --provider="Farayaz\LaravelSpy\LaravelSpyServiceProvider"
    php artisan migrate
    

    This sets up the http_logs table and default config.

  3. Enable Logging: Set SPY_ENABLED=true in your .env to start tracking requests immediately.

First Use Case

Debugging a Failing API Call:

// In your controller or job:
$response = Http::post('https://api.example.com/webhooks', [
    'user_id' => 123,
    'event' => 'payment.succeeded'
]);

// Check the logs table for the request/response details:
$log = \Farayaz\LaravelSpy\Models\HttpLog::latest()->first();
dd($log->response_body); // Inspect the raw response

Where to Look First

  • Logs Table: Run php artisan tinker and query:
    \Farayaz\LaravelSpy\Models\HttpLog::latest()->take(5)->get();
    
  • Configuration: Review config/laravel-spy.php for obfuscation rules and exclusions.
  • Dashboard (Optional): If enabled (SPY_DASHBOARD_ENABLED=true), access /spy for a UI overview.

Implementation Patterns

Core Workflows

1. Automatic Logging (Default)

  • Trigger: All Http:: facade calls and Guzzle clients bound to Laravel’s container are auto-logged.
  • Example:
    // Auto-logged via middleware
    Http::get('https://api.github.com/users/octocat');
    

2. Manual Logging (For Standalone Guzzle)

  • Use the spy helper or service container to log requests manually:
    use Farayaz\LaravelSpy\Facades\Spy;
    
    $client = new \GuzzleHttp\Client();
    $response = $client->request('GET', 'https://api.example.com');
    Spy::log($response, [
        'url' => 'https://api.example.com',
        'method' => 'GET',
        'headers' => [],
        'body' => null,
    ]);
    

3. Conditional Logging

  • Exclude specific URLs or domains in .env:
    SPY_EXCLUDE_URLS=*.staging.example.com,api.internal.*
    
  • Or dynamically in code:
    if (!app('spy')->shouldLog('https://api.example.com')) {
        // Skip logging
    }
    

4. Obfuscating Sensitive Data

  • Configure obfuscation rules in config/laravel-spy.php:
    'obfuscate' => [
        'headers' => ['authorization', 'x-api-key'],
        'body' => ['password', 'credit_card'],
    ],
    
  • Use regex patterns for dynamic matching:
    'obfuscate' => [
        'body' => ['/token=[^&]+/', '/secret_[a-z]+/'],
    ],
    

5. Custom Logging Drivers

  • Extend the HttpLog model or bind a custom logger via the spy.logged event:
    // In EventServiceProvider
    public function boot()
    {
        \Farayaz\LaravelSpy\Events\HttpLogged::listen(function ($log) {
            // Send to external service (e.g., Datadog, Sentry)
            \Log::channel('external')->info($log->toArray());
        });
    }
    

Integration Tips

With Laravel Jobs/Queues

  • Logs are stored synchronously during job execution. For high-volume queues, consider:
    • Batching logs with spy:clean scheduled daily.
    • Using a separate queue for logging (advanced).

With API Testing (Pest/PHPUnit)

  • Assert logged requests in tests:
    $this->post('/webhook', ['event' => 'test'])
         ->assertOk();
    
    $log = \Farayaz\LaravelSpy\Models\HttpLog::latest()->first();
    $this->assertEquals('POST', $log->method);
    $this->assertStringContainsString('event=test', $log->body);
    

With Laravel Telescope

  • Use the spy:clean command to purge old logs and integrate with Telescope’s storage:
    // In app/Console/Kernel.php
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('spy:clean')->daily();
    }
    

With Guzzle Middleware

  • For non-containerized Guzzle clients, use the spy middleware:
    $client = new \GuzzleHttp\Client([
        'middleware' => [
            new \Farayaz\LaravelSpy\Middleware\SpyMiddleware(),
        ],
    ]);
    

Gotchas and Tips

Pitfalls

1. Performance Overhead

  • Issue: Logging large request/response bodies (e.g., file uploads, binary data) can slow down requests.
  • Fix:
    • Limit payload size in config:
      'field_max_length' => 1024, // Truncate bodies >1KB
      
    • Exclude non-critical endpoints:
      SPY_EXCLUDE_URLS=*.example.com/files/*
      

2. Database Bloat

  • Issue: Unchecked log retention fills the http_logs table.
  • Fix:
    • Schedule cleanup:
      php artisan schedule:run
      
      (Add to app/Console/Kernel.php as shown above.)
    • Adjust retention:
      SPY_CLEAN_DAYS=7
      

3. Guzzle Auto-Detection Failures

  • Issue: Standalone Guzzle clients (not container-bound) won’t log automatically.
  • Fix: Manually log or use the SpyMiddleware as shown in the integration section.

4. Obfuscation Edge Cases

  • Issue: Regex obfuscation may accidentally mask valid data.
  • Fix:
    • Test obfuscation rules in a staging environment first.
    • Use precise patterns (e.g., token=[a-z0-9]{32} instead of token=.*).

5. Middleware Collisions

  • Issue: Conflicts with other HTTP middleware (e.g., retry, timeout).
  • Fix: Ensure LaravelSpyServiceProvider loads after your middleware in app/Providers/AppServiceProvider.php:
    public function register()
    {
        $this->app->register(\Farayaz\LaravelSpy\LaravelSpyServiceProvider::class);
    }
    

Debugging Tips

Verify Logging is Active

php artisan tinker
>>> app('spy')->isEnabled()
// Should return `true`

Check Excluded URLs

php artisan tinker
>>> app('spy')->shouldLog('https://excluded.example.com')
// Should return `false` if excluded

Inspect Raw Logs

php artisan spy:list
// Lists recent logs with IDs for debugging

Disable Logging Temporarily

SPY_ENABLED=false php artisan your:command

Extension Points

Custom Log Fields

Add metadata to logs via the spy.logged event:

\Farayaz\LaravelSpy\Events\HttpLogged::listen(function ($log) {
    $log->metadata = json_encode(['user_id' => auth()->id()]);
    $log->save();
});

Dashboard Integration

Extend the default dashboard (if enabled) by publishing views:

php artisan vendor:publish --tag=spy-views

Then override resources/views/vendor/laravel-spy/dashboard.blade.php.

Log to External Services

Subscribe to the spy.logged event to forward logs to tools like Datadog or Sentry:

\Farayaz\LaravelSpy\Events\HttpLogged::listen(function ($log) {
    \Sentry\captureMessage("HTTP Request: {$log->method} {$log->url}", [
        'level' => 'info',
        'extra' => $log->toArray(),
    ]);
});

Bulk Export Logs

Create a custom command to export logs to CSV/JSON:

// app/Console/Commands/ExportSpyLogs.php
public function handle()
{
    $logs = \Farayaz\LaravelSpy\Models\HttpLog::all();
    $this->info(json_encode($logs->toArray()));
}
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata