freightseeker / http-logger
Configurable outbound HTTP request logger for Laravel and Guzzle.
Requires
- php: ^8.3
- illuminate/database: ^11.0|^12.0|^13.0
- illuminate/queue: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- guzzlehttp/guzzle: ^7.8
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^4.4.1
- pestphp/pest-plugin-laravel: ^4.1.0
Suggests
- guzzlehttp/guzzle: Required for the Guzzle middleware adapter (^7.8).
README
A robust, highly configurable outbound HTTP request logger designed specifically for Laravel applications and Guzzle HTTP clients.
This package allows you to automatically monitor and store outbound API requests made by your application, providing full visibility into third-party integrations, webhook deliveries, and external service calls.
Key Features
- Store Options: Output logs securely to your SQL
database(default) or redirect them to a structured Laravellogfile based on configuration. - Automatic Laravel Integration: Seamlessly attaches to Laravel's HTTP Client (
Illuminate\Support\Facades\Http). - Native Guzzle Support: Includes middleware for easily logging raw Guzzle requests.
- Advanced Redaction & Security: Automatically redacts sensitive headers (e.g., API keys, Authorization tokens) and recursively scrubs sensitive JSON payload keys before persisting to the database.
- Filtering & Truncation: Configure maximum payload sizes to preserve database space, and strictly control which requests should be logged.
- Eloquent Polymorphism: Tie HTTP requests directly to Eloquent models using the
withLoggable()macro andHasHttpLogstrait. - Manual Logging Support: Use the
HttpLoggerfacade to record logs from custom auto-generated SDKs or vanilla cURL scripts.
Requirements
- PHP 8.3+
- Laravel 11.0 / 12.0 / 13.0
Installation
You can install the package via composer:
composer require freightseeker/http-logger
Laravel Projects
You can publish and run the migrations with:
php artisan vendor:publish --tag="http-logger-migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="http-logger-config"
Non-Laravel Projects
If you are using this package in a standalone PHP application (without the Laravel framework), you will need to manually handle the database schema or inject a custom HttpLogWriter into the HttpLogger.
If you choose to use the built-in database writer (which depends on illuminate/database), you must manually run this equivalent raw SQL to create the http_logs table:
CREATE TABLE `http_logs` ( `id` CHAR(26) NOT NULL, `direction` VARCHAR(10) NOT NULL, `driver` VARCHAR(20) NOT NULL, `url` TEXT NOT NULL, `method` VARCHAR(10) NOT NULL, `request_headers` JSON NULL, `request_body` LONGTEXT NULL, `response_status` INT NULL, `response_headers` JSON NULL, `response_body` LONGTEXT NULL, `duration_ms` INT UNSIGNED NOT NULL, `error_message` TEXT NULL, `loggable_type` VARCHAR(255) NULL, `loggable_id` CHAR(26) NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), INDEX `http_logs_loggable_type_loggable_id_created_at_index` (`loggable_type`, `loggable_id`, `created_at`) );
To entirely bypass illuminate/database, you can implement the HttpLogWriter interface and store your logs using raw PDO, Monolog, or any other solution:
use HttpLogger\Contracts\HttpLogWriter; use HttpLogger\HttpLogEntry; class MyPdoWriter implements HttpLogWriter { public function write(HttpLogEntry $entry): void { // Insert $entry data using raw PDO... } }
Usage
Laravel Integration
Laravel HTTP Client
The package automatically integrates with the Laravel HTTP Client. You don't need any additional setup.
use Illuminate\Support\Facades\Http; $response = Http::withHeaders(['X-First' => 'foo']) ->get('https://api.github.com/users/octocat'); // The request and response are now automatically stored in the database.
Polymorphic Relations
You can associate HTTP request logs with your Eloquent models using polymorphic relations. This is useful for tracking which requests belong to a specific record, such as a user, order, or shipment.
When using the Laravel HTTP Client, you can use the built-in macro to attach a model to the request:
use Illuminate\Support\Facades\Http; $order = Order::find(1); Http::withLoggable($order) ->post('https://api.example.com/orders/sync', $order->toArray());
Note:
withLoggable()stores the model in a per-process singleton and is designed for sequential requests. When usingHttp::pool()with multiple concurrent requests, only the most recently set loggable will be attached. For concurrent use-cases, construct anHttpLogEntrydirectly with the desiredloggableand callHttpLogger::record()manually.
To easily retrieve the associated logs, add the provided trait (or manually define the morphMany relationship) on your Eloquent model:
use Illuminate\Database\Eloquent\Model; use HttpLogger\Laravel\Concerns\HasHttpLogs; class Order extends Model { use HasHttpLogs; }
Now you can access the previous HTTP request logs directly from your model instance:
$logs = $order->httpLogs;
Guzzle HTTP Client
Automatic Logging (Recommended)
The package provides a LoggingGuzzleClient wrapper that handles all logging automatically. It is registered as a singleton in the Laravel service container and can be injected directly via the constructor:
use HttpLogger\Guzzle\LoggingGuzzleClient; class GitHubService { public function __construct(private readonly LoggingGuzzleClient $http) {} public function getUser(string $username): array { $response = $this->http->get("https://api.github.com/users/{$username}"); // The request and response are automatically logged. return json_decode((string) $response->getBody(), true); } }
You can associate requests with an Eloquent model using withLoggable(), mirroring the Laravel HTTP Client behavior:
$response = $this->http ->withLoggable($order) ->post('https://api.example.com/orders/sync', ['json' => $order->toArray()]);
Note:
withLoggable()is designed for sequential requests. The loggable is consumed (reset tonull) after the next request is dispatched.
To pass custom Guzzle config options (e.g. base_uri, timeout), resolve the client manually with LoggingGuzzleClient::make():
use HttpLogger\Guzzle\LoggingGuzzleClient; use HttpLogger\HttpLogger; $client = LoggingGuzzleClient::make(app(HttpLogger::class), [ 'base_uri' => 'https://api.example.com', 'timeout' => 10, ]);
Manual Middleware
If you need to attach logging to an existing Guzzle HandlerStack (e.g. wrapping a third-party SDK), push the middleware directly:
use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use HttpLogger\Guzzle\HttpLoggerMiddleware; use HttpLogger\HttpLogger; $stack = HandlerStack::create(); $stack->push(HttpLoggerMiddleware::make(app(HttpLogger::class))); $client = new Client(['handler' => $stack]); $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
Manual Logging
If you need to log requests made outside of Laravel's HTTP Client or Guzzle (for example, raw cURL requests or third-party SDKs), you can easily record entries using the built-in timer and the HttpLogger::log() helper method.
The log() method safely swallows all exceptions, guaranteeing that logging will never halt your application execution.
use HttpLogger\HttpDirection; use HttpLogger\Laravel\Facades\HttpLogger; // 1. Start the internal logger timer — returns a Closure that yields elapsed ms when called $timer = HttpLogger::startTimer(); // 2. Perform your manual request/interaction... $response = $customSdk->syncData(['foo' => 'bar']); // 3. Log the execution using the timer Closure HttpLogger::log( direction: HttpDirection::Outbound, driver: 'custom-sdk', url: 'https://api.example.com/sync', method: 'POST', requestHeaders: ['Content-Type' => 'application/json'], requestBody: json_encode(['data' => 'sync-me']), responseStatus: 200, responseHeaders: ['Content-Type' => 'application/json'], responseBody: json_encode(['status' => 'success']), timer: $timer, // Automagically resolves the request duration errorMessage: null, // Populate if your manual implementation encountered an error );
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Releasing
Please see RELEASING for instructions on how to cut a new release.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
License
The MIT License (MIT). Please see License File for more information.