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

Psr Logger Laravel Package

roadrunner/psr-logger

PSR-3 logging adapter for RoadRunner. Route standard PSR-3 log messages through RoadRunner's logging facility so worker output stays centralized, structured, and consistent with the application server's configuration and transports. Works with any PSR-3-compatible framework or library.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a very small, single-purpose adapter: it gives you a PSR-3 LoggerInterface implementation that pushes log records through RoadRunner's logger RPC to the RoadRunner server, instead of writing to stdout/stderr directly from PHP. That's the entire value proposition — if you're writing to echo inside a worker you're interleaving output with the protocol stream; this routes it properly.

Minimal steps:

composer require roadrunner/psr-logger
use RoadRunner\Logger\Logger;
use Spiral\RoadRunner\Worker;

$logger = new Logger(Worker::create());

$logger->info('Worker booted', ['pid' => getmypid()]);

Where to look first: the package is only a handful of files under src/, so read them all before you wire anything up. Expect to find the main Logger class plus StdoutLogger / StderrLogger variants (or equivalents) and a small factory. Confirm three things in the source before designing around it: (1) whether PSR-3 {placeholder} interpolation is implemented, (2) how Throwable values in context['exception'] are serialized, and (3) whether the RPC handle is created lazily or eagerly.

First real use case: replace the ad-hoc fwrite(STDERR, ...) / echo calls scattered through a long-running RoadRunner worker with an injected PSR-3 logger, so log lines get the server-side formatter, timestamps, and level filtering from .rr.yaml rather than whatever your worker happened to print.

Implementation Patterns

Inject the interface, not the class. Bind Psr\Log\LoggerInterface to the RoadRunner logger in your container and let application services type-hint the interface. This is the whole point of it being PSR-3 — you can swap in Monolog for tests and CLI commands and keep the production path on RoadRunner.

// bootstrap (Laravel-ish)
$this->app->singleton(LoggerInterface::class, fn () => new Logger(Worker::create()));

Framework bridge — use it as one channel, not the only one. In Laravel/Symfony you almost certainly still want Monolog for file logging, and you add this as an extra sink for worker-context messages. Practical shape: a Monolog Logger with a handler that forwards to the RoadRunner logger, or simply resolve LoggerInterface::class to RoadRunner inside worker entrypoints and to the framework logger elsewhere. Don't rip out Monolog; you lose channels, processors, and rotation.

Keep a request-scoped child logger. Since this is PSR-3, use $logger->withName()/context-merging in your own wrapper (PSR-3 has no withContext, so implement a tiny ContextLogger decorator) to attach request_id / trace_id once per job and let every downstream call inherit it. RoadRunner jobs are long-lived, so per-job context is cheap and enormously useful when you're grepping aggregated logs.

Log at boundaries, not in loops. Each call is an RPC round-trip to the server process. Log job start/end, retry attempts, and exceptions. Do not log per-row inside an import loop — batch a summary instead.

Use StdoutLogger/StderrLogger deliberately. If the variant exists for explicitly writing through RR's stdout/stderr channels, prefer StderrLogger for diagnostics: it survives even when the server-side logger pipeline is misconfigured, and it won't be confused with normal application log stream.

Structured context beats string interpolation. Pass scalars and small arrays in context; the RoadRunner server formatter handles the rest. Avoid pre-formatting exception messages into strings — pass ['exception' => $e] and let the adapter/server decide how much detail (stack trace, previous chain) to emit, gated by environment.

Gotchas and Tips

  • It only works inside a RoadRunner worker. There is no fallback. Called from a plain CLI script, a queue consumer under a different runtime, or a unit test, the underlying worker/RPC won't be there and you'll get an exception or a silent no-op depending on lazy-init behavior. Always wrap the binding so non-RR contexts resolve to a different logger.
  • Level filtering lives server-side. .rr.yaml's logs section (mode, level, encoding, output) controls what actually gets written. Your PHP $logger->debug() may still pay the full RPC cost and be dropped at the server. If debug logging is expensive in your code path, check the configured level before building the payload.
  • The adapter is thin and probably does little validation. Verify placeholder interpolation yourself — many minimal PSR-3 implementations leave {foo} in the message untouched, which silently breaks dashboards. If unsure, pre-interpolate.
  • Eager vs lazy RPC handle. If the constructor eagerly creates a worker/RPC connection, constructing the logger in a service provider during a non-worker boot will blow up. Defer construction behind a closure/factory.
  • Blocking I/O in hot paths. Every record is a synchronous RPC. In a high-throughput worker this is measurable latency. Consider an in-memory buffer flushed at job end (a simple BufferLogger decorator wrapping it) rather than one RPC per line.
  • Exception serialization is the usual weak spot. Confirm whether context['exception'] is rendered with the full trace or dropped/cast to string. If it's truncated, log the trace separately or configure .rr.yaml output for it.
  • Debugging tip: if logs vanish, first bypass the package — write to fwrite(STDERR, "ping\n") in the worker and see if it reaches the server's output. That isolates "RPC/logger config is broken" from "my logger binding is wrong." Also run with rr serve -v/debug mode to see the server-side logger pipeline.
  • Version pinning. The project has essentially no downstream dependents and a very small user base, so treat releases as low-signal for compatibility. Pin an exact version, and read the diff before bumping — the API surface is tiny enough that a full read is cheap.
  • Extension points are limited. Don't expect processors, handlers, or formatter pluggability. If you need structured JSON with custom fields, route through Monolog with a PsrLogMessageProcessor-style pipeline and use this package only as the final transport handler.
  • Honest alternative: for many projects a Monolog StreamHandler pointed at php://stderr gets you 90% of the benefit with zero new dependency, because RoadRunner already captures worker stderr. Reach for this package when you specifically want server-side level config, consistent formatting across all RoadRunner SDKs (Go, Python), and to keep the protocol stream clean.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib