mb4it / logger
File-based PSR-3 logger with channel support.
Requires
- php: >=8.1
- mb4it/filesystem: ^1.0
- psr/log: ^3.0
Requires (Dev)
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2026-02-20 08:47:59 UTC
README
PSR-3 compatible file logger with channel support (subdirectories), filename patterns, and filesystem abstraction via mb4it/filesystem.
Installation
composer require mb4it/logger
Requirements:
- PHP 8.1+
psr/log^3.0mb4it/filesystem^1.0
Overview
- Log path is set when creating the logger (
basePath). - Channel (
channel('payments')) is a logger that writes to a subdirectory or set of files underbasePath. - File operations use
mb4it/filesystem. - The logger implements
Psr\Log\LoggerInterface(viaPsr\Log\AbstractLogger).
Basic usage (single app.log file)
<?php use MB\Logger\Logger; $logger = new Logger(__DIR__ . '/storage/logs'); $logger->info('User logged in', ['user_id' => 123]); // creates: storage/logs/app.log
- The first constructor argument is the base path to the log directory.
- The directory is created automatically.
- All levels (
info,error,debug, …) are written toapp.logby default.
Quick start with Logger::create(...)
<?php use MB\Logger\Logger; $logger = Logger::create(__DIR__ . '/storage/logs'); $logger->info('Quick start'); // storage/logs/app.log
You can pass a filename pattern:
<?php use MB\Logger\Logger; $logger = Logger::create(__DIR__ . '/storage/logs', 'error_{date}.log'); $logger->error('Critical failure'); // storage/logs/error_YYYY-MM-DD.log
Driver selection in create(...):
- If the pattern contains
{date}→dailydriver is used. - Otherwise →
singledriver is used.
Channels as subdirectories (channel())
<?php use MB\Logger\Logger; /** @var \Psr\Log\LoggerInterface $logger */ $logger = new Logger(__DIR__ . '/storage/logs'); // channel payments → storage/logs/payments $paymentsLogger = $logger->channel('payments'); $paymentsLogger->info('Payment processed', ['order_id' => 10]); // channel auth → storage/logs/auth $authLogger = $logger->channel('auth'); $authLogger->warning('User failed login', ['email' => 'test@example.com']);
Resulting files:
storage/logs/app.log— default channel.storage/logs/payments/app.log— channelpayments.storage/logs/auth/app.log— channelauth.
Advanced configuration: LoggerConfig
Use config for flexible setup (separate error files, patterns, etc.).
driver: single vs daily
single— one file per channel (no date-based rotation); writes tofilenamePattern.daily— date-based filenames; typically used with patterns like{date}.logorerror_{date}.log.- Both support
path,filenamePattern,dateFormat, andlevels.
Example: error files by date error_YYYY-MM-DD.log
<?php use MB\Logger\Logger; use MB\Logger\LoggerConfig; use Psr\Log\LogLevel; $config = LoggerConfig::fromArray([ 'basePath' => __DIR__ . '/storage/logs', 'defaultChannel' => 'app', 'channels' => [ 'app' => [ 'driver' => 'single', 'path' => '', 'filenamePattern' => 'app.log', ], 'error' => [ 'driver' => 'daily', 'path' => 'errors', 'filenamePattern' => 'error_{date}.log', 'dateFormat' => 'Y-m-d', 'levels' => [ LogLevel::ERROR, LogLevel::CRITICAL, LogLevel::ALERT, LogLevel::EMERGENCY, ], ], ], ]); $logger = Logger::fromConfig($config); $logger->info('Regular message'); // storage/logs/app.log $logger->error('Something failed'); // storage/logs/errors/error_YYYY-MM-DD.log
{date}is formatted usingdateFormat(defaultY-m-d).levelsrestricts which levels are written to that channel.
Example: pattern {level}_{date}.log
<?php use MB\Logger\LoggerConfig; use MB\Logger\Logger; $config = LoggerConfig::fromArray([ 'basePath' => __DIR__ . '/storage/logs', 'defaultChannel' => 'app', 'channels' => [ 'by_level' => [ 'driver' => 'single', 'path' => 'by-level', 'filenamePattern' => '{level}_{date}.log', 'dateFormat' => 'Y-m-d', ], ], ]); $logger = Logger::fromConfig($config); $logger->info('Info msg'); // storage/logs/by-level/info_YYYY-MM-DD.log $logger->error('Error msg'); // storage/logs/by-level/error_YYYY-MM-DD.log
Placeholders in filenamePattern
Available:
{date}— formatted with channeldateFormat.{level}— level in lowercase (error,info, …).{LEVEL}— level in uppercase (ERROR,INFO, …).
Logger factory (LoggerFactory)
Convenience methods:
LoggerFactory::single($basePath, $filePattern = 'app.log', ...)— single file (driver: single).LoggerFactory::daily($basePath, $filePattern = '{date}.log', ...)— daily rotation (driver: daily).
<?php use MB\Logger\LoggerFactory; $logger = LoggerFactory::single(__DIR__ . '/storage/logs', 'app.log'); $logger->info('Hello'); // Daily log to e.g. 2025-02-18.log $dailyLogger = LoggerFactory::daily(__DIR__ . '/storage/logs'); $dailyLogger->info('Daily entry');
Building from array (fromArray)
For complex config (multiple channels, levels, patterns):
<?php use MB\Logger\LoggerFactory; use Psr\Log\LogLevel; $logger = LoggerFactory::fromArray([ 'basePath' => __DIR__ . '/storage/logs', 'defaultChannel' => 'app', 'channels' => [ 'app' => [ 'driver' => 'single', 'path' => '', 'filenamePattern' => 'app.log', ], 'error' => [ 'driver' => 'daily', 'path' => 'errors', 'filenamePattern' => 'error_{date}.log', 'dateFormat' => 'Y-m-d', 'levels' => [ LogLevel::ERROR, LogLevel::CRITICAL, ], ], ], ]);
Log format and PSR-3
- The logger implements
Psr\Log\LoggerInterface(viaPsr\Log\AbstractLogger), so it can be used by type. - All standard methods are available:
emergency,alert,critical,error,warning,notice,info,debug,log. - Invalid levels throw
Psr\Log\InvalidArgumentException.
Default line format (MB\Logger\Formatter\LineFormatter):
[YYYY-mm-dd HH:ii:ss][LEVEL] message {"context_key":"value", ...}
Context:
- Placeholders like
{user_id}in the message are replaced only for scalar andStringablevalues. - Context is appended as JSON; values are stringified (objects become
object(ClassName)).
Array format (ArrayFormatter)
For one-JSON-object-per-line (e.g. for parsing or streaming), use ArrayFormatter:
<?php use MB\Logger\Logger; use MB\Logger\Formatter\ArrayFormatter; $logger = Logger::create(__DIR__ . '/storage/logs', 'app.log', new ArrayFormatter()); $logger->info('User action', ['user_id' => 42]);
Each line in the file will look like:
{"date":"2025-02-18 12:00:00","level":"INFO","message":"User action","context":{"user_id":"42"}}
Filesystem (mb4it/filesystem)
The logger does not use raw file_put_contents or mkdir:
- An instance of
MB\Filesystem\Filesystemis used withbasePathfromLoggerConfig. - Logs are written via
updateContent($path, $updater, $atomic = false):atomic = falseis faster and sufficient for logs.- You can inject a custom
FilesysteminLogger::fromConfig()or theLoggerconstructor.
Tests
PHPUnit tests cover:
- Base log directory creation.
- Writing to default
app.log. - Channel subdirectories (
channel('payments')). - Filename patterns (
error_{date}.log,{level}_{date}.log). - Daily driver and date-based filenames.
- Level filtering (
levelsin channel config). - PSR-3 compliance (levels,
InvalidArgumentExceptionfor invalid level).
Run tests:
composer install vendor/bin/phpunit