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

Utils.log.psr.multi Logger Laravel Package

mouf/utils.log.psr.multi-logger

A PSR-3 compatible multi-logger for the Mouf framework that fans out each log message to several underlying loggers at once, letting you route logs to multiple destinations through a single PSR-3 interface, wired up via Mouf's dependency injection.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a thin PSR-3 decorator: a MultiLogger that implements LoggerInterface and fans each log() call out to a set of injected loggers. Conceptually this is a clean seam, but in a Laravel codebase it is functionally redundant — Laravel's stack driver (config/logging.php) already composes multiple channels behind one PSR-3 facade, with config caching, channel-level processors, and withContext semantics that this package does not know about. The only genuinely additive use case is a framework-agnostic seam: shared libraries or packages that must emit to several sinks without depending on Illuminate\Log\LogManager. If the team's need is "write to stderr and an audit channel from Laravel," the built-in stack channel wins on every axis.

Integration feasibility. Low effort, non-trivial wiring risk. There is no Laravel service provider, no config stub, no facade. Two viable paths:

  • (a) Container binding — construct new MultiLogger([Log::channel('app'), Log::channel('audit')]) in AppServiceProvider::register() and bind it to an aliased interface. Do not overwrite the global Psr\Log\LoggerInterface binding without a feature flag; that silently re-routes every Log:: call, including framework internals.
  • (b) Custom driver — Log::extend('multi', fn ($app, $config) => new MultiLogger(...)) plus a channel entry in config/logging.php. This is the more idiomatic path and survives config:cache, but it is real code you now own, which raises the fair question of why you would not just use driver => stack.

Technical risk. Code risk is negligible (the surface is ~a few dozen lines). Dependency and stewardship risk is high:

  • PSR-3 major-version conflict is the gating item. Laravel 9/10/11 ship Monolog 3, which requires psr/log ^3. A Mouf-era package pinning psr/log ^1.0 will block composer require outright. The LoggerInterface signatures changed across v1/v2/v3 (void return types in v2+), so even a soft constraint can produce fatal signature errors at runtime.
  • Ecosystem drag. Mouf packages historically pull mouf/* container/compat dependencies. Any transitive DI framework in a Laravel app is an unacceptable blast radius.
  • Adoption signal. 3 stars, 0 dependents, single-vendor origin — bus factor of one. The 0.045 score is a fair prior, not noise.
  • Behavioral unknowns. Does one throwing child abort the fan-out or is it isolated? Does it implement withContext/LoggerAwareInterface immutably or mutate? Neither is documented in the description.

Key questions for the maintainer/team before proceeding:

  1. What is the exact psr/log and php constraint in composer.json, and does it resolve against our target Laravel's Monolog 3 stack?
  2. Are there any non-psr/log transitive dependencies (specifically mouf/mouf or mouf/utils.common)?
  3. Is a failing child logger isolated, or does it propagate and turn a log call into a 500?
  4. Does it honor Laravel's context/processor pipeline (RequestId, withContext, Monolog processors) per child, or bypass it?
  5. What is the actual user story that the native stack driver cannot satisfy?

Integration Approach

Stack fit. Assume a Laravel 10/11 target on PHP 8.2/8.3. The package is PSR-3, so it speaks the right language, but it sits beside Laravel's logging rather than inside it. Treat it as a library-level decorator, not a logging subsystem.

Migration path.

  1. Dependency probe first (½ day). composer require mouf/utils.log.psr.multi-logger --dry-run in a throwaway branch, then composer why-not psr/log ^3.0. If it hard-conflicts, stop — the evaluation is over and the answer is "write 30 lines in-house."
  2. If it resolves, register as a named binding, never the global one. Wrap existing Laravel channels (Log::channel('app'), Log::channel('audit')) as children, so enrichment, formatters, and handlers stay where the team already configures them.
  3. Prefer the custom-driver route (Log::extend('multi', ...)) over container override — it composes with config:cache, keeps channel config declarative, and is discoverable for the next engineer.
  4. Contract test. One feature test asserting a single Log::info('x', $ctx) reaches every child with identical message and context, plus one test asserting a throwing child does not fail the request.

Compatibility checks. Verify LoggerInterface method signatures match the installed psr/log major (return types matter), confirm MultiLogger's constructor shape (array vs. variadic), and confirm no Mouf container coupling. If any of these are ambiguous from source, that ambiguity is itself the finding.

Sequencing. Probe → contract test → pilot in one non-critical service → 30-day observation → go/no-go on broader use. In parallel, price the alternative: Laravel stack channel (zero cost, config-only) and an in-house CompositeLogger implements LoggerInterface (~30 LOC, your license, your tests, no psr/log pinning). Realistically the build option should be the default and this package the challenger.

Recommendation. Do not adopt as a platform dependency. Either use the native stack driver, or vendor a ~30-line composite logger into app/Support/Logging with an equivalent test. Reserve this package for the narrow case where a shared, framework-agnostic library must fan out without Laravel — and even then, confirm the psr/log constraint is ^2 || ^3 first.

Operational Impact

Maintenance. This is the dominant cost. Three stars and zero dependents means the package's release cadence will not track Laravel's. Every Laravel major bump becomes a manual compatibility audit of a dependency you cannot influence. Because the surface is tiny, the correct operational posture is assume you will own the fork within 12 months — so plan the exit before the entry. MIT license makes vendoring or forking legally frictionless; that is the package's best attribute.

Support. No vendor, no SLA, GitHub issues only, small Mouf community. Any incident routes to your own on-call. That is acceptable for a 30-line utility and unacceptable for anything on the request path you cannot reason about. Budget an internal owner by name.

Scaling. Fan-out is synchronous and in-process: each log event costs N handler invocations. If any child is a network sink (remote syslog, HTTP log shipper), that child becomes the latency floor for every request that logs. There is no buffering, sampling, or async hand-off. Secondary effect is log volume multiplication — N sinks means N ingest bills. Validate against current Datadog/CloudWatch spend before promoting a multi channel into a high-traffic path; a fan-out that duplicates verbose debug logs across two paid sinks can be a five-figure annual line item.

Failure modes to design against.

  • Child exception propagation — one flaky handler taking down a request is the worst-case failure and the first thing to test.
  • Silent partial loss — if a child fails and is swallowed, you lose a sink without an alert. Add a health check or a dead-letter assertion per child.
  • Double logging / recursion — wrapping a logger that itself writes back through the composite; also duplicate records if the composite is bound globally and a channel is also individually invoked.
  • Lost enrichment — context added by Laravel middleware or Monolog processors is only present if each child channel is properly configured; a raw PSR-3 child will emit bare records.
  • Config drift — a container-level binding is invisible to config:cache and to anyone reading config/logging.php; the custom-driver route mitigates this.

Ramp-up. Effectively zero — it is PSR-3, and any engineer who knows LoggerInterface is productive in under an hour. The cognitive load is not in the API; it is in the organizational load of owning an orphaned dependency and remembering that a global binding override changes every log line in the application. That asymmetry — trivial to learn, easy to forget, expensive to debug — is the core argument for preferring the native stack driver or an in-house implementation.

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.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json