v1.0.0 2014-10-23 00:29 UTC

README

Total Downloads Latest Stable Version

mef\Log is a PSR-3 compliant logger for PHP 5.5+ designed to be as fast as reasonably possible without sacrificing useful functionality. All functionality is neatly stored away in separate layers, so you aren't penalized for features you don't need or use. (e.g., The core log method consists of only two simple if statements and a call to the handler's log method.)

Examples

Log to stdout/stderr

<?php
$logger = new mef\Log\StandardLogger;

// string interpolation works as expected
$logger->notice('This will go to {0}.', ['stdout']);
$logger->error('This will go to {location}.', ['location' => 'stderr']);

Log to file

<?php
$fileHandler = new mef\Log\Handler\FileHandler('/var/log/my.log');
$logger = new mef\Log\StandardLogger($fileHandler);

$logger->notice('This will go to /var/log/my.log');

Multiple handlers, with filtering

<?php
$debugHandler = new mef\Log\Handler\Stdout;
$debugHandler->filterHigherThan(Psr\Log\LogLevel::DEBUG);

$fileHandler = new mef\Log\Handler\FileHandler('/var/log/my.log');
$fileHandler->filterLowerThan(Psr\Log\LogLevel::INFO);

// The handlers could be pushed in any order. Here we are pushing the
// $fileHandler first because in production, there shouldn't be any
// debug messages, and the 'true' parameter will cause the chain handler
// to break early (thus skipping the debug handler) for any message that
// isn't marked DEBUG
$chainHandler = new mef\Log\Handler\ChainHandler;
$chainHandler->pushHandler($fileHandler, true);
$chainHandler->pushHandler($debugHandler);

$logger = new mef\Log\StandardLogger($chainHandler);

$logger->notice('This will go to /var/log/my.log');
$logger->debug('This will go to stdout');

More complete examples are available in the examples directory.

Overview

There are six main objects as defined by:

  • mef\Log\Logger - The core logger object that you interact with the most. It is PSR-3 compliant so that you can easily use it with most frameworks. The logger farms most work out to objects implementing the HandlerInterface and EntryFactoryInterface interfaces, but the subclass mef\Log\StandardLogger has reasonable defaults to avoid the hassle of setting everything up.

  • mef\Log\Handler\HandlerInterface - An object that does something with the entry. Entries are read-only to the handler. They are meant to do something useful like log the entries to a file.

  • mef\Log\Entry\EntryFactoryInterface - An object that builds a log entry object (that implements EntryInterface).

  • mef\Log\Entry\EntryInterface - A log message after it has been boxed into an object by a factory. This is what is passed around to the handlers. Every log entry has timestamp, an error level, a message, context (an array with arbitrary data).

  • mef\Log\Processor\ProcessorInterface - Modifies the log entry before it gets handled by the handler. A processor can change the message or alter the context.

  • mef\Log\Formatter\FormatterInterface - Formats the log entry into something that a handler can use. e.g., If using a stream based formatter, then you would use a formatter that returns a string.

The Logger has exactly one handler at all times. It is not possible to directly attach multiple handlers, nor is it possible to run it without a handler. But if you need either of that functionality, the ChainHandler and NullHandler are readily available.

Once you create a log entry (by calling $logger->debug, info, warning, etc...), the Logger first checks to see if it even wants to handle that level. If not, it does nothing. (This is implemented via the FilterTrait.) Filtering at the logger level is the most efficient way to ignore a message.

Assuming the logger does not filter away the message, it is packed into a mef\Log\Entry\EntryInterface object and sent to the handler. If using the DeferredEntryFactory and tthe handler ignores the message, then nothing happens. Neither the processor or the string interpolator (which could be "expensive" operations) will be invoked. This all happens in a single pass without the need to ask the handlers "Are you going to do something?"

If the handler does something with the log entry, the processor is invoked, and then string interpolation on the message occurs (to embed parts of the $context array into the message). The handler may then do its own special formatting of the entry (e.g., to add the timestamp and severity level).

Handlers

Exotic

  • NullHandler - Does nothing. Other than for testing, this really has no purpose. If you don't want to log anything in some situation, you can attach this as the handler, but you should still filter out all levels at the base Logger instance for maximum performance.

Decorators

  • ChainHandler - Distribute a single entry to multiple handlers.
  • FinalStrawHandler - Buffer all log entries until a certain severity level is reached. Once it is reached, all entries are passed to the sub-handler as a batch.

Stream Based

  • StreamHandler - Log to any PHP stream.
  • FileHandler - Log to a file.
  • StderrHandler - Log to stderr (console).
  • StdOutHandler - Log to stdout (console).
  • OutputHandler - Log to PHP's output buffer

Other

  • MemoryHandler - Log to queue in memory.

Processors

  • ChainProcessor - Distribute a single entry to multiple processors.
  • MemoryProcessor - Add the memory usage to the context.
  • NullProcessor - Does Nothing.

Formatters

  • CallbackFormatter - Convert any callable object into a formatter.
  • NullFormatter - Returns null (effectively making it impossible to log...)
  • StringFormatter - Uses a string interpolator with a customizable format to format the entry as a string.

License

Copyright (C) 2014 Matthew Leverton

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.