Weave 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 Http Client Logger Laravel Package

bilfeldt/laravel-http-client-logger

Log outgoing HTTP requests and responses made with Laravel’s HTTP client. The package adds configurable middleware that captures URLs, status codes, timing, headers, and payloads, with sensitive-data redaction and flexible logging options.

View on GitHub
Deep Wiki
Context7

Getting Started

bilfeldt/laravel-http-client-logger adds a middleware to Laravel's HTTP client that logs every outgoing request and response. It's a drop-in observability layer for the Http facade — useful the moment you have integrations (payment providers, CRMs, internal APIs) and no easy way to see what was actually sent.

Install and publish config:

composer require bilfeldt/laravel-http-client-logger
php artisan vendor:publish --tag=http-client-logger

Register the middleware globally in AppServiceProvider::boot():

use Bilfeldt\HttpClientLogger\Http\Middleware\LogRequestMiddleware;
use Illuminate\Support\Facades\Http;

Http::globalMiddleware(LogRequestMiddleware::class);

That's it — the next outgoing call lands in your default log channel. Check config/http-client-logger.php first; the main knobs are:

  • logger — the logger implementation class (defaults to the bundled LaravelLogger).
  • log_profile — full, short, headers, or none. Start with short while exploring; full dumps entire bodies.
  • log_channel — pin logs to a dedicated channel instead of polluting laravel.log.

First use case: point it at a flaky integration, set log_profile to full in local, fire a job, and read the request/response pair back out of storage/logs/laravel.log. This is the fastest way to answer "did we send the right payload and what did they actually return" without a debugger or a proxy like Charles.

If you've been on v2.5.x, v2.6.0 is a pure compatibility bump (Laravel 13.x support) with no API or config changes — a safe, no-op upgrade.

Implementation Patterns

Scope it to a single client. Global middleware logs everything, including health checks and third-party noise. For a per-service setup, build a dedicated client and attach middleware there:

$client = Http::withMiddleware(LogRequestMiddleware::class)
    ->baseUrl('https://api.stripe.com');

Toggle by environment, not by code. Keep the middleware registered everywhere and drive it from config so you can flip it on in staging without a redeploy:

// config/http-client-logger.php
'log_profile' => env('HTTP_CLIENT_LOG_PROFILE', 'short'),

Then set HTTP_CLIENT_LOG_PROFILE=none in production unless you have a dedicated, redacted channel.

Dedicated log channel. Create an http-client channel in config/logging.php and point log_channel at it. This lets you apply a separate retention policy, route it to a central collector, or tail it in isolation with php artisan tail-style tooling. It also keeps noisy payloads out of the main app log, where they drown out real errors.

Custom logger for redaction and structure. The logger config value is resolved from the container, so swapping it is the documented extension point. Subclass LaravelLogger (or implement the package's logger contract) when you need to strip authorization headers, customer emails, or card fragments before the record is written:

class RedactingLogger extends \Bilfeldt\HttpClientLogger\Loggers\LaravelLogger
{
    // override the request/response serialisation to mask fields
}

Register it via 'logger' => App\Logging\RedactingLogger::class — no middleware changes needed.

Add correlation context. Because the middleware runs inside the request/job lifecycle, you can combine it with Laravel's logging context to attach a trace or job ID. That's what makes the logs usable in a queue worker handling hundreds of jobs — without a correlation ID, interleaved request/response pairs are unreadable.

Pair it with Http::fake() in tests deliberately. Faked responses still flow through the client pipeline, so logging will fire in your test suite. Either set log_profile to none in phpunit.xml, or use it as a cheap assertion surface for what your code was about to send.

Gotchas and Tips

  • full is a data-leak waiting to happen. It logs complete request and response bodies, including bearer tokens, API keys, and customer PII in query strings, headers, and payloads. Never ship full as the production default — use short or headers, and pair it with a custom logger that redacts known-sensitive keys.
  • Multi-megabyte responses will wreck your logs. A full profile against an endpoint returning a large JSON or binary blob produces enormous entries, slows the request path, and can blow through log-storage quotas on high-traffic queue workers. Consider disabling on chatty clients.
  • Middleware ordering matters. Global middleware runs in registration order. If you have other global middleware that mutates requests or short-circuits (retry logic, auth refresh), verify that what gets logged is the final outgoing request — not a pre-mutation snapshot.
  • Connection failures may not be logged. The middleware observes responses; if the client throws a ConnectionException before a response exists, confirm whether you get a log line. If not, wrap critical calls or add a try/catch that logs the outbound attempt yourself, otherwise the most important failures are exactly the ones missing from your logs.
  • log_channel of null falls back to the default stack — which in many apps means a daily file, mixed with everything else. Set it explicitly; this is the single highest-leverage config tweak for making the package actually useful.
  • Config caching catches people out. After editing config/http-client-logger.php, run php artisan config:clear (or config:cache in deploy) — otherwise your log_profile change silently does nothing in a cached environment. Same applies to env-driven overrides.
  • Log level semantics are status-code driven, so 4xx/5xx responses land at higher severity than 2xx. That's useful for alerting, but it means a deliberate validation rejection from a partner API looks like an error in your dashboards — account for it when wiring up log-based alerts.
  • Upgrade path is clean for now. v2.6.0 only widens the Laravel constraint to include 13.x. No deprecated config keys, no renamed classes. Pin ^2.6 and move on.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package