manomano-tech/correlation-ids-bundle
A Symfony/PHP bundle for generating, propagating, and exposing correlation IDs across HTTP requests, logs, and downstream services. Helps trace requests end-to-end and improves observability in distributed systems.
This is a Symfony bundle, not a Laravel package — you cannot composer require it into a Laravel app (it depends on symfony/http-kernel and symfony/dependency-injection). The good news is that the framework-agnostic core, manomano-tech/correlation-ids, is a plain PHP class you can install and use directly:
composer require manomano-tech/correlation-ids
Start by reading the interface of CorrelationIds in the underlying package — it exposes a way to construct an instance from a string (or generate one when absent) and read the value back. That is the entire surface area you actually need.
Your first use case in Laravel is almost always: read X-Correlation-Id off the incoming request, synthesize one if missing, echo it back on the response, and make it available everywhere (logs, outbound HTTP, queued jobs). Look first at App\Http\Kernel::$middleware and app/Http/Middleware/ — that is where this bundle's Symfony KernelEventListener would translate to in Laravel.
Request middleware. Create a CorrelationIdMiddleware that:
X-Correlation-Id from the request (fall back to X-Request-Id if your gateway sends that).[A-Za-z0-9-]{8,64}), otherwise generates a new one.app()->instance(CorrelationIds::class, $ids) and/or Context::add('correlation_id', ...).$next($request) and adds the header to the response.Log context. This is the highest-value pattern. Use Illuminate\Support\Facades\Log::withContext(['correlation_id' => $id]) (or a Monolog processor) so every log line carried the ID without touching call sites. This is exactly what the Symfony bundle's Monolog bridge would have done for you.
Outbound HTTP propagation. Add a Guzzle Middleware::mapRequest() that copies the ID onto every outgoing request — otherwise the correlation breaks the moment you call another service. Centralize this in a Http::globalRequestMiddleware() if you use Laravel's HTTP client.
Queued jobs. Serialize the ID into the job payload in a base job class (__sleep/__wakeup or the handle() bootstrap), because a CLI worker does not inherit the request's container state. This is the most commonly missed propagation path.
Symfony precedent to copy. The bundle's structure (a listener + a service definition + a Monolog processor) is a reasonable template even in Laravel — mirror the same three pieces as middleware + app()->instance + log processor.
services.yaml and kernel event priorities. In Laravel, middleware priority matters just as much: this must run before anything that logs (e.g. before TrimStrings, and definitely before exception handlers that log).app()->scoped() (Octane-aware) or reset it in the terminate() phase.$request->header('X-Correlation-Id') only checks the exact key in Laravel — use $request->headers->get('X-Correlation-Id') which normalizes.test-request-id) instead of a random UUID — makes assertions much easier.How can I help you explore Laravel packages today?