Как сконфигурировать 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
    # config/packages/prod/monolog.yaml
    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
    <!-- 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
            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"
            И добавьте эту дочь внутрь 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
    // config/packages/prod/monolog.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 секунд). Если записи являются дубликатами, то они просто сбрасываются. Добавление этого обработчика уменьшает объем уведомлений до управляемого уровня, особенно в сценариях критического отказа. Вы можете настроить временной промежуток, используя опцию time:

  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # config/packages/prod/monolog.yaml
    monolog:
        handlers:
            # ...
            deduplicated:
                type: deduplication
                # время в секундах, в течение которого удаляются дублированные записи (по умолчанию: 60)
                time: 10
                handler: swift
    
  • XML
    1
    2
    3
    4
    5
    6
    7
    <!-- config/packages/prod/monolog.xml -->
    
    <!-- время: время в секундах, в течение которого удаляются дублированные записи (по умолчанию: 60) -->
    <monolog:handler name="deduplicated"
        type="deduplication"
        time="10"
        handler="swift" />
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    // config/packages/prod/monolog.php
    $container->loadFromExtension('monolog', array(
        'handlers' => array(
            // ...
            'deduplicated' => array(
                'type'    => 'deduplication',
                // время в секундах, в течение которого удаляются дублированные записи (по умолчанию: 60)
                'time' => 10,
                'handler' => 'swift',
             )
    

Потом сообщения передаются обработчику 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
    # config/packages/prod/monolog.yaml
    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
    <!-- config/packages/prod/monolog.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
    // config/packages/prod/monolog.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]',
                // or a list of recipients
                // '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.