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

Lightweight Laravel package that automatically logs all outgoing HTTP client requests. Capture URL, method, headers, payload, response headers/body, status code, and duration, with configurable logging and options to obfuscate sensitive data for debugging and auditing.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require farayaz/laravel-spy
    php artisan vendor:publish --provider="Farayaz\LaravelSpy\LaravelSpyServiceProvider"
    php artisan migrate
    
    • Auto-discovery handles the rest; no manual service provider registration required.
  2. Enable Logging: Add to .env:

    SPY_ENABLED=true
    
  3. First Use Case:

    • Make an HTTP request in a controller, job, or command:
      $response = Http::get('https://api.example.com/data');
      
    • Logs appear in the http_logs table and (if enabled) the /spy dashboard.

Where to Look First

  • Configuration: config/spy.php (published via vendor:publish).
  • Logs: Database table http_logs (schema: id, url, method, headers, body, response_headers, response_body, status_code, duration_ms, created_at).
  • Dashboard: /spy route (if SPY_DASHBOARD_ENABLED=true).
  • CLI: php artisan spy:clean for log management.

Implementation Patterns

Core Workflows

  1. Debugging API Integrations:

    • Enable in .env and inspect logs for failed requests:
      try {
          Http::post('https://payment-gateway.com/charge', $payload);
      } catch (\Exception $e) {
          // Check logs for payload/response mismatches
      }
      
    • Use the dashboard to filter by status_code != 200.
  2. Compliance Auditing:

    • Obfuscate sensitive fields in .env:
      SPY_OBFUSCATES=password,api_key,credit_card
      
    • Exclude non-compliant endpoints:
      SPY_EXCLUDE_URLS=api/webhooks/stripe
      
  3. CI/CD Validation:

    • Enable in CI pipeline to verify payload structures:
      # .github/workflows/test.yml
      env:
        SPY_ENABLED: true
      
    • Assert log entries match expected payloads in tests:
      $log = HttpLog::latest()->first();
      $this->assertEquals('expected_payload', $log->body);
      
  4. Performance Monitoring:

    • Track slow endpoints by querying duration_ms:
      $slowLogs = HttpLog::where('duration_ms', '>', 1000)->get();
      

Integration Tips

  • Middleware Integration: Attach to specific routes to log internal requests (not just external HTTP calls):

    Route::middleware([\Farayaz\LaravelSpy\Middleware\SpyMiddleware::class])->group(function () {
        // Routes to log
    });
    
  • Job/Queue Logging: Log async HTTP calls in jobs by enabling globally or per-job:

    class PaymentJob implements ShouldQueue {
        public function handle() {
            // Automatically logged if SPY_ENABLED=true
            Http::post('https://stripe.com/charge', $data);
        }
    }
    
  • Custom Storage: Extend the HttpLog model to support alternative storage (e.g., Redis):

    // app/Providers/AppServiceProvider.php
    use Farayaz\LaravelSpy\Models\HttpLog;
    
    public function boot() {
        HttpLog::extend('redis', function ($model) {
            return new RedisHttpLog($model);
        });
    }
    
  • Event-Based Extensions: Listen to spy.logged events to process logs in real-time:

    // app/Providers/EventServiceProvider.php
    protected $listen = [
        \Farayaz\LaravelSpy\Events\LogCreated::class => [
            \App\Listeners\ProcessHttpLog::class,
        ],
    ];
    
  • Testing: Mock logs in tests using the HttpLog facade:

    HttpLog::shouldReceive('create')->once();
    

Gotchas and Tips

Pitfalls

  1. Performance Overhead:

    • Issue: Synchronous DB writes can slow high-traffic endpoints (>100 RPS).
    • Fix: Disable in production or use SPY_FIELD_MAX_ROWS to limit log volume.
    • Workaround: Schedule spy:clean frequently to reduce table bloat.
  2. Binary Data Logging:

    • Issue: Large binary payloads (PDFs, images) may bloat logs.
    • Fix: Exclude content types:
      SPY_REQUEST_BODY_EXCLUDE_CONTENT_TYPES=image/,application/pdf
      
  3. Middleware Conflicts:

    • Issue: SPY_DASHBOARD_MIDDLEWARE may clash with existing route middleware.
    • Fix: Explicitly define middleware in routes/web.php:
      Route::get('/spy', [\Farayaz\LaravelSpy\Http\Controllers\SpyController::class, 'index'])
           ->middleware(['web', 'auth', 'spy.dashboard']);
      
  4. Obfuscation Edge Cases:

    • Issue: Partial matches in obfuscation (e.g., api_key_123 with SPY_OBFUSCATES=api_key).
    • Fix: Use regex patterns in future versions or pre-process payloads.
  5. Dashboard Limitations:

    • Issue: No pagination or advanced filtering in the built-in dashboard.
    • Fix: Build a custom view using the HttpLog model:
      $logs = HttpLog::where('status_code', '!=', 200)->paginate(20);
      
  6. Future-Dated Release:

    • Issue: Last release in 2026 may indicate stalled maintenance.
    • Fix: Fork the repo or monitor GitHub for updates. Consider alternatives like spatie/laravel-activitylog for critical projects.

Debugging Tips

  • Log Missing?:

    • Verify SPY_ENABLED=true and the request uses Laravel’s Http facade/client.
    • Check for URL exclusions:
      SPY_EXCLUDE_URLS=api/health,ping
      
  • Corrupted Logs:

    • Truncate and re-migrate the http_logs table:
      php artisan migrate:fresh --table=http_logs
      
  • Dashboard Not Loading:

    • Ensure middleware is correctly defined in SPY_DASHBOARD_MIDDLEWARE and no route conflicts exist.

Extension Points

  1. Custom Log Fields: Add columns to the http_logs table via a migration:

    Schema::table('http_logs', function (Blueprint $table) {
        $table->string('custom_metadata')->nullable();
    });
    

    Extend the HttpLog model to populate the field:

    use Farayaz\LaravelSpy\Events\LogCreated;
    
    LogCreated::listen(function ($log) {
        $log->custom_metadata = json_encode(['user_id' => auth()->id()]);
        $log->save();
    });
    
  2. Async Logging: Decouple logging from HTTP requests using queues:

    // app/Providers/AppServiceProvider.php
    use Farayaz\LaravelSpy\Jobs\LogHttpRequest;
    
    public function boot() {
        Http::macro('spy', function ($request) {
            LogHttpRequest::dispatch($request);
            return $request->send();
        });
    }
    
  3. Slack/Email Alerts: Trigger alerts for failed requests:

    // app/Providers/EventServiceProvider.php
    protected $listen = [
        \Farayaz\LaravelSpy\Events\LogCreated::class => [
            \App\Listeners\AlertOnFailure::class,
        ],
    ];
    
  4. GraphQL Support: Extend to log GraphQL queries by intercepting Http::asForm() or custom clients:

    Http::macro('graphql', function ($query, $variables = []) {
        $response = Http::post('graphql-endpoint', [
            'query' => $query,
            'variables' => $variables,
        ]);
        return $response;
    });
    
  5. Local Development Proxy: Use SPY_ENABLED=true with Laravel Valet or Laravel Sail to inspect local API calls:

    SPY_ENABLED=true SPY_EXCLUDE_URLS=localhost,127.0.0.1
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4