如何配置Monolog来发送错误邮件

3.4 版本
维护中的版本

Monolog 可被配置为“当程序有错误发生时”发送一封邮件。这种配置,需要一些嵌套的handlers,为的是避免收到过多邮件。初看配置信息会觉得很复杂,但细分起来,每种控制器都很直白:

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
# app/config/config_prod.yml
monolog:
    handlers:
        mail:
            type:         fingers_crossed
            # 500 errors are logged at the critical level
            # 500错误被记录到critical level(严苛级别)
            action_level: critical
            # to also log 400 level errors (but not 404's):
            # 同时记录了400级别的错误(但不包括404):
            # action_level: error
            # excluded_404s:
            #     - ^/
            handler:      deduplicated
        deduplicated:
            type:    deduplication
            handler: swift
        swift:
            type:       swift_mailer
            from_email: 'error@example.com'
            to_email:   'error@example.com'
            # or list of recipients / 或提供收件列表
            # to_email:   ['dev1@example.com', 'dev2@example.com', ...]
            subject:    "An Error Occurred! %%message%%"
            level:      debug
            formatter:  monolog.formatter.html
            content_type: text/html
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
<!-- 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 errors are logged at the critical level,
        to also log 400 level errors (but not 404's):
        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="error@example.com"
            subject='An Error Occurred! %%message%%'
            level="debug"
            formatter="monolog.formatter.html"
            content-type="text/html">
 
            <monolog:to-email>error@example.com</monolog:to-email>
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 errors are logged at the critical level
            'action_level' => 'critical',
            // to also log 400 level errors (but not 404's):
            // 'action_level' => 'error',
            // 'excluded_404s' => array(
            //     '^/',
            // ),
            'handler'      => 'deduplicated',
        ),
        'deduplicated' => array(
            'type'    => 'deduplication',
            'handler' => 'swift',
        ),
        'swift' => array(
            'type'         => 'swift_mailer',
            'from_email'   => 'error@example.com',
            'to_email'     => 'error@example.com',
            // or a list of recipients
            // 'to_email'   => array('dev1@example.com', 'dev2@example.com', ...),
            'subject'      => "An Error Occurred! %%message%%,
            'level'        => 'debug',
            'formatter'    => 'monolog.formatter.html',
            'content_type' => 'text/html',
        ),
    ),
));

mail handler是一个 fingers_crossed handler,这表明仅当动作级别(action level)达到 critical 时才会被触发。critical 仅在5xx HTTP错误代码(出现时)触发。一旦达成, fingers_crossed 将记录下所有信息而不管其action级别。 handler 设置表明,输出信息将被继续传入到 deduplicated handler中。

如果你希望400 level 和 500 level的错误都可以触发邮件,设置 action_levelerror 而不是 critical。可参考上例。

那个 deduplicated 控制器只是单纯保存了请求中的全部信息,然后将它们传向另一个嵌套的控制器,但仅当给定周期(默认60秒)之内的记录唯一时(才实施)。若有重复记录,信息会被放弃。添加这个控制器可将通知(notification)的数量减少到一个可维护的水平,特别是在critical级别的失败场合下。

然后,这些信息会被传入到 swift handler中。这个控制器真正用于发送你的错误。其配置是直白的,包括to和from地址,formatter,content type以及主题。

你可以将这些控制器与另一个控制器组合使用,以便令错误信息在邮件发送之后,仍然记录在服务器上:

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: 'error@example.com'
            to_email:   'error@example.com'
            subject:    "An Error Occurred! %%message%%"
            level:      debug
            formatter:  monolog.formatter.html
            content_type: text/html
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
<!-- 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="error@example.com"
            subject="An Error Occurred! %%message%%"
            level="debug"
            formatter="monolog.formatter.html"
            content-type="text/html">
 
            <monolog:to-email>error@example.com</monolog:to-email>
 
            <!-- or list of recipients -->
            <!--
            <monolog:to-email>dev1@example.com</monolog:to-email>
            <monolog:to-email>dev2@example.com</monolog:to-email>
            ...
            -->
        </monolog:handler>
    </monolog:config>
</container>
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'   => 'error@example.com',
            'to_email'     => 'error@example.com',
            // or a list of recipients
            // 'to_email'   => array('dev1@example.com', 'dev2@example.com', ...),
            'subject'      => 'An Error Occurred! %%message%%',
            'level'        => 'debug',
            'formatter'    => 'monolog.formatter.html',
            'content_type' => 'text/html',
        ),
    ),
));

这时要用到 group 控制器,以将信息发送到两个组内成员,即 deduplicatedstream handlers。信息会被同时写入日志以及送出邮件。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)