Как записывать логи сообщений в разные файлы

Дата обновления перевода 2024-07-25

Как записывать логи сообщений в разные файлы

Фреймворк Symfony организовывает сообщения логов в каналы. По умолчанию, существует несколько каналов, включая doctrine, event, security, request и другие. Канал печатается в сообщении лога и может также быть использован для направления разных каналов в разные места/файлы.

По умолчанию, Symfony записывает каждое сообщение в один и тот же файл (не зависимо от канала).

Note

Каждый канал соответствует сервису логирования (monolog.logger.XXX) в контейнере (используйте команду debug:container, чтоб увидеть полный список), и они внедряются в разные сервисы.

Переключение канала на другой обработчик

Теперь, представьте, что вы хотите логировать канал security в другой файл. Чтобы сделать это, создайте новый обработчик и сконфигурируйте его так, чтобы он записывал только сообщения из канала security. Следующий ример делает это только в prod окружении конфигурации , но вы можете сделать это в любом (или всех) окружениях:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config/packages/prod/monolog.yaml
monolog:
    handlers:
        security:
            # логировать все сообщения (так как отладка - нижайший уровень)
            level:    debug
            type:     stream
            path:     '%kernel.logs_dir%/security.log'
            channels: [security]

        # пример *отсутствия* логирования сообщений канала безопасности для этого обработчика
        main:
            # ...
            # channels: ['!security']

Caution

Конфигурация channels работает только для обработчиков высшего уровня. Обработчики, которые вложены в группу, буфер, фильтр, авось или что-либо подобное, будут игнорировать эту конфигурацию и обрабатывать каждое переданное им сообщение.

Вы можете указать конфигурацию многими способами:

1
2
3
4
5
6
7
channels: ~    # Включить все каналы

channels: foo  # Включить только канал 'foo'
channels: '!foo' # Включить все каналы, кроме 'foo'

channels: [foo, bar]   # Включить только каналы 'foo' и 'bar'
channels: ['!foo', '!bar'] # Включить все каналы, кроме 'foo' и 'bar'

Создание вашего собственного канала

Вы можете изменить канал записи логов Monolog по одному сервису за раз. Это делается либо через конфигурацию ниже, либо с помощью тегирования вашего сервиса monolog.logger и указания того, в каком канале сервис должен записывать логи. С тегом, обработчик логов, который внедряется в сервис, предварительно сконфигурирован так, чтобы использовать канал, который вы указали.

Конфигурация дополнительных канало без тегированных сервисов

Вы также можете сконфигурировать дополнительные каналы без необходимости тегировать ваши сервисы:

1
2
3
# config/packages/monolog.yaml
monolog:
    channels: ['foo', 'bar', 'foo_bar']

Symfony автоматически регистрирует по одному сервису на канал (в этом примере, канал foo создаёт сервис под названием monolog.logger.foo). Для того, чтобы внедрить этот сервис в другие, вы должны обновить конфигурацию сервиса, чтобы выбрать конкретный сервис для внедрения .

Как автомонтиорвать каналы логгера

Начиная с MonologBundle 3.5, вы можете автомонтиовать разные каналы Monolog, добавляя в ваши аргументы сервиса подсказки со следующим синтаксисом: Psr\Log\LoggerInterface $<camelCased channel name> + Logger. <channel> должен быть предопределён в вашей конфигурации Monolog .

Например, чтобы внедрить сервис, связанный с каналом логгера foo_bar, измените ваш конструктор таким образом:

1
2
3
4
5
public function __construct(
-     LoggerInterface $logger,
+     LoggerInterface $fooBarLogger,
    ) {
    }

Конфигурация каналов логгера с помощью атрибутов

Начиная с Monolog 3.5 вы также можете настроить канал логгера, используя атрибут #[WithMonologChannel] непосредственно в вашем классе сервиса:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Service/MyFixtureService.php
namespace App\Service;

use Monolog\Attribute\WithMonologChannel;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Monolog\Logger;

#[WithMonologChannel('fixtures')]
class MyFixtureService
{
    public function __construct(LoggerInterface $logger)
    {
        // ...
    }
}

Таким образом, вы сможете избежать объявления сервиса вручную для использования определенного канала.

3.5

Атрибут #[WithMonologChannel] был представлен в Monolog 3.5.0.