yiisoft/log
PSR-3-compatible logging library for Yii with configurable targets, message filtering, formatting, and context support. Route logs to files, syslog, email, or custom targets with flexible severity handling.
composer require yiisoft/log — no framework required; it's a standalone PSR-3 implementation from the Yii3 ecosystem.use Yiisoft\Log\Logger;
use Yiisoft\Log\Target\File\FileTarget;
$logger = new Logger();
$logger->addTarget(new FileTarget('/var/log/app.log'));
$logger->info('app started', ['pid' => getmypid()]);
$logger->flush();
Logger (PSR-3 entry points + flush() + setFlushInterval()), Target (the abstract base — this is your extension point), and Message (the object your targets actually receive).error_log() / var_dump() calls with a single injected logger writing to a rotated file, with ERROR+ routed somewhere a human will see.Psr\Log\LoggerInterface in services. Reach for Yiisoft\Log\LoggerInterface only when you specifically need flush() or setFlushInterval().Logger as a shared singleton in your DI container and build targets from config, not inline in services. Otherwise each new Logger buffers its own messages and flushes at unpredictable times.StreamTarget to stderr/stdout, all levels.FileTarget + FileRotator, WARNING+.EmailTarget or SyslogTarget, ERROR+ only, via setLevels().setLevels([LogLevel::ERROR, LogLevel::CRITICAL])) keeps noise down without touching call sites.{placeholder} interpolation from the PSR-3 context array, so log calls can stay readable: $logger->error('Payment failed for {orderId}', ['orderId' => $id]).Target, implement export(array $messages): void. Override collect() only if you need per-message buffering (rate limits, batching to a remote API).StreamTarget pointed at php://memory, or a tiny in-memory Target subclass, and assert on captured Message objects rather than string-matching output.flush(). This is the #1 surprise. Register register_shutdown_function(fn () => $logger->flush(true)) in your bootstrap, and call flush() in job/request teardown — otherwise a fatal error loses the messages that explain it.FileTarget grows forever; pass a FileRotator (max size, retained files) if you care about disk.Target::export() runs synchronously in your request. A bad path, full disk, or unwritable directory throws inside a log call — make the directory writable up front, and consider guarding custom targets in a try/catch.log($level, ...) accepts any string per PSR-3, but Yii filters compare against LogLevel::* constants — stick to the constants or your setLevels() config won't match.Array.flush() in tearDown(); buffered messages survive across test methods if the container shares one Logger.Target for new sinks, implement FileRotatorInterface for custom retention, and swap Logger behind its interface for a null-logger in benchmarks.How can I help you explore Laravel packages today?