Дата обновления перевода 2021-06-02

Логирование

Symfony поставляется с минималистичным логгером PSR-3: Logger. В соответствии с `двенадцатифакторной методологией приложений`_, он отправляет сообщения, начиная с уровня WARNING до stderr.

Минимальный уровень лога может быть изменен путем установки переменной окружения SHELL_VERBOSITY:

значение SHELL_VERBOSITY Минимальный уровень лога
-1 ERROR
1 NOTICE
2 INFO
3 DEBUG

Минимальный уровень лога, вывод по умолчанию и формат лога могут также быть изменены путем передачи соответствующих аргументов коструктору Logger. Чтобы сделать это, переопределите определение сервиса “logger”.

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

Чтобы логировать сообщение, внедрите логгер по умолчанию в ваш контроллер или сервис:

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!', [
        // включить дополнительную информацию "контекста" в ваши логи
        'cause' => 'in_hurry',
    ]);

    // ...
}

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

Monolog

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

Например, используя Monolog вы можете сконфигурировать логгер так, чтобы он делал разные вещи, основываясь на уровне сообщения (например, отправлять email при возникновении ошибки).

Выполните эту команду, чтобы установить логгер, основанный на Monolog, перед его использованием:

1
$ composer require symfony/monolog-bundle

Следующие разделы предполагают, что Monolog установлен.

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

По умолчанию, логи записываются в файл 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 - самый низший уровень)
                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
    15
    16
    17
    // config/packages/prod/monolog.php
    use Symfony\Config\MonologConfig;
    
    return static function (MonologConfig $monolog) {
        // этот ключ "file_log" может быть чем угодно
        $monolog->handler('file_log')
            ->type('stream')
            // логировать в var/log/(environment).log
            ->path('%kernel.logs_dir%/%kernel.environment%.log')
            // логировать *все* сообщения (debug - самый низший уровень)
            ->level('debug');
    
        $monolog->handler('syslog_handler')
            ->type('syslog')
            // log error-level messages and higher
            ->level('error');
    };
    

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

Note

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

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

Вмето того, чтобы записовать файлы логов где-либо, некоторые обработчики используются, чтобы фильтровать или изменять записи логов перед тем, как отправлять их другим обработчикам. Один мощный встроенный обработчик под названием 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
    31
    32
    <!-- config/packages/prod/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
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/monolog
            https://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
    
        <monolog:config>
            <!-- если *один* лог - ошибка или выше, передать *все* в file_log -->
            <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
    20
    21
    22
    23
    24
    // config/packages/prod/monolog.php
    use Symfony\Config\MonologConfig;
    
    return static function (MonologConfig $monolog) {
        $monolog->handler('filter_for_errors')
            ->type('fingers_crossed')
            // если *один* лог - ошибка или выше, передать *все* в file_log
            ->actionLevel('error')
            ->handler('file_log')
        ;
    
        // теперь переданы *все* логи, но только если один из них ошибка или выше
        $monolog->handler('file_log')
            ->type('stream')
            ->path('%kernel.logs_dir%/%kernel.environment%.log')
            ->level('debug')
        ;
    
        // все еще передаются *все* логи, и все еще только если логи - ошибка или выше
        $monolog->handler('syslog_handler')
            ->type('syslog')
            ->level('error')
        ;
    };
    

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

Tip

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

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

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/prod/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
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/monolog
            https://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
    
        <monolog:config>
            <!-- "max-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
    // config/packages/prod/monolog.php
    use Symfony\Config\MonologConfig;
    
    return static function (MonologConfig $monolog) {
        $monolog->handler('main')
            ->type('rotating_file')
            ->path('%kernel.logs_dir%/%kernel.environment%.log')
            ->level('debug')
            // максимальное количество хранящихся файлов логов
            // по умолчанию равняется нулю, что означает бесконечное количество
            ->maxFiles(10);
    };
    

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

Если ваше приложение использует автоконфигурацию сервиса, любой сервис, клас которого реализует Psr\Log\LoggerAwareInterface, будет получать вызов к своему методу setLogger() с сервисами логгера по умолчанию переданными в качестве сервиса.

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

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

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

См. How to Add extra Data to Log Messages via a Processor, чтобы узнать детали.

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