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

Log Target File Laravel Package

yiisoft/log-target-file

File log target for Yii's logging library that writes application messages to configurable log files. Supports level and category filtering, custom formatting, size-based rotation, and retention of rotated files—a straightforward choice for persistent file-based logging in Yii apps.

Deep Wiki
Context7

Getting Started

Install the package and its logging core:

composer require yiisoft/log-target-file

This pulls in yiisoft/log (which provides Logger, LoggerInterface, and AbstractTarget). There is nothing to configure out of the box — the package is a target, not a framework glue layer.

Minimal wiring

use Yiisoft\Log\Logger;
use Yiisoft\Log\Target\File\FileTarget;

$target = new FileTarget('/var/www/app/runtime/logs/app.log');

$logger = new Logger(['file' => $target]);

$logger->info('User {id} logged in', ['id' => 42]);
$logger->error('Payment failed', ['orderId' => 1001, 'exception' => $e]);

Where to look first

  1. FileTarget — the class you will actually touch. Public API: setLogFile(), setFileRotator(), setFormat(), and the setLevels() inherited from AbstractTarget.
  2. FileRotator — size-based rotation, retention count, compression, file mode.
  3. FileRotatorInterface — implement this if you want a custom rotation policy (e.g. daily rotation, size-aware naming, S3 upload after rotation).

First real use case

An application error/log file in runtime/logs/app.log with size-based rotation:

$target = new FileTarget('/var/www/app/runtime/logs/app.log');
$target->setFileRotator(new FileRotator(
    maxFileSize: 10 * 1024 * 1024, // 10 MB
    maxFiles: 5,
    compress: true,
));

$logger = new Logger(['file' => $target]);

Implementation Patterns

DI container configuration (Yii3 style)

In a Yii3 application, register the target once and let LoggerInterface be autowired. The typical place is config/common/di/logger.php:

use Yiisoft\Log\Logger;
use Yiisoft\Log\LoggerInterface;
use Yiisoft\Log\Target\File\FileTarget;
use Yiisoft\Log\Target\File\FileRotator;
use Yiisoft\Definitions\Reference;

return [
    LoggerInterface::class => [
        'class' => Logger::class,
        '__construct()' => [
            'targets' => [
                'file' => Reference::to(FileTarget::class),
            ],
        ],
    ],
    FileTarget::class => [
        '__construct()' => [
            'logFile' => '@runtime/logs/app.log',
        ],
        'setFileRotator()' => [
            new FileRotator(maxFileSize: 10_485_760, maxFiles: 5, compress: true),
        ],
    ],
];

Multiple targets

Logger accepts a map of targets keyed by name. Use one for structured app logs and another for errors-only:

$logger = new Logger([
    'file'    => $appFileTarget,     // all levels
    'errors'  => $errorsFileTarget,  // errors only
]);

$errorsFileTarget->setLevels(['error', 'warning']);

This is the cheapest way to get a separate errors.log without writing any custom filtering logic.

Placeholder formatting

The target renders messages using the Yii format string, so keep log calls structured:

// In the message
$logger->warning('Slow query {duration}ms: {sql}', [
    'duration' => 1200,
    'sql'      => 'SELECT ...',
]);

// Custom format (default is roughly "{timestamp} [{level}] {message}")
$target->setFormat("{timestamp} {level} {message}\n");

Customize the timestamp via setTimestampFormat() if you need ISO 8601, RFC 5424, etc. Prefer a UTC format for correlation across services.

Rotation in production

FileRotator triggers during a write whenever the file would exceed maxFileSize. Set maxFiles to match your retention budget, and enable compress (gzip) if you're disk-constrained. Rotated files are named with a numeric suffix (app.log.1, app.log.2, …), oldest first, and compressed ones get .gz.

Long-running workers

The target buffers through the logger; in short-lived requests, PHP flushes on shutdown. In queue workers, cron daemons, or Swoole/RoadRunner processes:

$logger->flush(); // after each job or batch

Alternatively, call flush() at natural boundaries (end of a job, before sleeping) rather than every line — flushing per message defeats the buffering benefit.

Gotchas and Tips

Writable path is on you. The target requires the parent directory of logFile to exist and be writable. Missing directories or a read-only mount throws a RuntimeException on the first write, not at construction — so a misconfigured path fails silently until the first log line, often inside an error handler where the failure is masked. Validate the path in a bootstrap step.

Permission mode quirks. The file is created with a default mode you can override through FileRotator (fileMode, typically 0775). On multi-user hosts, default umask may produce group-unreadable files; set fileMode explicitly if a log shipper runs as another user.

Default level filter drops debug. AbstractTarget historically filters to a conservative set (error, warning, info, trace, etc.). If your debug() calls don't appear, call setLevels($target->getLevels() + ['debug']) — the whitelist is exact, not severity-ordered. In production, keep debug off.

Rotation is not scheduled. It is evaluated on write. A low-traffic service can sit at 9.9 MB forever without ever rotating. If you need time-based rotation (daily, hourly), FileRotator won't help — implement FileRotatorInterface and check the mtime in rotate().

Compression requires zlib. compress: true uses gzip; if ext-zlib isn't loaded, rotation can fail at exactly the wrong moment (when the file is full). Add ext-zlib to composer.json requirements.

Open file handles and copy mode. On Windows or when another process holds the file, renaming a rotated file can fail. The rotator's copy-then-truncate behavior (rotateByCopy) exists for this; enable it if you see rotation errors on Windows or on network filesystems.

Concurrency. Multiple PHP-FPM workers appending to the same file are generally fine on local filesystems (append writes are atomic for small messages), but a single multi-line record can interleave with another worker's. Keep messages short, and avoid writing from both a web process and a long-running worker to the same file if you care about ordering. For high-volume concurrency, log to a dedicated file per pool or ship via a socket target instead.

Timestamp source. The timestamp comes from time(), not from the message — pass time() explicitly into context if you need the event time rather than the write time (matters for buffered long-running workers).

Testing. FileTarget writes to real files; in tests, point logFile at a tempnam() path under sys_get_temp_dir() and unlink it in tearDown. flush() immediately after the log call before asserting contents — otherwise the buffered message isn't on disk yet.

Extension point. All meaningful customization (rotation naming, retention, compression, external shipping) goes through FileRotatorInterface::rotate(). Implement it and inject with setFileRotator() — no subclassing of FileTarget is needed.

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.
teamzac/geocoder
ideatica/config-writer
keaton-php/pipe-dream
jacksonwebservices/laravel-user-suite
maksimru/conditional-laravel-debugbar
gismatul/nova-support-chat
gismatul/laravel-support-chat
networkrailbusinesssystems/oracle-api
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
ably/pubsub-server
mstfkhazaal/defender
mfonte/base62x
karnoweb/metapilot
tobya/bcsapiwrapper
swalker2/cpanel