eccube4でアプリケーションエラーがあった際にメールを送信する


おおまかな手順は[Symfony](https://symfony.com/doc/current/logging/monolog_email.html)の公式に記載。

今回はローカルからmailtrapに送信する形で試した。
追記分以外はデフォルトの状態

```dev/public/app/config/eccube/packages/dev/monolog.yml
monolog:
    handlers:
        buffered:
            type:     buffer
            handler:  easylog
            channels: ["!event"]
            level:    debug
        easylog:
            type: service
            id:   easycorp.easylog.handler
        console:
            type: console
            process_psr_3_messages: false
            channels: ['!event', '!doctrine', '!console']
        #追記分
        app_error:
            type: fingers_crossed
            action_level: critical
            handler: deduplicated
        deduplicated:
            type: deduplication
            handler: swift
        swift:
            type:       swift_mailer
            from_email: error@example.com
            to_email:   example@example.com
            # to_email:   [' dev1@example.com ', ' dev2@example.com ', ...]
            # カンマ区切りで複数に指定できる
            subject:    'エラーを検知しました'
            #メールの件名
            level: error
            #本文に記載するどのレベルのErrorを記載するか
            formatter:  monolog.formatter.html
            content_type: text/html
            #htmlメールで送信する場合に必要

services:
    easycorp.easylog.handler:
        class: EasyCorp\EasyLog\EasyLogHandler
        public: false
        arguments:
            - '%kernel.logs_dir%/%kernel.environment%/site.log'

```

順番に解説していこう。

```yaml
app_error:
    type: fingers_crossed
    action_level: critical
    handler: deduplicated
```
まずはfingers_crossedに実行するための条件を設定する。
action_level別に設定できる。
この場合はlog_levelがcriticalの時にhandlerで設定している処理を呼び出す。
つまりはdeduplicatedを呼び出す。

##### action_level別条件の詳細

| critical | error  |
| -------- | -------- |
| 5xx系のHTTPコードエラー |4xx・5xxレベルのHTTPコードエラー|


```yaml
deduplicated:
    type: deduplication
    handler: swift
```
[公式](https://symfony.com/doc/current/logging/monolog_email.html)をgoogle翻訳で直訳するとdeduplicationの役割は重複するメッセージを削除した後に次のhandlerに処理を渡すイメージかな？

今回はswiftにいく

>deduplicatedハンドラーは、要求のすべてのメッセージを保持し、それらが特定の期間（デフォルトでは60秒）にわたって一意である場合にのみ、一度にネストされたハンドラーにそれらを渡します。 レコードが重複している場合、それらは破棄されます。 このハンドラーを追加すると、特に重大な障害シナリオでは、通知の量が管理可能なレベルに減少します。 timeオプションを使用して期間を調整できます。

timeオプションはよくわかってない。

```yaml
swift:
    type:       swift_mailer
    from_email: error@example.com
    to_email:   example@example.com
    # to_email:   [' dev1@example.com ', ' dev2@example.com ', ...]
    # カンマ区切りで複数に指定できる
    subject:    '[%%level_name%%][%%datetime%%]エラーを検知しました'
    #メールの件名
    level: error
    #本文に記載するどのレベルのErrorを記載するか
    formatter:  monolog.formatter.html
    content_type: text/html
    #htmlメールで送信する場合に必要
```
subjectには以下のフォーマットを出力することが出来る。

| フォーマット | 出力する項目  |
| -------- | -------- |
| %%datetime%% |日付|
| %%channel%%|チャネル名|
| %%level_name%%|レベル|
| %%message%%|メッセージ内容|
| %%context%%|コンテキスト情報|
| %%extra%%|追加情報|
最後にメール処理に関する設定を記述すれば完成。
細かい部分は見せられないがこんな感じでメールが届く。
![error.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126370/af29dc73-9de2-4778-f81f-628fbab1881f.jpeg)

入れ子になってないからイメージしづらいが、fingers_crossedから順に処理をつなげていくイメージでいいかと思う。

slackに飛ばすことも可能なので有料会員であればslackに投げるのもあり。
（無料だとログが残らない）

概念的な理解は以下の記事が非常にわかりやすかった
[PHPのロガーMonologを理解しよう](https://tech.quartetcom.co.jp/2018/05/31/monolog/)
[PHPのロギングmonologを理解する](https://reffect.co.jp/php/monolog-to-understand)