monkeyscloud / monkeyslegion-logger
Advanced logger for the MonkeysLegion PHP framework.
Installs: 19
Dependents: 4
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/monkeyscloud/monkeyslegion-logger
Requires
- php: ^8.4
- psr/log: ^3.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.0@dev
README
A flexible, PSR-3 compliant PHP logging library with environment-aware logging, multiple drivers, and extensive configuration options.
Features
- ๐ฏ PSR-3 Compliant - Implements PSR-3 LoggerInterface
- ๐ Environment-Aware Logging - Smart logging based on environment
- ๐ Multiple Drivers - File, Console, Syslog, Error Log, Null, and Stack
- ๐จ Colorized Console Output - Beautiful colored terminal logs
- ๐ Log Level Filtering - Control what gets logged
- ๐ญ Custom Formatting - Flexible message formatting
- ๐ Stack Logger - Combine multiple loggers
- ๐ Daily Rotation - Automatic date-based log file rotation
- ๐ Circular Dependency Detection - Prevents infinite loops
- ๐งช Fully Tested - Comprehensive test coverage
- ๐ช Type-Safe - Full PHPStan level max compliance
Installation
composer require monkeyscloud/monkeyslegion-logger
Quick Start
use MonkeysLegion\Logger\Factory\LoggerFactory; // Load configuration $config = require 'config/logging.php'; // Create logger factory $factory = new LoggerFactory($config, 'production'); // Get default logger $logger = $factory->make(); // Start logging $logger->info('Application started', ['user_id' => 123]); $logger->error('Database connection failed', ['error' => $e->getMessage()]);
Configuration
Create a configuration file (e.g., config/logging.php):
<?php return [ 'default' => $_ENV['LOG_CHANNEL'] ?? 'stack', 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['daily', 'console'], ], 'single' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'level' => 'debug', ], 'daily' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, // Enable daily rotation 'date_format' => 'Y-m-d', // Optional, defaults to Y-m-d 'level' => 'debug', 'format' => '[{timestamp}] [{env}] {level}: {message} {context}', ], 'console' => [ 'driver' => 'console', 'level' => 'debug', 'colorize' => true, 'format' => '[{env}] {level}: {message} {context}', ], 'syslog' => [ 'driver' => 'syslog', 'level' => 'warning', 'ident' => 'my-app', 'facility' => LOG_USER, ], 'errorlog' => [ 'driver' => 'errorlog', 'level' => 'error', 'message_type' => 0, ], 'null' => [ 'driver' => 'null', ], ], ];
Available Drivers
File Logger
Logs to files with optional date-based rotation.
Single File (No Rotation):
'single' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'level' => 'debug', 'format' => '[{timestamp}] {level}: {message} {context}', ]
Daily Rotation:
'daily' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, // Enable daily rotation 'date_format' => 'Y-m-d', // Optional, defaults to Y-m-d 'level' => 'debug', 'format' => '[{timestamp}] [{env}] {level}: {message} {context}', ]
When daily rotation is enabled:
logs/app.logโlogs/app-2024-01-15.loglogs/errors.logโlogs/errors-2024-01-15.loglogs/debug.txtโlogs/debug-2024-01-15.txt
The date is automatically inserted before the file extension!
Console Logger
Outputs to console with optional colorization.
'console' => [ 'driver' => 'console', 'level' => 'debug', 'colorize' => true, 'format' => '[{env}] {level}: {message}', ]
Color Scheme:
- ๐ด Emergency/Alert/Critical - Bold Red
- ๐ด Error - Red
- ๐ก Warning - Yellow
- ๐ต Notice - Cyan
- ๐ข Info - Green
- โช Debug - White
Syslog Logger
Sends logs to system logger.
'syslog' => [ 'driver' => 'syslog', 'level' => 'warning', 'ident' => 'my-application', 'facility' => LOG_USER, ]
Error Log Logger
Uses PHP's native error_log() function.
'errorlog' => [ 'driver' => 'errorlog', 'level' => 'error', 'message_type' => 0, // 0=system, 1=email, 3=file, 4=SAPI 'destination' => null, // Required for types 1 and 3 ]
Null Logger
Discards all log messages (useful for testing).
'null' => [ 'driver' => 'null', ]
Stack Logger
Combines multiple loggers to write to multiple destinations.
'stack' => [ 'driver' => 'stack', 'channels' => ['daily', 'console', 'syslog'], ]
Usage Examples
Basic Logging
use MonkeysLegion\Logger\Factory\LoggerFactory; $factory = new LoggerFactory($config); $logger = $factory->make('daily'); // PSR-3 log levels $logger->emergency('System is down!'); $logger->alert('Database is unavailable'); $logger->critical('Application crash'); $logger->error('User registration failed'); $logger->warning('Disk space low'); $logger->notice('User logged in'); $logger->info('Email sent successfully'); $logger->debug('Processing request', ['data' => $requestData]);
Daily Rotation Example
$config = [ 'channels' => [ 'daily' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, // Enable rotation ], 'errors_daily' => [ 'driver' => 'file', 'path' => 'logs/errors.log', 'daily' => true, 'date_format' => 'Y-m-d', 'level' => 'error', ], ], ]; $factory = new LoggerFactory($config); $logger = $factory->make('daily'); $logger->info('This logs to logs/app-2024-01-15.log'); $errorLogger = $factory->make('errors_daily'); $errorLogger->error('This logs to logs/errors-2024-01-15.log');
Environment-Aware Smart Logging
The smartLog() method automatically adjusts log levels based on environment:
// Production: logs as INFO // Staging: logs as NOTICE // Testing: logs as WARNING // Development: logs as DEBUG $logger->smartLog('Processing payment', ['amount' => 99.99]);
Contextual Logging
$logger->info('User action', [ 'user_id' => 42, 'action' => 'purchase', 'amount' => 99.99, 'timestamp' => time(), ]); // Output: [2024-01-15 10:30:45] [production] INFO: User action {"user_id":42,"action":"purchase","amount":99.99,"timestamp":1705315845}
Using Different Channels
$factory = new LoggerFactory($config); // Production logging with daily rotation $productionLogger = $factory->make('stack'); $productionLogger->info('Application started'); // Debug logging to daily file $debugLogger = $factory->make('daily'); $debugLogger->debug('Debugging info', ['vars' => $debug]); // Emergency logging $emergencyLogger = $factory->make('syslog'); $emergencyLogger->emergency('Critical system failure');
Custom Formatting
Format tokens:
{timestamp}- Current date/time{env}- Environment name{level}- Log level (uppercase){message}- Log message{context}- JSON-encoded context
'custom' => [ 'driver' => 'file', 'path' => 'logs/custom.log', 'format' => '{timestamp}|{level}|{message}', ] // Output: 2024-01-15 10:30:45|INFO|User logged in
Log Level Filtering
Only logs at or above the specified level are written:
'production' => [ 'driver' => 'file', 'path' => 'logs/production.log', 'daily' => true, 'level' => 'warning', // Only warning, error, critical, alert, emergency ] $logger->debug('Debug info'); // Not logged $logger->info('Info message'); // Not logged $logger->warning('Warning!'); // Logged โ to logs/production-2024-01-15.log $logger->error('Error occurred'); // Logged โ to logs/production-2024-01-15.log
Log Level Hierarchy:
DEBUG < INFO < NOTICE < WARNING < ERROR < CRITICAL < ALERT < EMERGENCY
Advanced Usage
Factory with Environment
// Automatically uses APP_ENV from environment $factory = new LoggerFactory($config); // Or explicitly set environment $factory = new LoggerFactory($config, 'production'); $factory = new LoggerFactory($config, 'development');
Multiple Loggers with Daily Rotation
$config = [ 'channels' => [ 'app' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, ], 'errors' => [ 'driver' => 'file', 'path' => 'logs/errors.log', 'daily' => true, 'level' => 'error', ], 'audit' => [ 'driver' => 'file', 'path' => 'logs/audit.log', 'daily' => true, 'date_format' => 'Y-m-d', ], ], ]; $appLogger = $factory->make('app'); $errorLogger = $factory->make('errors'); $auditLogger = $factory->make('audit'); try { // Your code } catch (\Exception $e) { $errorLogger->error('Exception caught', [ 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } $auditLogger->info('User action', ['user_id' => $userId, 'action' => 'login']); $appLogger->debug('Request details', ['request' => $_REQUEST]); // This creates: // - logs/app-2024-01-15.log // - logs/errors-2024-01-15.log (only errors and above) // - logs/audit-2024-01-15.log
Testing with Null Logger
class UserService { public function __construct( private MonkeysLoggerInterface $logger ) {} } // Production $service = new UserService($factory->make('stack')); // Testing - no actual logging $service = new UserService($factory->make('null'));
Environment Configuration
# .env file
LOG_CHANNEL=stack
LOG_LEVEL=debug
APP_ENV=production
APP_NAME=my-application
Best Practices
1. Use Appropriate Log Levels
// โ Bad $logger->info('Database connection failed'); // โ Good $logger->error('Database connection failed', [ 'host' => $dbHost, 'error' => $e->getMessage(), ]);
2. Add Context
// โ Bad $logger->error('Payment failed'); // โ Good $logger->error('Payment failed', [ 'user_id' => $userId, 'amount' => $amount, 'payment_method' => $method, 'error_code' => $errorCode, ]);
3. Use Daily Rotation for Production
// โ Good for production 'production' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, // New file each day 'level' => 'warning', ] // โ Avoid single file in production (grows indefinitely) 'production' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => false, ]
4. Use smartLog() for General Flow
// Automatically adjusts based on environment $logger->smartLog('Processing order', ['order_id' => $orderId]);
5. Configure Per Environment
// config/logging-production.php return [ 'default' => 'stack', 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['syslog', 'daily'], ], 'daily' => [ 'driver' => 'file', 'path' => 'logs/app.log', 'daily' => true, 'level' => 'warning', // Only warnings and above ], ], ]; // config/logging-development.php return [ 'default' => 'console', 'channels' => [ 'console' => [ 'driver' => 'console', 'level' => 'debug', // Everything in development 'colorize' => true, ], ], ];
Testing
Run the test suite:
# Install dependencies composer install # Run tests ./vendor/bin/phpunit # Run with coverage ./vendor/bin/phpunit --coverage-html coverage # Run static analysis ./vendor/bin/phpstan analyse
Requirements
- PHP 8.1 or higher
- PSR-3 Logger Interface
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please submit pull requests or open issues on GitHub.
Support
For issues, questions, or suggestions, please open an issue on GitHub.
Changelog
Version 1.0.0
- Initial release
- PSR-3 compliant logging
- Multiple driver support (File, Console, Syslog, ErrorLog, Null, Stack)
- Environment-aware logging with smartLog()
- Daily rotation support for file logger
- Custom formatting with tokens
- Log level filtering
- Full test coverage
- PHPStan level max compliance
Made with โค๏ธ by MonkeysLegion