etsglobal/log-bundle
ETSGlobal LogBundle adds normalized logging and request tracing to Symfony apps: automatic logger injection, token collection and context enrichment, custom exception levels, a Slack handler, and Guzzle/Symfony HttpClient token forwarding.
Architecture fit — the core mismatch. etsglobal/log-bundle is a Symfony bundle, not a Laravel package. The README registration path (config/Bundles.php, app/AppKernel.php) and the class ETSGlobalLogBundle presuppose Symfony's HttpKernel, its DI container, Monolog handler wiring through monolog.handler.* tags, and Symfony's event system. Laravel has no bundle concept, no Kernel::registerBundles(), and its logging surface is Illuminate\Log\LogManager over Monolog channels configured in config/logging.php. There is no service provider, no facade, no auto-discovery entry. Any adoption inside a Laravel codebase is a port, not an install.
What is actually valuable here. The feature set is a coherent, opinionated correlation-ID design worth copying even if the code is never installed:
TokenCollection — a propagating trace token set intended to follow a request from app to app.global and process token lifecycle for inbound HTTP requests/responses and long-running processes (workers/daemons).app_name plus tokens on every record.NotFoundHttpException downgraded from error to info) — high value for signal-to-noise ratio.That is essentially a bespoke, pre-OpenTelemetry tracing layer. Modern equivalents (W3C traceparent, OpenTelemetry PHP, Laravel 11's Context facade) cover most of it with vendor-neutral semantics.
Integration feasibility: low-to-moderate, and mostly by extraction rather than consumption.
TokenCollection are plausibly framework-agnostic and could be lifted standalone.SlackHandler/SlackWebhookHandler constructor signatures changed materially across those majors, so the "extended Slack handler" is the most fragile piece.Technical risk: high, driven by provenance, not code quality.
Key questions to resolve before any commitment:
composer.json declare, and does it install cleanly alongside our Laravel and Monolog major?TokenCollection static/singleton state, or request-scoped? What resets it between requests and between queue jobs?traceparent or a de facto standard (X-Request-Id)?symfony/http-client, and would that pull a parallel HTTP stack into a Guzzle-based Laravel app?NotFoundHttpException) with no Laravel mapping hook?Stack fit: do not install; reimplement the contract. The bundle's value is its design decisions, not its Symfony plumbing. A Laravel-native equivalent is roughly 200–400 lines and removes every dependency and lifecycle risk above. Recommended posture: treat this repository as a reference implementation and design document, and cite it as prior art in the ADR rather than as a dependency.
If a direct dependency is mandated, contain it. Restrict adoption to the framework-agnostic surface — TokenCollection plus the Guzzle middleware — pulled in as a vendored/forked subtree. Do not register the bundle, do not rely on its Monolog processors, and do not use its Slack handler. Wrap the extracted pieces behind our own interfaces so they can be replaced by OpenTelemetry later without touching call sites.
Migration path (phased, ~3 sprints for a mid-size app):
X-Request-Id, X-Global-Token, X-Process-Token, or align to traceparent), the token format, max length, and the trust boundary for client-supplied values. This is the durable decision; everything else is implementation detail.app_name + tokens into Log::withContext() (Laravel 11+ Context) and into a request-scoped TokenStore singleton.Http::withHeaders() defaults so Illuminate\Support\Facades\Http inherits it.bootstrap/app.php withExceptions() or a Monolog processor, mapping ModelNotFoundException/NotFoundHttpException to warning, auth failures to notice. This is the single highest-ROI feature ported from the bundle.SlackWebhookHandler wrapped in FingersCrossedHandler and a BufferHandler/queued job rather than the bundle's handler. Keep the custom formatter concept, drop the code.TokenStore on JobProcessing and in Octane's request-reset listener. This is where the original bundle is weakest and where we must exceed it.Compatibility work to schedule explicitly: a Composer dry-run probe (composer require --dry-run) against the target Laravel major, a PHP 8.2/8.3 matrix run, and a decision record on whether Monolog 3's handler signatures invalidate the Slack and processor components. Assume they do.
Sequencing rationale: contract → inbound → outbound → leveling → notifications → async. Each phase is independently shippable and observable, and phases 1–3 deliver the majority of the tracing value without touching logging configuration risk.
Maintenance. Effectively fork-and-own. With zero external dependents, upstream will not be exercised by anyone but ETSGlobal's own applications, and our issues will not be prioritized. Budget for a named owner plus a periodic upstream diff review. If we vendor, pin to a commit SHA rather than a version range — the 2026-03-20 release date alongside a Travis badge suggests irregular, unversioned publishing cadence.
Support. No SLA, no documented upgrade guide, no security policy. Escalation path is a GitHub issue on a repository with no visible community. Treat support cost as internal, not vendor-provided.
Scaling. Header propagation itself is negligible — a few dozen bytes per hop. The real scaling risks are elsewhere:
FingersCrossed-gated, or moved to a queued job. Never allow it to throw into the request lifecycle.app_name increases index cardinality; token-per-request fields are fine for filtering but must not become high-cardinality metric labels.process token tracing in daemons — good intent, but under Octane/queue workers we must verify reset semantics ourselves. The failure mode is silent cross-request contamination, which is worse than no tracing.Failure modes to design against:
| Failure | Impact | Mitigation |
|---|---|---|
| Token silently absent on one hop | Trace chain breaks with no error | Assert token presence in dev/test; alert on missing-token rate |
| Client-supplied token trusted | Log injection, cardinality blowup, forged trace lineage | Validate/regenerate at the edge; length and charset allowlist |
| Static token state under Octane | Wrong correlation IDs across concurrent requests | Request-scoped binding + explicit reset listeners |
| Slack handler throws | 500s on paths that should have succeeded | Wrap in WhatFailureGroupHandler / queue it |
| Monolog major conflict | Resolution failure or silent handler no-op | Pin and verify in CI; integration test that asserts a handler fires |
| Bundle registered but listeners not firing | "Enabled" logging that does nothing | Smoke test emitting a log and asserting context keys in the output |
| Abandoned upstream | Unpatched PHP 8.x deprecations | Fork, vendor, or replace with OpenTelemetry |
Ramp-up. Low for engineers with Symfony DI experience — the README plus source is sufficient. Medium for a Laravel-only team, because the bundle's mental model (container compiler passes, tagged handlers, kernel listeners) does not transfer, and engineers will spend more time understanding Symfony wiring than the logging behaviour itself. Budget half a day of onboarding for the concepts and a day for the Laravel-native port.
Strategic recommendation. Score 14.3/100, 0 stars, 0 dependents is a clear signal: do not add this as a runtime dependency. Adopt the correlation-ID and exception-leveling patterns into a small in-house Laravel package, and set OpenTelemetry (or at minimum traceparent alignment) as the forward path so the correlation contract survives the next tooling change. If the organization already runs Symfony services on this bundle, the correct TPM move is a cross-team correlation-contract standard — including queue and scheduled-job propagation — that both the Symfony and Laravel sides implement independently.
How can I help you explore Laravel packages today?