diff --git a/doc/extending.md b/doc/extending.md new file mode 100644 index 00000000..9db481a8 --- /dev/null +++ b/doc/extending.md @@ -0,0 +1,69 @@ +Extending Monolog +================= + +Monolog is fully extendable, allowing you to adapt your logger to your needs. + +Writing your own handler +------------------------ + +Monolog provides many built-in handlers. But if the one you need does not +exist, you can write it and use it in your logger. The only requirement is +to implement `Monolog\Handler\HandlerInterface`. + +Let's write a PDOHandler to log records to a database. We will extend the +abstract class provided by Monolog to keep things DRY. + +```php +pdo = $pdo; + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + if (!$this->initialized) { + $this->initialize(); + } + + $this->statement->execute(array( + 'channel' => $record['channel'], + 'level' => $record['level'], + 'message' => $record['formatted'], + 'time' => $record['datetime']->format('U'), + )); + } + + private function initialize() + { + $this->pdo->exec('CREATE TABLE IF NOT EXISTS monolog (channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'); + $this->statement = $this->pdo->prepare('INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)'); + } +} +``` + +You can now use this handler in your logger: + +```php +pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +The `Monolog\Handler\AbstractProcessingHandler` class provides most of the +logic needed for the handler, including the use of processors and the formatting +of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``. diff --git a/doc/usage.md b/doc/usage.md new file mode 100644 index 00000000..45694d88 --- /dev/null +++ b/doc/usage.md @@ -0,0 +1,117 @@ +Using Monolog +============= + +Installation +------------ + +To install Monolog, simply get the code (from github or through PEAR) and +configure an autoloader for the Monolog namespace. + +Monolog does not provide its own autoloader but follows the PSR-0 convention, +thus allowing to use any compliant autoloader. You could for instance use +the [Symfony2 ClassLoader component](https://github.com/symfony/ClassLoader). + +Configuring a logger +-------------------- + +Here is a basic setup to log to a file and to firephp on the DEBUG level: + +```php +pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG)); +$logger->pushHandler(new FirePHPHandler()); + +// You can now use your logger +$logger->addInfo('My logger is now ready'); +``` + +Let's explain it. The first step is to create the logger instance which will +be used in your code. The argument is a channel name, which is useful when +you use several loggers (see below for more details about it). + +The logger itself does not know how to handle a record. It delegates it to +some handlers. The code above registers two handlers in the stack to allow +handling records in two different ways. + +Note that the FirePHPHandler is called first as it is added on top of the +stack. + +Adding extra data in the records +-------------------------------- + +Monolog provides two different ways to add extra informations along the simple +textual message. + +The first one is the context, allowing to pass an array of data along the +record: + +```php +addInfo('Adding a new user', array('username' => 'Seldaek')); +``` + +Simple handlers (like the StreamHandler for instance) will simply format +the array to a string but richer handlers can take advantage of the context +(FirePHP is able to display arrays in pretty way for instance). + +The second way is to add extra data for all records by using a processor. +Processors can be any callable. They will get the record as parameter and +must return it after having eventually changed the `extra` part of it. Let's +write a processor adding some dummy data in the record: + +```php +pushProcessor(function($record){ + $record['extra']['dummy'] = 'Hello world!'; + + return $record; +}); +``` + +Monolog provides some built-in processors that can be used in your project. +Look at the README file for the list. + +> Tip: processors can also be registered on a specific handler instead of + the logger to apply only for this handler. + +Leveraging channels +------------------- + +Channels are a great way to identify to which part of the application a record +is related. This is useful in big application (and is leveraged by MonologBundle +in Symfony2). +Using different loggers with the same handlers allow to identify the logger +that issued the record (through the channel name) by keeping the same handlers +(for instance to use a single log file). + +```php +pushHandler($stream); +$logger->pushHandler($firephp); + +// Create a logger for the security-related stuff with a different channel +$securityLogger = new Logger('security'); +$securityLogger->pushHandler($stream); +$securityLogger->pushHandler($firephp); +```