Логирование с помощью Monolog

Symfony безупречно интегрирована с Monolog, наиболее популярной PHP библиотекой логирования, для создания и хранения сообщений логов в ряде различных мест.

Установка

В приложениях, использующих Symfony Flex, выполните эту команду, чтобы установить логгер, основанный на Monolog, перед тем, как его использовать:

1
$ composer require logger

Логирование сообщения

Если приложение использует конфигурацию services.yaml по умолчанию, то вы можете получить сервис логирования, внедрив класс LoggerInterface:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
use Psr\Log\LoggerInterface;

public function index(LoggerInterface $logger)
{
    $logger->info('I just got the logger');
    $logger->error('An error occurred');

    $logger->critical('I left the oven on!', array(
        // включить дополнительную информацию "контекста" в ваши логи
        'cause' => 'in_hurry',
    ));

    // ...
}

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

Смотрите LoggerInterface, чтобы увидеть список всех методов логгера.

Где хранятся логи

По умолчанию, логи записываются в файл var/log/dev.log когда вы находитесь в окружении dev. В окружении prod, логи записываются в var/log/prod.log, но только во время запроса, в котором была ошибка или высокоприоритетный лог (т.е. error() , critical(), alert() или emergency()).

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

Обработчики: Запись логов в разных локациях

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

Tip

Вы также можете конфигурировать "каналы" логирования, которые схожи с категориями. Каждый канал может иметь свои собственные обработчики, что означает, что вы можете хранить разные сообщения логов в разных местах. См. Обработчики каналов </logging/channels_handlers?.

Symfony предварительно конфигурирует некоторые базовые обработчики в файлах конфигурации по умолчанию monolog.yaml. Посмотрите на них, чтобы увидеть настоящие примеры.

Этот пример использует два обработчика:stream (чтобы записывать в файл) и syslog, чтобы записывать логи, используя функцию syslog:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    # config/packages/monolog.yaml
    monolog:
        handlers:
            # этот ключ "file_log" может быть чем угодно
            file_log:
                type: stream
                # логировать в var/log/(environment).log
                path: "%kernel.logs_dir%/%kernel.environment%.log"
                # логировать *все* сообщения (debug is lowest level)
                level: debug
    
            syslog_handler:
                type: syslog
                # логировать сообщения уровня ошибок и выше
                level: error
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!-- config/packages/monolog.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:monolog="http://symfony.com/schema/dic/monolog"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/monolog
            http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
    
        <monolog:config>
            <monolog:handler
                name="file_log"
                type="stream"
                path="%kernel.logs_dir%/%kernel.environment%.log"
                level="debug"
            />
            <monolog:handler
                name="syslog_handler"
                type="syslog"
                level="error"
            />
        </monolog:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    // config/packages/monolog.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            'file_log' => array(
                'type'  => 'stream',
                'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
                'level' => 'debug',
            ),
            'syslog_handler' => array(
                'type'  => 'syslog',
                'level' => 'error',
            ),
        ),
    ));
    

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

Обработчики, которые изменяют записи логов

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

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # config/packages/monolog.yaml
    monolog:
        handlers:
            filter_for_errors:
                type: fingers_crossed
                # если *один* лог - ошибка или выше, передать *все* в file_log
                action_level: error
                handler: file_log
    
            # теперь переданы *все* логи, но только если один из них ошибка или выше
            file_log:
                type: stream
                path: "%kernel.logs_dir%/%kernel.environment%.log"
    
            # все еще передаются *все* логи, и все еще только если логи - ошибка или выше
            syslog_handler:
                type: syslog
                level: error
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <!-- config/packages/monolog.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:monolog="http://symfony.com/schema/dic/monolog"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/monolog
            http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
    
        <monolog:config>
            <monolog:handler
                name="filter_for_errors"
                type="fingers_crossed"
                action-level="error"
                handler="file_log"
            />
            <monolog:handler
                name="file_log"
                type="stream"
                path="%kernel.logs_dir%/%kernel.environment%.log"
                level="debug"
            />
            <monolog:handler
                name="syslog_handler"
                type="syslog"
                level="error"
            />
        </monolog:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // config/packages/monolog.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            'filter_for_errors' => array(
                'type'         => 'fingers_crossed',
                'action_level' => 'error',
                'handler'      => 'file_log',
            ),
            'file_log' => array(
                'type'  => 'stream',
                'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
                'level' => 'debug',
            ),
            'syslog_handler' => array(
                'type'  => 'syslog',
                'level' => 'error',
            ),
        ),
    ));
    

Теперь, даже если одна запись лога имеет уровень error или выше, то все записи логов для этого запроса сохраняются в файл с помощью обработчика file_log. Это означает, что ваш файл логов будет содержать все детали о проблематичном запросе, что значительно облегчит отладку!

Tip

Обработчик, называнный "file_log" не будет включен в стопку, так как он используется в качестве гнездового обработчика fingers_crossed.

Note

Если вы хотите переопределить конфигурацию monolog с помощью другого файла конфигурации, вам понадобится переопределить всю стопку handlers. Конфигурация двух файлов не может быть объединена, так как порядок имеет значение, а слияение не позволяет контролировать порядок.

Все встроенные обработчики

Monolog поставляется со многими встроенными обработчиками для отправки логов по почте, отправки их в Loggly, или для оповещения вас в Slack. Они документируются внутри самого MonologBundle. Для полного списка, см. Конфигурация Monolog.

Как чередовать ваши файлы логов

Со временем, файлы логов могут вырасти огромными, как во время разработки, так и в производстве. Наилучшей практикой решения является исползование инструмента вроде команды Linux logrotate для чередования файлов логов до того, как они станут слишком большими.

Еще одна опция - заставить Monolog чередовать файлы за вас, используя обработчик rotating_file. Этот обработчик создает новый файл логов каждый день, а также может удалять старые файлы автоматически. Чтобы использовать его, просто установите опцию``type`` вашего обработчика как rotating_file:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    # config/packages/dev/monolog.yaml
    monolog:
        handlers:
            main:
                type:  rotating_file
                path:  '%kernel.logs_dir%/%kernel.environment%.log'
                level: debug
                # максимальное количество хранящихся файлов логов
                # по умолчанию равняется нулю, что означает бесконечное количество
                max_files: 10
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!-- config/packages/dev/monolog.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:monolog="http://symfony.com/schema/dic/monolog"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            http://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/monolog
            http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
    
        <monolog:config>
            <!-- "max_files": max number of log files to keep
                 defaults to zero, which means infinite files -->
            <monolog:handler name="main"
                type="rotating_file"
                path="%kernel.logs_dir%/%kernel.environment%.log"
                level="debug"
                max-files="10"
            />
        </monolog:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    // config/packages/dev/monolog.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            'main' => array(
                'type'  => 'rotating_file',
                'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
                'level' => 'debug',
                // max number of log files to keep
                // defaults to zero, which means infinite files
                'max_files' => 10,
            ),
        ),
    ));
    

Использование Logger внутри сервиса

Чтобы использовать логгер в ваших собственных сервисах, добавьте сервис @logger в качестве аргумента к этим сервисам. Если вы хотите использовать в своих сервисах предварительно сконфигурированный логгер, который использует особенный канал (по умолчанию app),используйте тег monolog.logger со свойством channel, как объясняется в Справочнике внедрения зависимостей.

Добавление дополнительных данных в каждый лог (например, метки уникального запроса)

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

См. Процессоры, чтобы узнать детали.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.