Обзор

Phalcon\Logger -это компонент, предоставляющий услуги ведения журнала для приложений. Он предлагает ведение журнала в разные бэк-энды с помощью разных адаптеров. Он также предлагает ведение журнала транзакций, параметры конфигурации и различные форматы ведения журнала. Вы можете использовать Phalcon\Logger для любых нужд ведения журнала вашего приложения, от отладки процессов до отслеживания потока приложений.

Phalcon\Logger был переписан в соответствии с PSR-3. Это позволяет использовать Phalcon\Logger в любом приложении, использующем регистратор PSR-3, а не только на основе Phalcon.

В версии v3 регистратор включал адаптер в тот же компонент. Таким образом, по сути, создавая объект logger, разработчик создавал адаптер (файл, поток и т. д.) с функциональностью регистратора.

Для версии v4 мы переписали компонент, чтобы реализовать только функциональность ведения журнала и принять один или несколько адаптеров, которые будут отвечать за ведение журнала. Это сразу же обеспечивает совместимость с PSR-3 и разделяет обязанности компонента. Он также предлагает простой способ подключения нескольких адаптеров к компоненту ведения журнала, чтобы можно было вести журнал к нескольким адаптерам. Используя эту реализацию, мы сократили код, необходимый для этого компонента,и удалили старый компонент Logger\Multiple.

Адаптеры

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

АдаптерОписание
Phalcon\Logger\Adapter\Noop Адаптер Blackhole (используется в основном для тестирования)
Phalcon\Logger\Adapter\Stream Записывает сообщения в файловый поток
Phalcon\Logger\Adapter\Syslog Записывает сообщения в системный журнал

Stream

Этот адаптер используется, когда мы хотим записывать сообщения в определенный файловый поток. Этот адаптер сочетает в себе v3 Stream и  File. Обычно это наиболее часто используемый метод: вход в файл в файловой системе.

Syslog

Этот адаптер отправляет сообщения в системный журнал. Поведение системного журнала может варьироваться от одной операционной системы к другой.

Noop

Это адаптер для черных дыр. Он посылает сообщения в бесконечность и за ее пределы! Этот адаптер используется в основном для тестирования или если вы хотите пошутить с коллегой.

Factory

Вы можете использовать компонент Phalcon\Logger\LoggerFactory для создания регистратора. Для работы Phalcon\Logger\LoggerFactory его необходимо создать с помощью Phalcon\Logger\AdapterFactory:

<?php

use Phalcon\Logger\LoggerFactory;
use Phalcon\Logger\AdapterFactory;

$adapterFactory = new AdapterFactory();
$loggerFactory  = new LoggerFactory($adapterFactory);

load()

Phalcon\Logger\LoggerFactory предлагает метод load, который создает регистратор на основе предоставленной конфигурации. Конфигурация может быть массивом или объектом Phalcon\Config.

ПРИМЕЧАНИЕ: Вариант использования: создайте регистратор с двумя потоковыми адаптерами. Один адаптер будет называться main для регистрации всех сообщений, тогда как второй будет называться admin, регистрируя только сообщения, созданные в области администратора нашего приложения.

<?php

use Phalcon\Logger\AdapterFactory;
use Phalcon\Logger\LoggerFactory;

$config = [
    "name"     => "prod-logger",
    "adapters" => [
        "main"  => [
            "adapter" => "stream",
            "name"    => "/storage/logs/main.log",
            "options" => []
        ],
        "admin" => [
            "adapter" => "stream",
            "name"    => "/storage/logs/admin.log",
            "options" => []
        ],
    ],
];

$adapterFactory = new AdapterFactory();
$loggerFactory  = new LoggerFactory($adapterFactory);

$logger = $loggerFactory->load($config);

newInstance()

The Phalcon\Logger\LoggerFactory также предлагает метод newInstance() , который строит регистратор на основе предоставленного имени и массива соответствующих адаптеров. Используя приведенный выше пример использования:

<?php

use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\AdapterFactory;
use Phalcon\Logger\LoggerFactory;

$adapters = [
    "main"  => new Stream("/storage/logs/main.log"),
    "admin" => new Stream("/storage/logs/admin.log"),
];

$adapterFactory = new AdapterFactory();
$loggerFactory  = new LoggerFactory($adapterFactory);

$logger = $loggerFactory->newInstance('prod-logger', $adapters);

 

Создание регистратора

Создание регистратора-это многоступенчатый процесс. Сначала вы создаете объект logger, а затем присоединяете к нему адаптер. После этого вы можете начать регистрировать сообщения в соответствии с потребностями вашего приложения.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('/storage/logs/main.log');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Something went wrong');

В приведенном выше примере создается адаптер Phalcon\Logger\Adapter\Stream. Затем мы создаем объект logger и прикрепляем к нему этот адаптер. Каждый адаптер, подключенный к регистратору, должен иметь уникальное имя, чтобы регистратор мог знать, где регистрировать сообщения. При вызове метода error() на объекте logger сообщение будет сохранено в файле /storage/logs/main.log.

Поскольку компонент logger реализует PSR-3, доступны следующие методы:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('/storage/logs/main.log');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->alert("Это тревожное сообщение");
$logger->critical("Это очень важное сообщение");
$logger->debug("Это отладочное сообщение");
$logger->error("Это сообщение об ошибке");
$logger->emergency("Это экстренное сообщение");
$logger->info("Это информационное сообщение");
$logger->log(Logger::CRITICAL, "Это сообщение журнала");
$logger->notice("Это сообщение с уведомлением");
$logger->warning("Это предупреждающее сообщение");

Сформированный отчет выглядит следующим образом:

[Tue, 25 Dec 18 12:13:14 -0400][ALERT] Это тревожное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][CRITICAL] Это очень важное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][DEBUG] Это отладочное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][ERROR] Это сообщение об ошибке
[Tue, 25 Dec 18 12:13:14 -0400][EMERGENCY] Это экстренное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][INFO] Это информационное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][CRITICAL] Это сообщение журнала
[Tue, 25 Dec 18 12:13:14 -0400][NOTICE] Это сообщение с уведомлением
[Tue, 25 Dec 18 12:13:14 -0400][WARNING] Это предупреждающее сообщение

Несколько адаптеров

Phalcon\Logger может отправлять сообщения нескольким адаптерам с помощью всего одного вызова:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter1 = new Stream('/logs/first-log.log');
$adapter2 = new Stream('/remote/second-log.log');
$adapter3 = new Stream('/manager/third-log.log');

$logger = new Logger(
    'messages',
    [
        'local'   => $adapter1,
        'remote'  => $adapter2,
        'manager' => $adapter3,
    ]
);

// Log to all adapters
$logger->error('Something went wrong');

Сообщения отправляются обработчикам в том порядке, в котором они были зарегистрированы, используя принцип "первым пришёл — первым ушёл".

Исключение адаптеров

Phalcon\Logger также предлагает возможность исключить ведение журнала на один или несколько адаптеров при регистрации сообщения. Это особенно полезно, когда необходимо зарегистрировать сообщение, связанное с менеджером, в журнале менеджера, но не в локальном журнале без необходимости создания экземпляра нового регистратора.

Со следующей настройкой:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter1 = new Stream('/logs/first-log.log');
$adapter2 = new Stream('/remote/second-log.log');
$adapter3 = new Stream('/manager/third-log.log');

$logger = new Logger(
    'messages',
    [
        'local'   => $adapter1,
        'remote'  => $adapter2,
        'manager' => $adapter3,
    ]
);

у нас есть следующее:

<?php

$logger->error('Something went wrong');

Журнал для всех адаптеров

<?php

$logger
    ->excludeAdapters(['local'])
    ->info('This does not go to the "local" logger');

Вход только для удаленных и менеджер

ПРИМЕЧАНИЕ Внутренний компонент проходит по зарегистрированным адаптерам и вызывает соответствующий метод регистрации, чтобы выполнить регистрацию для нескольких адаптеров. Если один из них выходит из строя, цикл прерывается, а остальные адаптеры (из цикла) не регистрируют сообщение. В будущих версиях Phalcon мы будем вводить асинхронное ведение журнала, чтобы облегчить эту проблему.

Константы

Этот класс предлагает ряд констант,которые можно использовать для различения уровней журнала. Эти константы также могут быть использованы в качестве первого параметра в методеlog().

ConstantValue
EMERGENCY 0
CRITICAL 1
ALERT 2
ERROR 3
WARNING 4
NOTICE 5
INFO 6
DEBUG 7
CUSTOM 8

Уровни журнала

Phalcon\Logger позволяет установить минимальный уровень регистрации для регистратора(ов) для регистрации. Если вы зададите это целочисленное значение, любой уровень выше по числу, чем один набор, не будет регистрироваться. Проверьте значения констант в предыдущем разделе для порядка установки уровней.

В следующем примере мы устанавливаем уровень журнала для оповещения ALERT. Мы будем видеть только экстренные EMERGENCY, критические CRITICAL и  тревожные ALERT сообщения.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('/storage/logs/main.log');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->setLogLevel(Logger::ALERT);

$logger->alert("Это тревожное сообщение");
$logger->critical("Это очень важное сообщение");
$logger->debug("Это отладочное сообщение");
$logger->error("Это сообщение об ошибке");
$logger->emergency("Это экстренное сообщение");
$logger->info("Это информационное сообщение");
$logger->log(Logger::CRITICAL, "Это сообщение журнала");
$logger->notice("Это сообщение с уведомлением");
$logger->warning("Это предупреждающее сообщение");

Сформированный отчет выглядит следующим образом:

[Tue, 25 Dec 18 12:13:14 -0400][ALERT] Это тревожное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][CRITICAL] Это очень важное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][EMERGENCY] Это экстренное сообщение
[Tue, 25 Dec 18 12:13:14 -0400][CRITICAL] Это сообщение журнала

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

ПРИМЕЧАНИЕ: Набор уровней журнала включен в ведение журнала. Все, что ниже этого уровня (т. е. более высокое число), не будет регистрироваться

ПРИМЕЧАНИЕ: Никогда не стоит подавлять уровни ведения журнала в вашем приложении, поскольку даже предупреждающие ошибки требуют обработки циклов ЦП, и игнорирование этих ошибок может потенциально привести к непредвиденным обстоятельствам

Транзакции

Phalcon\Logger также предлагает возможность поставить сообщения в очередь в вашем регистраторе, а затем зафиксировать их все вместе в файле журнала. Это похоже на транзакцию базы данных с begin и commit. Каждый адаптер предоставляет следующие методы:

  • begin - начинается протоколирование транзакции
  • inTransaction - bool  определить вы находитесь в транзакции или нет
  • commit - записывает все сообщения в очередь в файл журнала

Поскольку функциональность доступна на уровне адаптера, вы можете запрограммировать свой регистратор для использования транзакций на основе каждого адаптера.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter1 = new Stream('/logs/first-log.log');
$adapter2 = new Stream('/remote/second-log.log');
$adapter3 = new Stream('/manager/third-log.log');

$logger = new Logger(
    'messages',
    [
        'local'   => $adapter1,
        'remote'  => $adapter2,
        'manager' => $adapter3,
    ]
);

$logger->getAdapter('manager')->begin();

$logger->error('Что-то случилось');

$logger->getAdapter('manager')->commit();

В приведенном выше примере мы регистрируем три адаптера. Мы устанавливаем регистратор manager в режим транзакции. Как только мы вызовем:

$logger->error('Something happened');

сообщение будет зарегистрировано как в local , так и в remote адаптерах. Он будет поставлен в очередь для адаптера manager и не будет зарегистрирован, пока мы не вызовем метод commit в адаптере manager.

ПРИМЕЧАНИЕ: Если вы настроите один или несколько адаптеров на режим транзакции (т. е. вызов begin) и забудете вызвать commit, адаптер вызовет commit для вас прямо перед тем, как он будет уничтожен.

Форматирование сообщений

Этот компонент использует средства formatters для форматирования сообщений перед их отправкой в ​​серверную часть. Доступны следующие форматеры:

AdapterОписание
Phalcon\Logger\Formatter\Line Форматирует сообщение в одну строку текста
Phalcon\Logger\Formatter\Json Форматирует сообщение в виде строки JSON

Строка Форматирования

Форматирует сообщения, используя однострочную строку. Формат ведения журнала по умолчанию:

[%date%][%type%] %message%

Формат сообщения

Если формат сообщения по умолчанию не соответствует потребностям вашего приложения, вы можете изменить его с помощью метода setFormat(). Допустимыми переменными формата журнала являются:

ПеременнаяОписание
%message% Ожидается, что само сообщение будет зарегистрировано
%date% Дата добавления сообщения
%type% Строка в верхнем регистре с типом сообщения

В следующем примере показано, как изменить формат сообщения:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\Formatter\Line;

$formatter = new Line('[%type%] - [%date%] - %message%');
$adapter   = new Stream('/storage/logs/main.log');

$adapter->setFormatter($formatter);

$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

производящий:

[ALERT] - [Tue, 25 Dec 18 12:13:14 -0400] - Что-то пошло не так

Если вы не хотите использовать конструктор для изменения сообщения, вы всегда можете использовать setFormat() в форматоре:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\Formatter\Line;

$formatter = new Line();
$formatter->setFormat('[%type%] - [%date%] - %message%');

$adapter = new Stream('/storage/logs/main.log');

$adapter->setFormatter($formatter);

$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

Формат даты

Формат даты по умолчанию::

"D, d M y H:i:s O"

Если формат сообщения по умолчанию не соответствует потребностям вашего приложения, вы можете изменить его с помощью метода setDateFormat (). Метод принимает строку с символами, соответствующими форматам дат. Для всех доступных форматов, пожалуйста, обратитесь к этой странице.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\Formatter\Line;

$formatter = new Line();
$formatter->setDateFormat('Ymd-His');

$adapter = new Stream('/storage/logs/main.log');

$adapter->setFormatter($formatter);

$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так'); 

который производит:

[ERROR] - [20181225-121314] - Something went wrong

Форматер JSON

Форматирует сообщения, возвращающие строку JSON:

{
    "type"      : "Тип сообщения",
    "message"   : "Сообщение",
    "timestamp" : "Дата, определенная в формате даты"
}

Формат даты

Формат даты по умолчанию:

"D, d M y H:i:s O"

Если формат сообщения по умолчанию не соответствует потребностям вашего приложения, вы можете изменить его с помощью метода setDateFormat(). Метод принимает строку с символами, соответствующими форматам дат. Для всех доступных форматов, пожалуйста, обратитесь к этой странице.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\Formatter\Line;

$formatter = new Line();
$formatter->setDateFormat('Ymd-His');

$adapter = new Stream('/storage/logs/main.log');
$adapter->setFormatter($formatter);

$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

который производит:

{
    "type"      : "error",
    "message"   : "Что-то пошло не так",
    "timestamp" : "20181225-121314"
}

Пользовательский форматтер

Интерфейс Phalcon\Logger\Formatter\FormatterInterface должен быть реализован для того, чтобы создать свой собственный форматер или расширить существующие. Кроме того, вы можете повторно использовать абстрактный класс Phalcon\Logger\Formatter\AbstractFormatter.

Интерполяция

Регистратор также поддерживает интерполяцию. Иногда вам может потребоваться ввести дополнительный текст в сообщения журнала; текст, который динамически создается вашим приложением. Это может быть легко достигнуто путем отправки массива в качестве второго параметра метода ведения журнала (например, error, info, alert и т. д.). Массив содержит ключи и значения, где ключ-это заполнитель в сообщении, а значение-это то, что будет введено в сообщение.

В следующем примере показана интерполяция путем введения в сообщение параметров "framework”и "secs".

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('/storage/logs/main.log');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$message = '{framework} выполнил тест "Hello World" за {secs} секунду(ы)';
$context = [
    'framework' => 'Phalcon',
    'secs'      => 1,
];

$logger->info($message, $context);

Пункт

Приведенные выше классы форматирования принимают объект Phalcon\Logger\Item. Объект содержит все необходимые данные, необходимые для процесса регистрации. Он используется для передачи данных из регистратора в форматтер.

Исключения

Любые исключения, генерируемые в компоненте Logger, будут иметь тип Phalcon\Logger\Exception. Вы можете использовать это исключение, чтобы выборочно перехватывать исключения, выданные только из этого компонента.

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;
use Phalcon\Logger\Exception;

try {
    $adapter = new Stream('/storage/logs/main.log');
    $logger  = new Logger(
        'messages',
        [
            'main' => $adapter,
        ]
    );
    
    // Log to all adapters
    $logger->error('Что-то пошло не так');
} catch (Exception $ex) {
    echo $ex->getMessage();
}

 

Примеры

Stream

Вход в файл:

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('/storage/logs/main.log');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

// Log to all adapters
$logger->error('Что-то пошло не так');

Stream logger записывает сообщения в действительный зарегистрированный поток на PHP. Список потоков доступен здесь. Вход в поток

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$adapter = new Stream('php://stderr');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

Syslog

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Syslog;

// Setting identity/mode/facility
$adapter = new Syslog(
    'ident-name',
    [
        'option'   => LOG_NDELAY,
        'facility' => LOG_MAIL,
    ]
);

$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

Noop

<?php

use Phalcon\Logger;
use Phalcon\Logger\Adapter\Noop;

$adapter = new Noop('nothing');
$logger  = new Logger(
    'messages',
    [
        'main' => $adapter,
    ]
);

$logger->error('Что-то пошло не так');

Пользовательские адаптеры

Интерфейс Phalcon\Logger\Adapter\AdapterInterface должен быть реализован для того, чтобы создавать свои собственные адаптеры регистратора или расширять существующие. Вы также можете воспользоваться функциональностью в абстрактном классе Phalcon\Logger\Adapter\AbstractAdapter.

Абстрактные классы

Существует два абстрактных класса, которые предлагают полезную функциональность при создании пользовательских адаптеров: Phalcon\Logger\Adapter\AbstractAdapter и Phalcon\Logger\Formatter\AbstractFormatter.

Внедрение зависимости

Вы можете зарегистрировать любое количество регистраторов в контейнере [Phalcon\Di\FactoryDefault][factorydefault]. Пример регистрации услуги и доступа к ней приведен ниже:

<?php

use Phalcon\Di;
use Phalcon\Logger;
use Phalcon\Logger\Adapter\Stream;

$container = new Di();

$container->set(
    'logger',
    function () use () {
        $adapter = new Stream('/storage/logs/main.log');
        $logger  = new Logger(
            'messages',
            [
                'main' => $adapter,
            ]
        );

        return new $logger;
    }
);