keboola/logging-bundle
A Symfony bundle that adds Keboola-specific logging to your application, wiring Monolog handlers, processors, and configuration so logs are structured, consistent, and ready for Keboola's logging infrastructure. Drop it in, configure a few options, and get production-ready logging without boilerplat...
What this package actually is. Despite the Laravel/PHP framing, keboola/logging-bundle is a Symfony bundle, not a Laravel package. It ships three classes: a DependencyInjection\KeboolaLoggingExtension that runs a function_exists('DDTrace\current_context') check at container compile time, a Monolog\DataDogContextProcessor tagged monolog.processor, and the bundle registration class. Its entire functional surface is: if the ddtrace PHP extension is loaded, attach extra.dd.trace_id and extra.dd.span_id to every Monolog record so Datadog can correlate logs to APM traces. There is no configuration, no service provider, no facade.
What 2.0.0 changes. The 2.0.0 release is a manifest-level breaking change, not a functional one: Monolog 3.x is now the only supported Monolog, and Symfony 7.x is now explicitly supported (Symfony 6.4 presumably retained). Nothing in the release notes suggests the processor logic, the extra.dd.* key contract, the DI guard, the missing php constraint, or the two-branch test coverage changed. Operationally this is good news for us — it confirms the package has been formalised onto the stack we would actually use (Laravel 10/11/12 all ship Monolog 3) — but it means every technical risk identified below survives 2.0.0 intact.
Architecture fit.
ddtrace extension — log/trace correlation is a real gap in most Laravel Datadog setups and this is the canonical fix.Symfony\Component\HttpKernel\Bundle\Bundle and DependencyInjection\Extension are dead weight in a Laravel app. Installing it pulls Symfony HttpKernel/DI/Config transitively for ~60 lines of logic. 2.0.0 does not change this; if anything, declaring Symfony 7 support widens the transitive surface a Laravel consumer inherits from a package that contributes one processor.Integration feasibility.
config/logging.php supports 'tap' => [ProcessorClass::class] per channel. That is a one-file change and gets the identical behaviour without booting Symfony DI.composer require keboola/logging-bundle:^2.0 and reference only Keboola\LoggingBundle\Monolog\DataDogContextProcessor in the channel tap; (b) vendor the ~20-line processor into app/Logging/ with attribution under MIT. Given the adoption signals below, (b) is the defensible default and (a) the fallback if Keboola ships fixes we want. 2.0.0 marginally strengthens case (a) — it is evidence the package is maintained, and it removes the Monolog-2/Monolog-3 ambiguity a vendored copy would otherwise have to carry — but it does not fix the mirror or the missing php constraint.__invoke(LogRecord $record): LogRecord) and the LogRecord API rather than array $record; the 2.0.0 breaking change is precisely this surface. A stale vendored copy silently misbehaves against Monolog 3.Technical risk.
keboola/logging-bundle is a read-only CI re-split of libs/logging-bundle/ in keboola/platform-libraries. PRs against it are force-overwritten and closed. Any bug we hit means cloning a large monorepo, or forking. For a 60-line dependency that is a poor trade — and 2.0.0 demonstrates the churn mode: the mirror is force-pushed on every green monorepo build, so derived tags can include a major version bump for what is, functionally, a composer.json edit.extra.dd.trace_id / extra.dd.span_id must survive the Monolog formatter and then be remapped in Datadog's log pipeline. Monolog's default JsonFormatter nests these under extra, so out of the box Datadog will not correlate — you need a formatter that flattens extra, or a pipeline remapper targeting extra.dd.trace_id. A rename or refactor breaks correlation with zero test failure and zero runtime error. Nothing in 2.0.0 addresses this.php constraint in composer.json. Composer will happily install on PHP 8.4/8.5 where nothing is tested. CI reportedly covers Symfony 6.4/7.2 on PHP 8.1/8.3; Symfony 7.x support in 2.0.0 implies PHP 8.2+ is exercised for that leg, but PHP 8.4 and Symfony 8 remain uncovered. Open question: did 2.0.0 add a php constraint? The release notes don't say, and this is the one line item that would move the risk needle.config.policy.advisories.block=false in the package's own composer config (a CI workaround) does not propagate to consumers, but it signals dependency resolution friction that consumers may inherit.Key questions.
ddtrace extension present in every runtime that emits logs — php-fpm, queue:work supervisors, schedule:run, and any Lambda/container sidecars? Correlation is per-process.extra to top level? If not, who owns the Datadog log-pipeline remapper?php constraint, and is Symfony 6.4 still supported or are we forced onto 7.x? Read the actual composer.json, not the release notes.DD_SERVICE/DD_ENV injection sufficient?Stack fit.
ddtrace extension: the processor class is directly reusable, and as of 2.0.0 it is only usable there. The Symfony bundle wrapper is not. This is now a clean, unambiguous match with our target platform — no version-matrix hedging.LogManager already merges tap processors into the channel's Monolog logger, so no service provider is needed — this is the whole integration.LogRecord signature only if it is on Monolog 3, otherwise write it as a two-line adapter.Migration path.
ddtrace extension version and that DDTrace\current_context() returns non-null inside a web request and inside a queued job. This is the single go/no-go gate.app/Logging/DataDogContextProcessor.php (vendored, MIT header preserved) or composer require keboola/logging-bundle:^2.0. Pin the major — the mirror's derived tags have already taken one unexplained major jump.'tap' => [DataDogContextProcessor::class] on the stack/daily/stderr channels used in production; guard registration with function_exists so local and CI environments are unaffected.extra into the JSON root or add a Datadog pipeline remapper for extra.dd.trace_id → dd.trace_id.Compatibility.
php constraint — if it did, Composer will protect us; if not, it still won't.composer.json. Irrelevant to a Laravel tap integration, which never instantiates the bundle.extra is not used by Laravel internals, so overwriting risk is nil.DD_LOGS_INJECTION=true already does this at the tracer level and would make this package redundant. Check this first; it may obviate the entire evaluation, and 2.0.0 does not change that calculus.Sequencing.
DD_LOGS_INJECTION is off, verify extension presence across all runtimes, re-read the 2.0.0 composer.json for the php constraint, decide vendor vs. depend.extra.dd.trace_id appears when the extension is stubbed.Maintenance.
dd.trace_id/dd.span_id) is fixed. Vendoring shifts the burden from dependency management to a ~20-line file we own, which is the cheaper side of that trade at this scale. 2.0.0 strengthens this: the only change in a major release was a dependency-constraint edit, i.e. exactly the kind of churn a vendored copy is immune to.Support.
Scaling.
DDTrace\current_context() once per log record. At high log volume (thousands of records/sec across a fleet) this is a measurable but small per-record function call; benchmark before applying to chatty debug channels. Recommend production channels only.queue:work processes need the trace context to be refreshed per job; verify the processor isn't capturing a stale context from a prior job's span.Failure modes.
function_exists('DDTrace\current_context') in each container image.extra, or a Datadog pipeline remapper is edited → logs and traces stop joining, nothing fails. Mitigation: synthetic check that emits a log inside a known trace and asserts the join in Datadog; run post-deploy.dd.trace_id → breaks correlation invisibly. Mitigation: comment the contract in the vendored file and cover it with a unit test.DD_LOGS_INJECTION=true is enabled later — duplicate or conflicting fields. Mitigation: make it a mutually exclusive setting in the platform config.php constraint — only applies if we depend rather than vendor, and only if 2.0.0 did not add one.array $record signature. Mitigation: diff the vendored processor against 2.0.0 before merging.Ramp-up.
dd.trace_id, pipeline remappers, per-index enablement) and knowing that all three layers must align.How can I help you explore Laravel packages today?