Как сконфигурировать Monolog так, чтобы он отправлял ошибки по электронной почте

Как сконфигурировать Monolog так, чтобы он отправлял ошибки по электронной почте

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

  • YAML
     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
    # app/config/config_prod.yml
    monolog:
        handlers:
            mail:
                type:         fingers_crossed
                # на критическом уровне логируется 500 ошибок
                action_level: critical
                # чтобы также логировать уровень 400 ошибок (но не ошибок 404):
                # action_level: error
                # excluded_404s:
                #     - ^/
                handler:      deduplicated
            deduplicated:
                type:    deduplication
                handler: swift
            swift:
                type:       swift_mailer
                from_email: '[email protected]'
                to_email:   '[email protected]'
                # или список получателей
                # to_email:   ['[email protected]', '[email protected]', ...]
                subject:    'An Error Occurred! %%message%%'
                level:      debug
                formatter:  monolog.formatter.html
                content_type: text/html
    
  • 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    <!-- app/config/config_prod.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>
            <!--
            на критическом уровне логируется 500 ошибок
            чтобы также логировать уровень 400 ошибок (но не ошибок 404):
            action-level="error"
            And add this child inside this monolog:handler
            <monolog:excluded-404>^/</monolog:excluded-404>
            -->
            <monolog:handler
                name="mail"
                type="fingers_crossed"
                action-level="critical"
                handler="deduplicated"
            />
            <monolog:handler
                name="deduplicated"
                type="deduplication"
                handler="swift"
            />
            <monolog:handler
                name="swift"
                type="swift_mailer"
                from-email="[email protected]"
                subject="An Error Occurred! %%message%%"
                level="debug"
                formatter="monolog.formatter.html"
                content-type="text/html">
    
                <monolog:to-email>[email protected]</monolog:to-email>
    
                <!-- или список получателей -->
                <!--
                <monolog:to-email>[email protected]</monolog:to-email>
                <monolog:to-email>[email protected]</monolog:to-email>
                ...
                -->
            </monolog:handler>
        </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
    25
    26
    27
    28
    29
    30
    31
    // app/config/config_prod.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            'mail' => array(
                'type'         => 'fingers_crossed',
                // на критическом уровне логируется 500 ошибок
                'action_level' => 'critical',
                // чтобы также логировать уровень 400 ошибок (но не ошибок 404):
                // 'action_level' => 'error',
                // 'excluded_404s' => array(
                //     '^/',
                // ),
                'handler'      => 'deduplicated',
            ),
            'deduplicated' => array(
                'type'    => 'deduplication',
                'handler' => 'swift',
            ),
            'swift' => array(
                'type'         => 'swift_mailer',
                'from_email'   => '[email protected]',
                'to_email'     => '[email protected]',
                // или список получателей
                // 'to_email'   => array('[email protected]', '[email protected]', ...),
                'subject'      => 'An Error Occurred! %%message%%',
                'level'        => 'debug',
                'formatter'    => 'monolog.formatter.html',
                'content_type' => 'text/html',
            ),
        ),
    ));
    

Обработчик mail - это обработчик fingers_crossed, что означает, что он запускается только, когда достигнут уровень действия, в этом случае - critical. Уровень critical запускается только для ошибок HTTP-кода 5xx. Если этот уровень достигнут единожды, обработчик fingers_crossed будет логировать все сообщения, не глядя на их уровень. Настройка handler означает, что вывод потом передаётся в обработчик deduplicated.

Tip

Если вы хотите, чтобы и ошибки 400 и 500 уровня вызывали отправку письма, установите action_level в значении error вместо critical. См. код выше, чтобы увидеть пример.

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

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

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

  • YAML
     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
    # app/config/config_prod.yml
    monolog:
        handlers:
            main:
                type:         fingers_crossed
                action_level: critical
                handler:      grouped
            grouped:
                type:    group
                members: [streamed, deduplicated]
            streamed:
                type:  stream
                path:  '%kernel.logs_dir%/%kernel.environment%.log'
                level: debug
            deduplicated:
                type:    deduplication
                handler: swift
            swift:
                type:       swift_mailer
                from_email: '[email protected]'
                to_email:   '[email protected]'
                subject:    'An Error Occurred! %%message%%'
                level:      debug
                formatter:  monolog.formatter.html
                content_type: text/html
    
  • 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <!-- app/config/config_prod.xml -->
    <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="main"
                type="fingers_crossed"
                action_level="critical"
                handler="grouped"
            />
            <monolog:handler
                name="grouped"
                type="group"
            >
                <member type="stream"/>
                <member type="deduplicated"/>
            </monolog:handler>
            <monolog:handler
                name="stream"
                path="%kernel.logs_dir%/%kernel.environment%.log"
                level="debug"
            />
            <monolog:handler
                name="deduplicated"
                type="deduplication"
                handler="swift"
            />
            <monolog:handler
                name="swift"
                type="swift_mailer"
                from-email="[email protected]"
                subject="An Error Occurred! %%message%%"
                level="debug"
                formatter="monolog.formatter.html"
                content-type="text/html">
    
                <monolog:to-email>[email protected]</monolog:to-email>
    
                <!-- or list of recipients -->
                <!--
                <monolog:to-email>[email protected]</monolog:to-email>
                <monolog:to-email>[email protected]</monolog:to-email>
                ...
                -->
            </monolog:handler>
        </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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    // app/config/config_prod.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            'main' => array(
                'type'         => 'fingers_crossed',
                'action_level' => 'critical',
                'handler'      => 'grouped',
            ),
            'grouped' => array(
                'type'    => 'group',
                'members' => array('streamed', 'deduplicated'),
            ),
            'streamed'  => array(
                'type'  => 'stream',
                'path'  => '%kernel.logs_dir%/%kernel.environment%.log',
                'level' => 'debug',
            ),
            'deduplicated' => array(
                'type'     => 'deduplication',
                'handler'  => 'swift',
            ),
            'swift' => array(
                'type'         => 'swift_mailer',
                'from_email'   => '[email protected]',
                'to_email'     => '[email protected]',
                // или список получателей
                // 'to_email'   => array('[email protected]', '[email protected]', ...),
                'subject'      => 'An Error Occurred! %%message%%',
                'level'        => 'debug',
                'formatter'    => 'monolog.formatter.html',
                'content_type' => 'text/html',
            ),
        ),
    ));
    

Используется обработчик group для отправки сообщений двум членамгруппы, обработчики deduplicated и stream. Теперь оба сообщения будут записаны в файл логов и отправлены по электронной почте.

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