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 Logger Laravel Package

andriichuk/laravel-http-logger

A Laravel package that logs outgoing HTTP requests and responses to the database, making it easy to inspect, debug, and monitor third-party API calls with configurable logging, pruning, and a built-in dashboard.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer and publish its single config file:

composer require vendor/http-logger
php artisan vendor:publish --tag=http-logger-config

That gives you config/http-logger.php — this is the only file you need to know about. Everything the package does (routing, status filtering, header/body sanitization, channel, prefix) is driven from there and is env-aware, so skim it top-to-bottom once before changing anything.

Minimum viable setup for a first use case — log only API traffic, only errors, to a dedicated channel:

// config/http-logger.php
'enabled' => env('HTTP_LOGGER_ENABLED', false),
'channel' => env('HTTP_LOGGER_CHANNEL', 'http_logger'),
'prefix'  => '[HttpLogger]',
'routes'  => ['api/*'],
'statuses' => [400, 401, 403, 404, 422, 429, 500, 502, 503],
// config/logging.php
'channels' => [
    'http_logger' => [
        'driver' => 'daily',
        'path' => storage_path('logs/http-logger.log'),
        'days' => 14,
        'level' => 'debug',
    ],
],
HTTP_LOGGER_ENABLED=true
HTTP_LOGGER_CHANNEL=http_logger

The package hooks Laravel's RequestHandled event, so there is nothing to register in a service provider or middleware stack — once enabled and the channel exists, requests matching your route patterns start landing in storage/logs/http-logger.log-YYYY-MM-DD.

First use case to reach for: turning this on in staging with routes => ['api/*'] and statuses => [4*, 5*]-style filtering to get a readable error trail for failing API calls, without drowning in 200s.

Implementation Patterns

Environment-scoped enablement. Treat enabled as the primary switch and keep it false by default in config/http-logger.php. Flip it per environment via HTTP_LOGGER_ENABLED — on in local/staging, off (or errors-only) in production. Do not rely on route/status filters alone as your volume control.

Route patterns as the coarse filter. routes accepts patterns in the same spirit as Route::is(), so api/*, api/v1/orders*, webhooks/* all work. Prefer a small number of explicit patterns over *; the listener runs on every request that matches, so a broad pattern is a broad performance and log-volume cost. Use a separate pattern set per environment if your route surface differs.

Status buckets for signal-to-noise. statuses takes 1xx–5xx classes. Two common profiles:

  • Error trail: [400, 401, 403, 404, 409, 422, 429, 500, 502, 503, 504] — the everyday choice.
  • Full audit (short-lived): [1, 2, 3, 4, 5] — for a debugging window only. 2xx/3xx logging generates enormous volume fast.

Header allowlists plus masking. Set the header allowlist to what you actually need to correlate a request (X-Request-Id, Accept, Content-Type, User-Agent), and make sure the sensitive-header mask list covers Authorization, Cookie, Set-Cookie, X-Api-Key, and any internal auth headers. Masking happens on output, but the safe default is: don't allowlist a header you don't need.

Body sanitization as a config contract. The sensitive-field list and truncation length are the two settings worth codifying in code review. Add your domain's secret-ish fields (password, password_confirmation, token, secret, card_number, cvv, ssn) and pick a truncation length that keeps logs greppable — a few hundred to a couple of thousand characters is usually right. Long truncation defeats the purpose on payload-heavy endpoints.

Prefixes for correlation. Keep the [HttpLogger] prefix (or set your own) — it makes grep against a shared channel trivial and lets you route on it in log aggregators. If you inject a request ID into the prefix, you get per-request correlation across app and HTTP logs for free.

Test with log assertions, not real files. Because everything funnels through the configured channel, Log::fake() / Log::spy() plus assertions on the channel is the clean way to test that a given route+status produces (or doesn't produce) a log line. This is also how you regression-test sanitization: assert the masked value appears and the raw secret does not.

Custom channels for separation of concerns. Point channel at different channels per environment (e.g. a Slack/critical channel for 5xx in production, a daily file for everything in staging). Since it's just a Laravel log channel name, anything the logging system supports works.

Gotchas and Tips

  • Channel must exist first. If channel names a channel that isn't defined in config/logging.php, you'll get a silent-ish failure or an exception depending on driver. Create the channel before enabling.
  • Config cache. After editing config/http-logger.php, run php artisan config:clear (or config:cache) — in cached environments nothing you change will take effect otherwise. This is the single most common "it's not logging" cause.
  • Streamed and file responses. Response bodies for StreamedResponse/BinaryFileResponse aren't reliably readable at RequestHandled time. Don't expect download endpoints or SSE streams to produce useful body logs, and consider excluding those routes entirely.
  • Body logging has a real cost. Reading and sanitizing request/response bodies adds overhead and memory per request, especially on large JSON payloads. Truncation limits the log size, not necessarily the serialization cost — exclude upload endpoints and keep routes narrow in production.
  • Masking is a safety net, not a guarantee. Field-name matching won't catch secrets nested under unexpected keys or embedded in free-text fields. Review the sanitization list whenever you add an endpoint that accepts credentials or PII.
  • Header matching is likely case-insensitive but verify it. Check how your allowlist/mask entries are compared for the headers you care about, and test authorization vs Authorization once rather than assuming.
  • Don't double up. If you already log requests via middleware or a third-party logger, you'll get duplicate lines for the same request. Pick one owner per route group.
  • Long-running workers (Octane/queue). Config is read at boot; changing env vars requires a worker restart. If you toggle enabled per-request for debugging, expect to need a reload.
  • Correlate, don't dump. The most useful upgrade to the default setup is making sure every log line carries a request ID (via prefix or an allowlisted X-Request-Id) so HTTP logs can be joined to the application log entry that explains the failure.
  • Extension point. If the default line format doesn't fit, the supported lever today is the channel's formatter and the message prefix — reach for a custom log channel/formatter rather than patching the package, and keep your customization in config/logging.php so package upgrades stay clean.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console