Статьи

Реализация PSR-3 с log4php

С недавним появлением PSR-3, стандарта для общего интерфейса для библиотек журналов, представляется целесообразным обсудить реализацию с моей любимой библиотекой журналов. log4php — это проект Apache с открытым исходным кодом, представляющий собой очень универсальную среду ведения журналов.

Через конфигурационные файлы log4php ведение журнала имеет множество выходных местоположений, поэтому можно отправлять определенные уровни журналов в разные выходные местоположения. Например: отладка, информация и уведомление используются главным образом для общего ведения журнала и отладки, и поэтому имеет смысл направить их в стандартный файл журнала, тогда как критическое значение и выше обычно означают, что что-то пошло не так с нашим приложением, и это делает больше смысл отправить их нам по электронной почте для немедленной диагностики.

Получение зависимостей

Прежде чем мы сможем начать писать код, нам нужно наши зависимости. Требуется класс интерфейса PSR-3; в настоящее время он находится на GitHub и может быть установлен через композитора из Packagist . Также требуется каркас log4php, который можно загрузить из Apache , с помощью PEAR или composer .

Вот пример файла composer.json

 {
    "require": {
        "psr/log": "dev-master",
        "apache/log4php": "2.3.0"
    }
}

Упаковка log4php

Установив необходимые сторонние библиотеки, мы можем создать общий класс ведения журнала, который реализует интерфейс PSR-3 и использует log4php.

Интерфейс PSR-3 предоставляет восемь различных уровней журнала: отладка, информация, уведомление, предупреждение, ошибка, критическое состояние, предупреждение и аварийная ситуация. log4php содержит шесть уровней ведения журнала: трассировка, отладка, информация, предупреждение, ошибка и фатальный. Мы должны отобразить уровни PSR-3 на соответствующие уровни log4php. Приведенный ниже класс реализует интерфейс и управляет экземпляром log4php logger для сопоставления уровней.

 <?php
require_once 'vendor/autoload.php';

class MyLogger implements PsrLogLoggerInterface
{
    private $logger;

    public function __construct($logger = 'main', $config = null) {
        Logger::configure($config);
        $this->logger = Logger::getLogger($logger);
    }

    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array()) {
        $this->logger->fatal($this->interpolate($message, $context));
    }

    /**
     * Action must be taken immediately.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array()) {
       $this->logger->fatal($this->interpolate($message, $context));
    }

    /**
     * Critical conditions.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array()) {
        $this->logger->fatal($this->interpolate($message, $context));
    }

    /**
     * Runtime errors that do not require immediate action but should
     * be logged and monitored.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array()) {
        $this->logger->error($this->interpolate($message, $context));
    }

    /**
     * Exceptional occurrences that are not errors.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array()) {
        $this->logger->warn($this->interpolate($message, $context));
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array()) {
        $this->logger->info($this->interpolate($message, $context));
    }

    /**
     * Interesting events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array()) {
        $this->logger->info($this->interpolate($message, $context));
    }

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array()) {
        $this->logger->debug($this->interpolate($message, $context));
    }

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    public function log($level, $message, array $context = array()) {
        throw new Exception('Please call specific logging message');
    }

    /**
     * Interpolates context values into the message placeholders.
     * Taken from PSR-3's example implementation.
     */
    protected function interpolate($message, array $context = array()) {
        // build a replacement array with braces around the context
        // keys
        $replace = array();
        foreach ($context as $key => $val) {
            $replace['{' . $key . '}'] = $val;
        }

        // interpolate replacement values into the message and return
        return strtr($message, $replace);
    }
}

Помимо реализации интерфейса PSR-3, этот класс содержит конструктор, который принимает 2 необязательных параметра с именами $logger$config Первый параметр позволяет указать имя для регистратора, и log4php будет поддерживать ссылку на него, позволяя одновременно поддерживать несколько экземпляров регистратора с разными именами. Второй параметр позволяет указать файл конфигурации. Если ничего не указано, log4php будет использовать конфигурацию по умолчанию.

Недавно созданный класс MyLogger

 <?php
$logger = new MyLogger();
$logger->debug('My debug test');

Параметр log4php по умолчанию для отладки выведет сообщение на стандартный вывод, поэтому результаты этого примера будут отправлены в веб-браузер.

Конфигурация log4php

log4php поставляется с конфигурацией по умолчанию, поэтому мы сразу приступим к ее использованию, но она также предоставляет возможность переопределить конфигурацию с использованием кода XML или PHP. Наиболее популярной поддерживаемой конфигурацией является XML.

Давайте создадим файл config.xml

 <configuration xmlns="http://logging.apache.org/log4php/">
 <appender name="myAppender" class="LoggerAppenderFile">
  <param name="file" value="myLog.log"/>
 </appender>
 <root>
  <level value="WARN"/>
   <appender_ref ref="myAppender"/>
  </root>
</configuration>

Теперь нам нужно передать имя нового файла конфигурации MyLogger

 <?php
$logger = new MyLogger('main', 'config.xml');
$logger->debug('My debug test');

Если вы повторно запустите пример, когда вызывается сообщение отладки, log4php проигнорирует его, потому что отладка находится под предупреждением ниже, а наша конфигурация регистрирует только предупреждения и выше.

Вывод

Благодаря использованию интерфейса ведения журнала PSR-3 и log4php, совместимое со стандартами ведение журнала теперь чрезвычайно просто добавить в любой из наших проектов. Чтобы узнать больше о log4php, посетите краткое руководство . Подробнее о PSR-3 читайте в стандарте на GitHub .

Изображение через Fotolia