LogMonster makes logging in PHP simple and powerful. Whether you're building your first PHP application or a complex enterprise system, LogMonster helps you track what's happening in your code with easy-to-use logging that automatically handles security, performance, and file management.
Logging is like keeping a diary for your application. It records what happens when your code runs - successful operations, errors, user actions, and system events. This is essential for:
- Debugging: Finding out why something went wrong
- Monitoring: Keeping track of your application's health
- Security: Recording suspicious activities
- Analytics: Understanding how users interact with your app
- Compliance: Meeting regulatory requirements
Example: Instead of wondering "Why did the user's payment fail?", your logs will show you exactly what happened, when, and why.
- Beginner-friendly: Works with just 3 lines of code
- Professional-grade: Scales to enterprise applications
- Standards-compliant: Follows PHP industry standards (PSR-3)
- Automatic data protection: Hides passwords, API keys, and sensitive data
- Safe by default: No accidental exposure of secrets in logs
- Automatic file rotation: Prevents log files from getting too large
- Organized storage: Keeps your logs tidy and searchable
- Multiple formats: Human-readable text or structured JSON
- Fast logging: Won't slow down your application
- Memory efficient: Uses minimal system resources
- Smart filtering: Only logs what you actually need
- Works everywhere: Laravel, Symfony, Slim, or plain PHP
- HTTP request logging: Automatically track web requests and responses
- Middleware support: Easy integration with modern PHP frameworks
If you're new to Composer, it's PHP's package manager. Install Composer first if you haven't already.
composer require thedevbob005/utilsMake sure you have:
- PHP 8.0 or newer (check with
php --version) - Composer installed (check with
composer --version)
That's it! LogMonster will automatically install any other dependencies it needs.
<?php
require_once 'vendor/autoload.php'; // Load LogMonster
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
// 1. Create a logger
$logger = new LogMonster();
// 2. Tell it where to save logs (creates the file automatically)
$logger->addHandler(new FileHandler('my-app.log'));
// 3. Start logging!
$logger->info('Hello, LogMonster! My app is running.');
$logger->error('Oops, something went wrong!');That's it! Check your my-app.log file - you'll see your logs there.
LogMonster uses standard log levels (from most to least severe):
$logger->emergency('System is completely down!'); // 🚨 Most severe
$logger->alert('Database server is not responding'); // 🔴 Needs immediate attention
$logger->critical('Payment system failed'); // 🟠 Critical problems
$logger->error('User login failed'); // 🔴 Error conditions
$logger->warning('Disk space is getting low'); // 🟡 Warning conditions
$logger->notice('User changed their password'); // 🔵 Normal but significant
$logger->info('User logged in successfully'); // ℹ️ General information
$logger->debug('Processing step 3 of 10'); // 🐛 Detailed debug infoPro tip: Use info() for general events, error() for problems, and debug() for detailed troubleshooting.
Perfect for tracking user actions, errors, and system events:
<?php
require_once 'vendor/autoload.php';
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
$logger = new LogMonster();
$logger->addHandler(new FileHandler('logs/app.log'));
// Log user actions
$logger->info('User logged in', [
'user_id' => 123,
'username' => 'john_doe',
'ip_address' => '192.168.1.1'
]);
// Log errors with context
try {
// Some risky operation
connectToDatabase();
} catch (Exception $e) {
$logger->error('Database connection failed', [
'error_message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
}
// Log business events
$logger->notice('Order completed', [
'order_id' => 'ORD-12345',
'customer_id' => 456,
'total_amount' => 99.99
]);When your logs might get large, use rotating files:
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Config\LoggerConfig;
use Thedevbob005\Utils\Handlers\RotatingFileHandler;
// Configure automatic file rotation
$config = new LoggerConfig([
'max_file_size' => 10 * 1024 * 1024, // 10MB per file
'max_files' => 5 // Keep 5 old files
]);
$logger = new LogMonster($config);
// This handler automatically creates new files when they get too big
$logger->addHandler(new RotatingFileHandler('logs/app.log', $config));
$logger->info('This will be in a manageable file size!');For structured logs that tools like ELK Stack can easily parse:
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
use Thedevbob005\Utils\Formatters\JsonFormatter;
$logger = new LogMonster();
// Create a handler with JSON formatting
$handler = new FileHandler('logs/structured.log');
$handler->setFormatter(new JsonFormatter());
$logger->addHandler($handler);
$logger->info('API request processed', [
'endpoint' => '/api/users',
'method' => 'POST',
'response_time_ms' => 245,
'status_code' => 201
]);
// This creates clean JSON logs like:
// {"timestamp":"2024-01-15 10:30:45","level":"info","message":"API request processed","context":{"endpoint":"/api/users","method":"POST","response_time_ms":245,"status_code":201}}LogMonster automatically hides sensitive information:
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Config\LoggerConfig;
use Thedevbob005\Utils\Handlers\FileHandler;
// Configure which fields to automatically hide
$config = new LoggerConfig([
'sensitive_fields' => ['password', 'api_key', 'credit_card', 'ssn']
]);
$logger = new LogMonster($config);
$logger->addHandler(new FileHandler('logs/secure.log'));
// This is SAFE - sensitive data will be automatically redacted
$logger->info('User registration', [
'username' => 'john_doe',
'email' => 'john@example.com',
'password' => 'super_secret_123', // Will show as [REDACTED]
'api_key' => 'sk_live_abc123xyz' // Will show as [REDACTED]
]);
// Your logs will show: username=john_doe, email=john@example.com, password=[REDACTED], api_key=[REDACTED]You can customize LogMonster's behavior with simple configuration:
use Thedevbob005\Utils\Config\LoggerConfig;
$config = new LoggerConfig([
// Where to save logs
'log_directory' => 'logs/',
// Only log important stuff (skips debug/info in production)
'min_log_level' => 'warning', // Options: debug, info, notice, warning, error, critical, alert, emergency
// File size management
'max_file_size' => 5 * 1024 * 1024, // 5MB (in bytes)
'max_files' => 3, // Keep 3 old files when rotating
// Security: automatically hide these fields
'sensitive_fields' => ['password', 'api_key', 'credit_card']
]);
$logger = new LogMonster($config);| Setting | What It Does | Example Values | Beginner Tip |
|---|---|---|---|
log_directory |
Where to save log files | 'logs/', '/var/log/myapp/' |
Use relative paths for simplicity |
min_log_level |
Minimum severity to log | 'info', 'warning', 'error' |
Use 'info' for development, 'warning' for production |
max_file_size |
Max size before creating new file | 1024*1024 (1MB), 10*1024*1024 (10MB) |
Smaller = more files, larger = fewer files |
max_files |
How many old files to keep | 5, 10, 30 |
More files = longer history, but uses more disk space |
sensitive_fields |
Fields to automatically hide | ['password', 'ssn'] |
Always include passwords and API keys! |
For Development (see everything):
$config = new LoggerConfig([
'min_log_level' => 'debug', // Log everything
'log_directory' => 'logs/', // Local directory
'sensitive_fields' => [] // Don't hide anything (for debugging)
]);For Production (performance & security focused):
$config = new LoggerConfig([
'min_log_level' => 'warning', // Only log problems
'log_directory' => '/var/log/myapp/',
'sensitive_fields' => ['password', 'api_key', 'token', 'credit_card'],
'max_file_size' => 50 * 1024 * 1024, // 50MB files
'max_files' => 10 // Keep 10 days of logs
]);If you're building a web application, LogMonster can automatically log all HTTP requests and responses:
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Middleware\LoggingMiddleware;
use Thedevbob005\Utils\Handlers\FileHandler;
// Set up logger
$logger = new LogMonster();
$logger->addHandler(new FileHandler('logs/requests.log'));
// Create middleware that logs all HTTP requests
$middleware = new LoggingMiddleware($logger, [
'log_request_body' => true, // Log what users send
'log_response_body' => false, // Don't log responses (can be large)
'include_timing' => true, // Track how long requests take
'include_memory' => true // Track memory usage
]);
// Now every HTTP request to your app will be automatically logged!Laravel (add to app/Http/Kernel.php):
protected $middleware = [
// ... other middleware
\Thedevbob005\Utils\Middleware\LoggingMiddleware::class,
];Slim Framework:
$app->add($loggingMiddleware); // Add before your routesPlain PHP (add to your main file):
// At the start of your application
$middleware->process($request, $handler);<?php
require_once 'vendor/autoload.php';
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Config\LoggerConfig;
use Thedevbob005\Utils\Handlers\RotatingFileHandler;
// Configure for an e-commerce site
$config = new LoggerConfig([
'log_directory' => 'logs/',
'min_log_level' => 'info',
'sensitive_fields' => ['password', 'credit_card', 'cvv', 'api_key'],
'max_file_size' => 20 * 1024 * 1024, // 20MB files
'max_files' => 7 // Keep a week of logs
]);
$logger = new LogMonster($config);
$logger->addHandler(new RotatingFileHandler('logs/ecommerce.log', $config));
// Log customer actions
$logger->info('Customer registered', [
'customer_id' => 12345,
'email' => 'customer@example.com',
'registration_source' => 'website'
]);
// Log order processing
$logger->info('Order created', [
'order_id' => 'ORD-67890',
'customer_id' => 12345,
'total_amount' => 149.99,
'payment_method' => 'credit_card'
]);
// Log payment processing (sensitive data automatically hidden)
$logger->info('Payment processed', [
'order_id' => 'ORD-67890',
'credit_card' => '4111-1111-1111-1111', // Will be redacted
'amount' => 149.99,
'status' => 'success'
]);
// Log errors with full context
try {
processPayment($orderData);
} catch (PaymentException $e) {
$logger->error('Payment failed', [
'order_id' => 'ORD-67890',
'error_code' => $e->getCode(),
'error_message' => $e->getMessage(),
'customer_id' => 12345,
'retry_count' => 1
]);
}<?php
require_once 'vendor/autoload.php';
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
use Thedevbob005\Utils\Formatters\JsonFormatter;
// Set up JSON logging for API service
$logger = new LogMonster();
$handler = new FileHandler('logs/api.log');
$handler->setFormatter(new JsonFormatter()); // JSON format for log analysis tools
$logger->addHandler($handler);
// Log API requests
function handleApiRequest($endpoint, $method, $data) {
global $logger;
$startTime = microtime(true);
$logger->info('API request started', [
'endpoint' => $endpoint,
'method' => $method,
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown'
]);
try {
// Process the API request
$result = processApiRequest($endpoint, $method, $data);
$duration = (microtime(true) - $startTime) * 1000; // Convert to milliseconds
$logger->info('API request completed', [
'endpoint' => $endpoint,
'method' => $method,
'duration_ms' => round($duration, 2),
'status' => 'success',
'response_size' => strlen(json_encode($result))
]);
return $result;
} catch (Exception $e) {
$duration = (microtime(true) - $startTime) * 1000;
$logger->error('API request failed', [
'endpoint' => $endpoint,
'method' => $method,
'duration_ms' => round($duration, 2),
'error_message' => $e->getMessage(),
'error_code' => $e->getCode(),
'stack_trace' => $e->getTraceAsString()
]);
throw $e;
}
}<?php
require_once 'vendor/autoload.php';
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Config\LoggerConfig;
use Thedevbob005\Utils\Handlers\FileHandler;
// Configure for background jobs
$config = new LoggerConfig([
'min_log_level' => 'debug', // Log everything for job debugging
'log_directory' => 'logs/jobs/'
]);
$logger = new LogMonster($config);
$logger->addHandler(new FileHandler('logs/jobs/worker.log'));
function processEmailQueue() {
global $logger;
$logger->info('Email queue processing started');
$emailsProcessed = 0;
$errors = 0;
while ($email = getNextEmailFromQueue()) {
$logger->debug('Processing email', [
'email_id' => $email['id'],
'recipient' => $email['to'],
'subject' => $email['subject']
]);
try {
sendEmail($email);
$emailsProcessed++;
$logger->info('Email sent successfully', [
'email_id' => $email['id'],
'recipient' => $email['to']
]);
} catch (Exception $e) {
$errors++;
$logger->error('Failed to send email', [
'email_id' => $email['id'],
'recipient' => $email['to'],
'error' => $e->getMessage(),
'retry_count' => $email['retry_count'] ?? 0
]);
}
}
$logger->info('Email queue processing completed', [
'emails_processed' => $emailsProcessed,
'errors' => $errors,
'success_rate' => $emailsProcessed > 0 ? round(($emailsProcessed / ($emailsProcessed + $errors)) * 100, 2) : 0
]);
}
## Advanced Features (When You're Ready)
### Multiple Log Files for Different Purposes
You can send different types of logs to different files:
```php
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
$logger = new LogMonster();
// Send all logs to main file
$logger->addHandler(new FileHandler('logs/app.log'));
// Send only errors to a separate error file
$errorHandler = new FileHandler('logs/errors.log');
// Note: You'd typically filter this in a custom handler implementation
$logger->addHandler($errorHandler);
$logger->info('This goes to app.log');
$logger->error('This goes to both app.log and errors.log');Make your logs look exactly how you want:
use Thedevbob005\Utils\Formatters\LineFormatter;
// Create a custom format
$formatter = new LineFormatter('[%datetime%] %level_name%: %message% %context%');
$handler = new FileHandler('logs/custom.log');
$handler->setFormatter($formatter);
$logger->addHandler($handler);
// Your logs will look like:
// [2024-01-15 10:30:45] INFO: User logged in {"user_id":123,"username":"john"}If you use log analysis tools (like ELK Stack, Splunk, etc.):
use Thedevbob005\Utils\Formatters\JsonFormatter;
$handler = new FileHandler('logs/structured.log');
$handler->setFormatter(new JsonFormatter());
$logger->addHandler($handler);
// Creates structured JSON that analysis tools love:
// {"timestamp":"2024-01-15T10:30:45+00:00","level":"info","message":"User logged in","context":{"user_id":123}}Add your own sensitive fields to protect:
use Thedevbob005\Utils\Sanitizers\DataSanitizer;
$sanitizer = new DataSanitizer();
$sanitizer->addSensitiveField('social_security_number');
$sanitizer->addSensitiveField('bank_account');
$sanitizer->addSensitiveField('phone_number');
$logger->setSanitizer($sanitizer);
// Now these fields will be automatically hidden in logs
$logger->info('Customer data', [
'name' => 'John Doe',
'social_security_number' => '123-45-6789', // Will show as [REDACTED]
'bank_account' => '9876543210' // Will show as [REDACTED]
]);Problem: Can't write to log file Solution: Make sure your web server can write to the log directory
# On Linux/Mac, make the logs directory writable
mkdir logs
chmod 755 logs
# Or for development (less secure but works)
chmod 777 logsProblem: Log files are eating up disk space Solution: Use rotating file handlers
use Thedevbob005\Utils\Handlers\RotatingFileHandler;
use Thedevbob005\Utils\Config\LoggerConfig;
$config = new LoggerConfig([
'max_file_size' => 5 * 1024 * 1024, // 5MB max per file
'max_files' => 5 // Keep only 5 old files
]);
$logger->addHandler(new RotatingFileHandler('logs/app.log', $config));Problem: Logs are too noisy in production Solution: Set minimum log level
// For production - only log warnings and errors
$config = new LoggerConfig(['min_log_level' => 'warning']);
// For development - log everything
$config = new LoggerConfig(['min_log_level' => 'debug']);Problem: Passwords or API keys showing up in logs Solution: Configure sensitive field protection
$config = new LoggerConfig([
'sensitive_fields' => [
'password', 'passwd', 'pwd',
'api_key', 'apikey', 'token',
'secret', 'private_key',
'credit_card', 'ssn'
]
]);// Use higher log levels to reduce I/O
$config = new LoggerConfig([
'min_log_level' => 'error', // Only log errors and above
'max_file_size' => 50 * 1024 * 1024, // Larger files = less rotation overhead
]);// Log everything for debugging
$config = new LoggerConfig([
'min_log_level' => 'debug',
'max_file_size' => 10 * 1024 * 1024, // Smaller files for easier reading
]);Create a test file to make sure everything works:
<?php
// test-logging.php
require_once 'vendor/autoload.php';
use Thedevbob005\Utils\LogMonster;
use Thedevbob005\Utils\Handlers\FileHandler;
echo "Testing LogMonster...\n";
try {
$logger = new LogMonster();
$logger->addHandler(new FileHandler('test.log'));
$logger->info('Test message', ['test' => true]);
if (file_exists('test.log')) {
echo "✅ Success! Check test.log file\n";
echo "Log content: " . file_get_contents('test.log') . "\n";
} else {
echo "❌ Failed: No log file created\n";
}
} catch (Exception $e) {
echo "❌ Error: " . $e->getMessage() . "\n";
}Run it with: php test-logging.php
If you're contributing to LogMonster:
# Install development dependencies
composer install
# Run all tests
composer test
# Run tests with coverage report
composer test-coverage
# Check code quality
composer phpstan
# Check code style
composer cs-checkBegin with basic file logging and gradually add features as you need them.
- Migration Guide - If upgrading from LogMonster v1.x
- API Documentation - Complete technical reference
- Configuration Guide - All configuration options
- Usage Examples - More real-world examples
- Development: Use
debuglevel, log everything - Production: Use
warninglevel, protect sensitive data - Always: Include context data to make debugging easier
- Security: Never log passwords, API keys, or personal data without sanitization
- Issues: GitHub Issues
- Email: thedevbob005@gmail.com
For enterprise applications, you might want to log to a database:
use Thedevbob005\Utils\Handlers\HandlerInterface;
use Thedevbob005\Utils\LogRecord;
class DatabaseHandler implements HandlerInterface
{
private PDO $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function handle(LogRecord $record): bool
{
$stmt = $this->pdo->prepare(
'INSERT INTO application_logs (level, message, context, created_at) VALUES (?, ?, ?, ?)'
);
return $stmt->execute([
$record->level,
$record->message,
json_encode($record->context),
$record->datetime->format('Y-m-d H:i:s')
]);
}
public function isHandling(string $level): bool
{
return true; // Handle all log levels
}
public function close(): void
{
// Clean up database connection if needed
}
}
// Use it like any other handler
$pdo = new PDO('mysql:host=localhost;dbname=myapp', $username, $password);
$logger->addHandler(new DatabaseHandler($pdo));Database table structure:
CREATE TABLE application_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
level VARCHAR(20) NOT NULL,
message TEXT NOT NULL,
context JSON,
created_at DATETIME NOT NULL,
INDEX idx_level (level),
INDEX idx_created_at (created_at)
);- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Email: thedevbob005@gmail.com
If you're upgrading from LogMonster v1.x, please see our Migration Guide for detailed instructions on updating your code.
- API Documentation - Complete API reference
- Configuration Guide - Detailed configuration options
- Usage Examples - Practical usage examples
- Migration Guide - Upgrading from v1.x
- Complete rewrite with PSR-3 compliance
- Added PSR-7 middleware support
- Enhanced data sanitization
- Improved performance and memory management
- Added comprehensive test suite
- PHP 8+ requirement
- Backward compatibility layer with deprecation warnings
- Legacy LogMonster implementation (deprecated)