Monolog is a popular and powerful PHP logging library designed to send your logs to files, sockets, databases, and various web services. It is an extremely flexible and extensible library, making it the de-facto standard for logging in modern PHP applications, often included in frameworks like Symfony and Laravel.
Core Concepts:
1. Logger: The central object responsible for logging. You instantiate a Logger and give it a name. It's the entry point for logging messages (e.g., `$logger->info('User created');`).
2. Handlers: Handlers are where the magic happens. They are responsible for taking a log record and actually writing or sending it somewhere. Monolog provides a wide array of built-in handlers, such as `StreamHandler` (for files or `php://stderr`), `SyslogHandler`, `FirePHPHandler`, `NativeMailerHandler`, `RotatingFileHandler`, `PushoverHandler`, `SlackHandler`, and many more. You can attach multiple handlers to a single Logger, allowing logs to be sent to different destinations simultaneously.
3. Formatters: Handlers optionally use Formatters to convert a log record into a string that will be written. For example, `LineFormatter` formats the log into a single line, `HtmlFormatter` formats it for HTML output, and `JsonFormatter` outputs log records as JSON.
4. Processors: Processors are middleware that can add extra data to a log record before it's passed to the handlers. Common uses include adding current user details, request ID, memory usage, or network details (e.g., IP address, user agent) using `WebProcessor` or `IntrospectionProcessor`. This enriches your log data, making it more useful for debugging and analysis.
5. Log Levels: Monolog implements the standard PSR-3 log levels (DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY). Each handler can be configured to process only log records above a certain level, allowing you to filter logs effectively.
How it Works:
When you log a message using a Logger instance (e.g., `$logger->warning('Something went wrong');`):
1. A "log record" is created, containing the message, level, channel name, context data, and datetime.
2. Any attached Processors modify or add data to this record.
3. The record is passed to each attached Handler.
4. Each Handler decides if it should process the record based on its configured log level threshold.
5. If a Handler processes the record, it uses its configured Formatter (if any) to convert the record into a suitable output format.
6. Finally, the Handler sends or writes the formatted log output to its destination.
Benefits:
* Flexibility: Easily route different types of logs to different destinations.
* Extensibility: Simple to write custom handlers, formatters, or processors.
* Readability: Helps keep your application code clean by centralizing logging concerns.
* Debugging & Monitoring: Indispensable for understanding application behavior, diagnosing issues, and monitoring system health.
Example Code
<?php
require __DIR__ . '/vendor/autoload.php'; // Composer autoloader
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\WebProcessor;
// 1. Create a Logger instance
// The 'my_app' string is the channel name for the logs.
$logger = new Logger('my_app');
// 2. Create a Handler
// This handler will write logs to 'app.log' file
// Log records at INFO level and above will be handled.
$streamHandler = new StreamHandler(__DIR__ . '/app.log', Logger::INFO);
// Optionally, create a formatter and set it for the handler.
// The default format is usually fine, but you can customize it.
// Example: "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
$output = "[%datetime%] %level_name%: %message% %context% %extra%\n";
$formatter = new LineFormatter($output);
$streamHandler->setFormatter($formatter);
// Add the handler to the logger
$logger->pushHandler($streamHandler);
// 3. Add an additional handler for critical errors, sending them to a separate file
$errorHandler = new StreamHandler(__DIR__ . '/error.log', Logger::ERROR);
$logger->pushHandler($errorHandler);
// 4. Add a processor to automatically add web request details (URL, IP, method, etc.)
// This is useful for web applications.
$logger->pushProcessor(new WebProcessor());
// Now, log some messages
$logger->debug('This is a debug message. It will not be written by StreamHandler (Logger::INFO threshold).');
$logger->info('An informational message.');
$logger->notice('A normal but significant condition.');
$logger->warning('This is a warning! Something might be wrong.');
$logger->error('An error occurred.', ['exception' => 'Some detailed exception info']);
$logger->critical('Critical condition detected! Application might be crashing.', ['user_id' => 123]);
// To see the `debug` message, you would need a handler with `Logger::DEBUG` threshold:
$debugHandler = new StreamHandler(__DIR__ . '/debug.log', Logger::DEBUG);
$logger->pushHandler($debugHandler);
$logger->debug('This debug message will now be written to debug.log.');
echo "Log messages written to app.log, error.log, and debug.log (check your project directory)." . PHP_EOL;
// --- Example of logging to console (php://stdout or php://stderr) ---
// This is useful for CLI applications or Docker environments
$consoleHandler = new StreamHandler('php://stdout', Logger::INFO);
$consoleFormatter = new LineFormatter("CLI [%datetime%] %level_name%: %message%\n");
$consoleHandler->setFormatter($consoleFormatter);
$cliLogger = new Logger('cli_app');
$cliLogger->pushHandler($consoleHandler);
$cliLogger->info('This message goes to your console/terminal stdout.');
$cliLogger->warning('A warning for the CLI user.');
?>








monolog/monolog