# 通知設計書 21-メーラー処理イベント

## 概要

本ドキュメントは、Ruby on Rails フレームワークにおける `process.action_mailer` 計装イベント（Instrumentation Event）の仕様を定義する。このイベントは ActionMailer がメーラーアクションを処理する際に発行される内部計装通知であり、アプリケーションのパフォーマンス監視やデバッグに活用される。

### 本通知の処理概要

`process.action_mailer` イベントは、ActionMailer のメーラークラスでアクションメソッドが呼び出され、メール生成処理が実行される際に発行される計装イベントである。

**業務上の目的・背景**：Rails アプリケーションにおいて、メール送信は重要なビジネスプロセスの一部を構成する。このイベントを購読することで、どのメーラーのどのアクションがいつ実行されたか、処理にどれだけの時間がかかったかを計測・記録できる。これにより、メール生成処理のパフォーマンスボトルネックの特定、アプリケーション監視ツール（New Relic、Datadog 等）との連携、および本番環境でのトラブルシューティングが可能となる。

**通知の送信タイミング**：メーラークラスのアクションメソッド（例：`NotifierMailer.welcome`）が呼び出され、`process` メソッドが実行される際に発行される。具体的には、`ActionMailer::Base#process` メソッド内で `ActiveSupport::Notifications.instrument` を通じてイベントが発行される。イベントはブロックで囲まれており、メール生成処理の開始から終了までの時間が計測される。

**通知の受信者**：このイベントは `ActiveSupport::Notifications.subscribe` を使用して購読するサブスクライバーに配信される。デフォルトでは `ActionMailer::LogSubscriber` と `ActionMailer::StructuredEventSubscriber` が購読しており、ログ出力や構造化イベントの生成を行う。アプリケーション開発者やAPMツールが独自のサブスクライバーを登録することも可能。

**通知内容の概要**：イベントのペイロードには、メーラークラス名（`:mailer`）、実行されたアクション名（`:action`）、およびアクションに渡された引数（`:args`）が含まれる。イベント自体には開始時刻、終了時刻、処理時間（duration）、ユニークIDなどのメタデータも含まれる。

**期待されるアクション**：受信者（サブスクライバー）は、このイベントを使用してメール生成処理のログ記録、メトリクス収集、パフォーマンス監視ダッシュボードへのデータ送信、またはカスタムビジネスロジックの実行を行うことが期待される。

## 通知種別

計装通知（ActiveSupport::Notifications Instrumentation Event）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ブロック実行中にイベント発行） |
| 優先度 | 中（計装イベントとして標準的な優先度） |
| リトライ | なし（計装イベントは一度のみ発行） |

### 送信先決定ロジック

`ActiveSupport::Notifications` に登録されているすべてのサブスクライバーに対してブロードキャストされる。サブスクライバーは以下の方法で登録可能：

1. `ActiveSupport::Notifications.subscribe("process.action_mailer")` - 特定イベントの購読
2. `ActiveSupport::Notifications.subscribe(/action_mailer/)` - 正規表現による複数イベントの購読
3. `ActiveSupport::Notifications.subscribe(nil)` - すべてのイベントの購読

## 通知テンプレート

### イベントペイロード

| 項目 | 内容 |
|-----|------|
| イベント名 | `process.action_mailer` |
| 名前空間 | `action_mailer` |
| ペイロード形式 | Ruby Hash |

### ペイロード構造

```ruby
{
  mailer: "NotificationMailer",  # メーラークラス名（String）
  action: "welcome_email",       # アクション名（Symbol/String）
  args: []                       # アクションに渡された引数（Array）
}
```

### 添付ファイル

該当なし（計装イベントには添付ファイルは含まれない）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| `:mailer` | メーラークラスの名前 | `self.class.name` | Yes |
| `:action` | 実行されるアクションメソッドの名前 | `method_name` 引数 | Yes |
| `:args` | アクションメソッドに渡される引数の配列 | `*args` 引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| メソッド呼び出し | メーラーアクションの実行 | 常に送信 | `ActionMailer::Base#process` が呼び出されると必ず発行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | このイベントには送信抑止条件はない。processメソッドが呼び出されれば必ず発行される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[メーラーアクション呼び出し] --> B[MessageDelivery生成]
    B --> C[message/deliver_now等の呼び出し]
    C --> D[ActionMailer::Base#process 実行]
    D --> E[payload構築]
    E --> F[ActiveSupport::Notifications.instrument]
    F --> G[process.action_mailerイベント開始]
    G --> H[親クラスのprocess実行]
    H --> I[テンプレートレンダリング]
    I --> J[Mail::Message生成]
    J --> K[process.action_mailerイベント終了]
    K --> L[サブスクライバーへ通知]
    L --> M[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（計装イベント自体はデータベースを参照しない）

### 更新テーブル一覧

該当なし（計装イベント自体はデータベースを更新しない）

注：サブスクライバーの実装によっては、ログやメトリクスをデータベースに保存する可能性がある。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| サブスクライバーエラー | サブスクライバー内で例外が発生 | エラーは伝播せず、他のサブスクライバーの処理は継続 |
| processメソッドエラー | メール生成中に例外が発生 | イベントは終了し、例外情報がペイロードに追加される |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（メーラー呼び出しごとに発行） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（メーラー処理が実行されるタイミングで即座に発行）

## セキュリティ考慮事項

- ペイロードの `:args` にはメーラーアクションに渡された引数が含まれる可能性があり、これには個人情報（メールアドレス、ユーザー情報等）が含まれる場合がある
- サブスクライバーでログ出力やメトリクス送信を行う際は、機密情報のマスキングやフィルタリングを検討すること
- APMツールへのデータ送信時は、PII（個人識別情報）の取り扱いポリシーに従うこと

## 備考

- このイベントは Rails 5.1 で導入された
- `deliver.action_mailer` イベント（メール配信イベント）とは異なり、こちらはメール生成（process）のタイミングで発行される
- 非同期配信（`deliver_later`）の場合、このイベントはジョブ実行時に発行される

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、イベントのペイロード構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | ペイロードの構築（645-650行目）を確認 |

**読解のコツ**: `payload` ハッシュがどのようなキーと値を持つかを確認する。`:mailer`, `:action`, `:args` の3つのキーが設定される。

#### Step 2: エントリーポイントを理解する

処理の起点となるメソッドを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | `process` メソッド（645-657行目）がイベント発行の起点 |

**主要処理フロー**:
1. **645行目**: `process` メソッドの定義開始
2. **646-650行目**: ペイロードの構築（mailer, action, args）
3. **652行目**: `ActiveSupport::Notifications.instrument` によるイベント発行
4. **653行目**: 親クラス（AbstractController）の `process` メソッド呼び出し

#### Step 3: ログサブスクライバーを理解する

デフォルトのサブスクライバーがどのようにイベントを処理するかを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | log_subscriber.rb | `actionmailer/lib/action_mailer/log_subscriber.rb` | `processed` メソッド（27-34行目）でログ出力を確認 |
| 3-2 | structured_event_subscriber.rb | `actionmailer/lib/action_mailer/structured_event_subscriber.rb` | `process` メソッド（27-33行目）で構造化イベント生成を確認 |

**主要処理フロー**:
- **log_subscriber.rb 27-33行目**: デバッグログとして「メーラー名#アクション名: processed outbound mail in Xms」を出力
- **structured_event_subscriber.rb 27-32行目**: 構造化イベントを発行（mailer, action, duration_ms）

#### Step 4: メッセージ配信フローを理解する

メーラーがどのように呼び出されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | base.rb | `actionmailer/lib/action_mailer/base.rb` | `method_missing`（624-629行目）でメーラーアクション呼び出しを処理 |

**主要処理フロー**:
- **624-629行目**: クラスメソッドとしてメーラーアクションが呼び出されると `MessageDelivery` オブジェクトを生成

### プログラム呼び出し階層図

```
NotifierMailer.welcome(user)           # メーラーアクション呼び出し
    |
    +-- ActionMailer::Base.method_missing
            |
            +-- MessageDelivery.new(NotifierMailer, :welcome, user)
                    |
                    +-- MessageDelivery#message / #deliver_now / #deliver_later
                            |
                            +-- ActionMailer::Base#process(:welcome, user)
                                    |
                                    +-- ActiveSupport::Notifications.instrument("process.action_mailer")
                                            |
                                            +-- AbstractController::Base#process
                                            |       |
                                            |       +-- #welcome メソッド実行
                                            |       +-- #mail メソッド実行
                                            |       +-- テンプレートレンダリング
                                            |
                                            +-- サブスクライバーへの通知
                                                    |
                                                    +-- LogSubscriber#processed
                                                    +-- StructuredEventSubscriber#process
```

### データフロー図

```
[入力]                          [処理]                              [出力]

メーラークラス名 ─────────────┐
                              │
アクション名 ─────────────────┼──▶ ActionMailer::Base#process ──▶ process.action_mailer イベント
                              │           │
引数配列 ─────────────────────┘           │
                                          ▼
                              ActiveSupport::Notifications.instrument
                                          │
                                          ▼
                              ┌───────────────────────────┐
                              │     サブスクライバー       │
                              │  - LogSubscriber          │ ──▶ ログ出力
                              │  - StructuredEventSub     │ ──▶ 構造化イベント
                              │  - カスタムサブスクライバー │ ──▶ APM/メトリクス
                              └───────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| base.rb | `actionmailer/lib/action_mailer/base.rb` | ソース | メーラー基底クラス、イベント発行元 |
| log_subscriber.rb | `actionmailer/lib/action_mailer/log_subscriber.rb` | ソース | ログ出力用サブスクライバー |
| structured_event_subscriber.rb | `actionmailer/lib/action_mailer/structured_event_subscriber.rb` | ソース | 構造化イベント用サブスクライバー |
| message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | ソース | メーラー呼び出しのラッパー |
| active_support_instrumentation.md | `guides/source/active_support_instrumentation.md` | ドキュメント | 公式計装ガイド |
| base_test.rb | `actionmailer/test/base_test.rb` | テスト | メーラー基本機能のテスト |
