pear/log
PEAR Log provides a simple, standardized logging system for PHP. It supports multiple backends (file, console, syslog, database, mail, etc.), configurable priorities and formatting, and a consistent API to route application messages wherever you need.
Installation:
composer require pear/log
Ensure pear/pear_exception (v1.0.1–1.0.2) is installed if not already present.
Basic Logger Setup:
use PEAR\Log;
// Initialize logger with default level (e.g., PEAR_LOG_INFO)
$logger = Log::singleton(PEAR_LOG_INFO);
// Log a message
$logger->log("Application started", PEAR_LOG_NOTICE);
First Use Case: File Logging
$logger = Log::singleton(PEAR_LOG_DEBUG);
$logger->addHandler(new Log\Handler\File('/var/log/myapp.log'));
$logger->log("Debugging mode enabled", PEAR_LOG_DEBUG);
Laravel Integration (Wrapper Class):
Create a facade or service provider to bridge Laravel’s Log facade with pear/log:
// app/Services/PearLogger.php
class PearLogger {
public static function info($message, array $context = []) {
$log = Log::singleton(PEAR_LOG_INFO);
$log->log($message . (count($context) ? ' - ' . json_encode($context) : ''), PEAR_LOG_INFO);
}
}
Register in AppServiceProvider:
Log::extend('pear', function () {
return new PearLogger();
});
Usage:
Log::channel('pear')->info('User logged in', ['user_id' => 1]);
Handler-Based Logging:
$logger = Log::singleton(PEAR_LOG_ALL);
$logger->addHandler(new Log\Handler\File('/var/log/app.log'));
$logger->addHandler(new Log\Handler\Syslog('myapp'));
Contextual Logging:
$userId = 123;
$logger->log("User action", PEAR_LOG_INFO, [
'user_id' => $userId,
'action' => 'profile_update'
]);
// Output: "User action - {"user_id":123,"action":"profile_update"}"
Log Level Filtering:
PEAR_LOG_ALL or PEAR_LOG_ERR | PEAR_LOG_WARNING):
$logger = Log::singleton(PEAR_LOG_ERR | PEAR_LOG_WARNING);
$logger->log("This won't appear in debug logs", PEAR_LOG_DEBUG);
Custom Handlers:
Log\Handler for specialized outputs (e.g., database, HTTP):
class DatabaseHandler extends Log\Handler {
public function handle($message, $priority) {
DB::table('logs')->insert([
'message' => $message,
'level' => $priority,
'created_at' => now()
]);
}
}
Channel Integration:
pear/log as a custom channel in config/logging.php:
'pear' => [
'driver' => 'custom',
'path' => env('LOG_PATH', storage_path('logs/pear.log')),
'level' => env('LOG_LEVEL', 'debug'),
],
app/Providers/AppServiceProvider:
Log::extend('pear', function ($config) {
$logger = Log::singleton($config['level']);
$logger->addHandler(new Log\Handler\File($config['path']));
return new PearLogDriver($logger);
});
Queue-Based Async Logging:
Log::channel('pear')->info('Async log message');
// In a queue worker:
while ($message = queue()->pop('logs')) {
$logger = Log::singleton(PEAR_LOG_INFO);
$logger->log($message['message'], $message['level']);
}
Log Rotation:
Log::rotateStorages() with a custom handler:
$handler = new Log\Handler\File('/var/log/app.log');
$handler->setRotation(7); // Rotate weekly
$logger->addHandler($handler);
PEAR Autoloader Conflicts:
pear/log is loaded via Composer’s classmap:
{
"autoload": {
"classmap": ["vendor/pear/log"]
}
}
Log Level Mismatches:
Log::debug() maps to PEAR_LOG_DEBUG, but ensure bitmask levels align (e.g., PEAR_LOG_ALL may not work on 32-bit systems; use PEAR_LOG_DEBUG | PEAR_LOG_INFO | ... explicitly).Context Data Loss:
pear/log does not natively support structured logging. Manually encode context:
// Bad: Context is ignored
$logger->log("User data", PEAR_LOG_INFO, ['user_id' => 1]);
// Good: Encode context into message
$logger->log("User data: " . json_encode(['user_id' => 1]), PEAR_LOG_INFO);
Syslog Handler Quirks:
SyslogHandler requires the $name parameter to be non-null (fixed in v1.14.4). Ensure you pass a valid identifier:
$logger->addHandler(new Log\Handler\Syslog('myapp')); // Valid
$logger->addHandler(new Log\Handler\Syslog(null)); // Throws error
PHP 7.4+ Strictness:
new Log()) may trigger deprecation warnings. Use the singleton pattern:
$logger = Log::singleton(PEAR_LOG_INFO); // Preferred
// $logger = new Log(); // Deprecated
Handler Return Values:
if ($logger->log("Test", PEAR_LOG_INFO)) {
// Handler may return false on failure
}
Log Level Tracing:
PEAR_LOG_ALL to capture all messages during debugging, then narrow down:
$logger = Log::singleton(PEAR_LOG_ALL);
Handler-Specific Issues:
$fileHandler = new Log\Handler\File('/tmp/debug.log');
$logger->addHandler($fileHandler);
$logger->log("Test file handler", PEAR_LOG_DEBUG);
PEAR Exception Handling:
pear/log calls in try-catch blocks to handle pear_exception:
try {
$logger->log("Critical error", PEAR_LOG_ERR);
} catch (pear_exception $e) {
error_log("Logging failed: " . $e->getMessage());
}
Performance Bottlenecks:
storage_path('logs/laravel.log') as a fallback:
$handler = new Log\Handler\File('/tmp/app.log');
$handler->setMode(0644); // Ensure writable permissions
Custom Formatters:
Log\Formatter to add structured logging (e.g., JSON):
class JsonFormatter extends Log\Formatter {
public function format($message, $priority) {
return json_encode([
'message' => $message,
'level' => $priority,
'timestamp' => date('c')
]);
}
}
Laravel Event Listeners:
// app/Listeners/LogUserActivity.php
public function handle($event) {
Log::channel('pear')->info('User activity', $event->data);
}
Dynamic Handler Configuration:
$handlers = [];
if (env('LOG_TO_FILE')) {
$handlers[] = new Log\Handler\File(env('LOG_PATH'));
}
if (env('LOG_TO_SYSLOG')) {
$handlers[] = new Log\
How can I help you explore Laravel packages today?