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

Реализует PSR-3.

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

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

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

Адаптеры

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

АдаптерОписание
Phalcon\Logger\Adapter\Noop Логи в текстовый файл
Phalcon\Logger\Adapter\Stream Логи в PHP потоки
Phalcon\Logger\Adapter\Syslog Логи в системный журнал

Stream

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

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.

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

<?php

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

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

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

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

newInstance()

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);

Создание журнала

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

<?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. Затем мы создадим объект регистратора и присоединим к нему этот адаптер. Каждый адаптер, подключенный к регистратору, должен иметь уникальное имя, чтобы регистратор мог знать, где регистрировать сообщения. При вызове метода error() для объекта logger сообщение будет сохранено в файле /storage/logs/main.log.

Поскольку компонент регистратора реализует 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('Something happened');

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

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

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

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

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

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

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

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

Line Formatter

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

[%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('Something went wrong');

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

[ALERT] - [Tue, 25 Dec 18 12:13:14 -0400] - Something went wrong

Если вы не хотите использовать конструктор для изменения сообщения, вы всегда можете использовать 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"      : "Type of the message",
    "message"   : "The message",
    "timestamp" : "The date as defined in the date format"
}

Формат даты

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

"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"   : "Something went wrong",
    "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} executed the "Привет Мир" test in {secs} second(s)';
$context = [
    'framework' => 'Phalcon',
    'secs'      => 1,
];

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

Item

Классы форматирования выше принимают объект 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,
        ]
    );
    
    // Журнал для всех адаптеров
    $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,
    ]
);

// Журнал для всех адаптеров
$logger->error('Что-то пошло не так');

Потоковый регистратор записывает сообщения в действительный зарегистрированный поток в 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;
    }
);