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

Request Id Bundle Laravel Package

talentrydev/request-id-bundle

Adds a unique request ID to each incoming request so logs, responses, and error reports can be correlated. Exposes the ID through headers and middleware, making it simpler to trace requests across services. Lightweight drop-in integration for Laravel and PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there's no service provider or config/request-id.php. As a Laravel dev you have two paths: consume it inside a Symfony service, or read the ~100 lines of source and port the idea to a Laravel middleware (usually the smarter move given the project's state: 0 stars, 0 dependents, last release March 2021).

If you're in a Symfony app:

composer require talentrydev/request-id-bundle

Register it in config/bundles.php:

return [
    // ...
    Talentry\Dev\RequestIdBundle\RequestIdBundle::class => ['all' => true],
];

Where to look first, in this order:

  1. src/ — the bundle is small; find the event subscriber/listener (likely on kernel.request / kernel.response).
  2. The DI extension class (DependencyInjection/*Extension.php) — this tells you the real config keys and service IDs. Don't guess config from the README.
  3. The ID generator service — this is the seam you'll want to override.

First use case: put a request ID on every response and in every log line, so when a user reports "the checkout failed at 2:14pm" you can grep one ID and see the whole trace.

curl -i https://app.local/checkout | grep -i request-id
# X-Request-Id: 0f8c1e2a-...
grep 0f8c1e2a- storage/logs/*.log

If that round-trip works, the bundle is doing its job.

Implementation Patterns

Inbound propagation (the important one). Most real deployments sit behind a gateway/load balancer that already assigns a correlation ID. The useful pattern is: reuse the incoming header if present, otherwise generate. Verify the bundle does this — if it unconditionally generates, the ID your edge logs and the ID your app logs won't match, which defeats the purpose.

// What you want the listener to look like
$id = $request->headers->get('X-Request-Id') ?: $this->generator->generate();
$request->attributes->set('_request_id', $id);
$response->headers->set('X-Request-Id', $id);

Monolog processor. The header alone is half the value. Wire a processor so every record carries the ID:

# config/services.yaml
services:
    App\Logging\RequestIdProcessor:
        arguments: ['@request_stack']
        tags:
            - { name: monolog.processor, method: __invoke }
final class RequestIdProcessor
{
    public function __construct(private RequestStack $stack) {}

    public function __invoke(array $record): array
    {
        $record['extra']['request_id'] =
            $this->stack->getCurrentRequest()?->attributes->get('_request_id') ?? 'cli';
        return $record;
    }
}

Also add %extra.request_id% to your Monolog line formatter — otherwise it lands in the record but never prints.

Async work. Correlate jobs with the originating request: stash the ID into the message envelope and restore it in the worker. Without this, queue logs are orphaned from the HTTP request that caused them.

Laravel translation. If you'd rather not depend on an unmaintained bundle, the same behavior is a middleware in ~15 lines:

public function handle($request, Closure $next)
{
    $id = Str::isUuid($request->header('X-Request-Id'))
        ? $request->header('X-Request-Id')
        : (string) Str::uuid();

    $request->attributes->set('request_id', $id);
    app()->instance('request_id', $id); // injectable, Log::withContext()-friendly

    $response = $next($request);
    return $response->header('X-Request-Id', $id);
}

Pair it with Log::withContext(['request_id' => app('request_id')]) in a bootstrap step and you get the Symfony bundle's whole feature set with zero external dependency.

Testing. Assert the header exists and is stable across the request — a common bug is the response listener regenerating instead of reading the request attribute. Freeze the generator in tests for deterministic assertions.

Gotchas and Tips

  • Maintenance risk is the headline. Last release 2021-03-18, zero dependents. That predates Symfony 6/7 conventions. Expect to patch bundle registration, service visibility (private by default since Symfony 4), and possibly deprecations around ReturnTypeWillChange or event dispatcher signatures. Read composer.json for a hard symfony/* constraint before installing into a modern app — a ^4.0|^5.0 requirement will block install outright.
  • Don't trust the client header. Accepting arbitrary X-Request-Id values invites log injection (newlines, ANSI escapes) and log-spoofing. Validate it as a UUID or at least cap length and charset before propagating.
  • Proxies strip or overwrite headers. Confirm your ingress (nginx, ALB, Cloudflare) forwards X-Request-Id; several don't by default. If it's stripped in transit, the "reuse upstream ID" logic silently never fires and every hop generates its own.
  • Listener ordering matters. The ID must exist before the first log line and before any component that logs during kernel.request. If the subscriber runs late, early log records carry null. Check priority on the subscriber; kernel.request needs a high priority (e.g. 2048 or higher).
  • Console commands have no request. getCurrentRequest() returns null in bin/console, so a naive processor throws or logs empty. Generate a synthetic per-command ID and make the processor null-safe.
  • Sub-requests and error pages. Symfony's exception controller can run as a sub-request; if the listener registers on every kernel.request, you may get ID churn on error pages. Guard with if (!$event->isMainRequest()) return;.
  • Extension points to prefer: swap the ID generator service (alias yours over the bundle's), rather than forking. If the generator is final or not aliased, that's a sign the bundle wasn't designed for override — another argument for the 15-line middleware.
  • Debugging: dump what actually landed on the request with a quick listener on kernel.response:
dump($request->attributes->all(), $request->headers->get('X-Request-Id'));

If the attribute is set but the log formatter shows nothing, the problem is your Monolog config, not the bundle. Isolate those two layers first — it's the single most common source of "the request ID doesn't work" confusion.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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