# 通知設計書 26-SparkListenerApplicationStart

## 概要

本ドキュメントは、Apache SparkにおけるSparkListenerApplicationStartイベント通知の設計仕様を定義する。このイベントは、Sparkアプリケーションが開始された際に発火し、アプリケーションの基本情報（名前、ID、ユーザー、開始時刻など）をリスナーに通知する。

### 本通知の処理概要

本通知は、SparkContextの初期化完了後にアプリケーション開始情報をすべてのリスナーに配信するイベントである。Sparkアプリケーションのライフサイクルにおいて最も重要な初期イベントの一つである。

**業務上の目的・背景**：Sparkアプリケーションの開始を正式に記録し、Spark UIおよび履歴サーバでアプリケーション情報を表示するための基盤データを提供する。アプリケーション名、アプリケーションID、開始時刻、ユーザー名などのメタデータは、ジョブの追跡・監視・監査において不可欠な情報である。

**通知の送信タイミング**：SparkContext.postApplicationStart()メソッドが呼ばれた際に発火する。このメソッドはSparkContextの初期化プロセスの中で、タスクスケジューラが初期化されクラスタマネージャからアプリケーションIDを取得した後に呼ばれる。

**通知の受信者**：LiveListenerBusに登録されたすべてのSparkListenerInterface実装クラス。主要な受信者はAppStatusListener（アプリケーション情報のKVStore書き込み）、EventLoggingListener（イベントログへの永続化）、FsHistoryProvider（履歴サーバでのアプリケーション情報管理）である。

**通知内容の概要**：appName（アプリケーション名）、appId（アプリケーションID、Option型）、time（開始時刻）、sparkUser（実行ユーザー）、appAttemptId（試行ID、Option型）、driverLogs（ドライバログURL、Option型）、driverAttributes（ドライバ属性、Option型）の7フィールドを含む。

**期待されるアクション**：AppStatusListenerがアプリケーション情報をKVStoreに書き込み、Spark UIに表示する。EventLoggingListenerがイベントログに記録する。履歴サーバがアプリケーション一覧に追加する。

## 通知種別

アプリ内イベント通知（Sparkイベントリスナーバス経由の非同期配信）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（LiveListenerBus経由） |
| 優先度 | 高（アプリケーションライフサイクルイベント） |
| リトライ | 無 |

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

LiveListenerBusに登録されたすべてのSparkListenerInterface実装リスナーに対してブロードキャスト配信される。SparkListenerBus.doPostEventメソッドにおいて、SparkListenerApplicationStartイベントとパターンマッチし、listener.onApplicationStart()が呼び出される。

## 通知テンプレート

### メール通知の場合

該当なし。本通知はSparkの内部イベントバスを介したプログラマティック通知である。

### 本文テンプレート

```
イベント: SparkListenerApplicationStart
アプリケーション名: {appName}
アプリケーションID: {appId}
開始時刻: {time}
ユーザー: {sparkUser}
試行ID: {appAttemptId}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| appName | アプリケーション名 | SparkConf ("spark.app.name") | Yes |
| appId | アプリケーションID | クラスタマネージャから取得（Option[String]） | Yes（Some） |
| time | アプリケーション開始時刻（ミリ秒） | SparkContext.startTime | Yes |
| sparkUser | Spark実行ユーザー名 | Utils.getCurrentUserName() | Yes |
| appAttemptId | アプリケーション試行ID | クラスタマネージャから取得（Option[String]） | No |
| driverLogs | ドライバログURL | schedulerBackend.getDriverLogUrls | No |
| driverAttributes | ドライバ属性 | schedulerBackend.getDriverAttributes | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| アプリケーション初期化 | SparkContext初期化完了 | 常時（SparkContext生成時に必ず発火） | postApplicationStart()メソッド内で発火 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 特になし | SparkContextが正常に初期化される限り、必ず発火する |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[SparkContext初期化] --> B[タスクスケジューラ初期化]
    B --> C[クラスタマネージャからアプリケーションID取得]
    C --> D[SparkContext.postApplicationStart]
    D --> E[listenerBus.post SparkListenerApplicationStart]
    E --> F[SparkListenerBus.doPostEvent]
    F --> G[listener.onApplicationStart]
    G --> H[AppStatusListener: KVStore書き込み]
    G --> I[EventLoggingListener: イベントログ記録]
```

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

### 参照テーブル一覧

該当なし。

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| AppStatusStore (KVStore) | INSERT | AppStatusListenerがApplicationInfoWrapper、ApplicationAttemptInfoを書き込み |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| appId未定義 | appIdがNoneの場合 | AppStatusListenerでassert(event.appId.isDefined)によりアサーションエラー |
| リスナー例外 | リスナーのonApplicationStart実装で例外発生 | ListenerBusが例外をキャッチしログ出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | N/A（アプリケーション起動時に1回のみ発火） |
| 1日あたり上限 | N/A |

### 配信時間帯

制限なし。アプリケーション起動時に1回のみ発火する。

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

本通知にはアプリケーション名、ユーザー名、アプリケーションIDが含まれる。ユーザー名は実行環境のユーザー情報であり、イベントログへの書き込み時にはファイルシステムのアクセス制御に依存する。driverAttributesにはドライバ固有の属性情報が含まれる可能性があり、内容に応じてセキュリティ上の考慮が必要。

## 備考

- AppStatusListenerではappIdが定義されていることをassertで確認している（行118）。
- EventLoggingListenerではflushLogger=trueで即座にフラッシュされる。
- FsHistoryProviderのAppListingListenerでは本イベントからアプリケーション名、開始時刻、Sparkバージョンなどを取得する。
- JsonProtocolでのJSON直列化では"App Name"、"App ID"、"Timestamp"、"User"等のキー名が使用される。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SparkListener.scala | `core/src/main/scala/org/apache/spark/scheduler/SparkListener.scala` | 行273-280: SparkListenerApplicationStartケースクラスの定義。7フィールド |

**読解のコツ**: driverLogsとdriverAttributesはOption[Map[String, String]]型であり、クラスタマネージャの実装に依存する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SparkContext.scala | `core/src/main/scala/org/apache/spark/SparkContext.scala` | 行2936-2941: postApplicationStartメソッド。applicationId、startTime、sparkUser、driverLogUrls、driverAttributesを使用 |

**主要処理フロー**:
1. **行2936**: postApplicationStart()メソッド定義
2. **行2937-2938**: コメント - タスクスケジューラが初期化されアプリケーションIDが取得済みであることを前提とする
3. **行2939-2941**: listenerBus.post(SparkListenerApplicationStart(...))

#### Step 3: リスナー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AppStatusListener.scala | `core/src/main/scala/org/apache/spark/status/AppStatusListener.scala` | 行117-152: onApplicationStartの実装。ApplicationAttemptInfo生成、KVStore書き込み |
| 3-2 | EventLoggingListener.scala | `core/src/main/scala/org/apache/spark/scheduler/EventLoggingListener.scala` | 行178-180: onApplicationStartの実装。flushLogger=trueでログ記録 |

#### Step 4: JSON直列化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | JsonProtocol.scala | `core/src/main/scala/org/apache/spark/util/JsonProtocol.scala` | 行302-315: applicationStartToJsonメソッド。各フィールドのJSON変換 |
| 4-2 | JsonProtocol.scala | `core/src/main/scala/org/apache/spark/util/JsonProtocol.scala` | 行1124-1133: applicationStartFromJsonメソッド。JSONからオブジェクトへの逆変換 |

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

```
SparkContext (初期化完了)
    |
    +-- postApplicationStart()
           |
           +-- listenerBus.post(SparkListenerApplicationStart)
                  |
                  +-- SparkListenerBus.doPostEvent
                         |
                         +-- AppStatusListener.onApplicationStart
                         |      |
                         |      +-- KVStore書き込み (ApplicationInfoWrapper)
                         |
                         +-- EventLoggingListener.onApplicationStart
                         |      |
                         |      +-- logEvent (flushLogger=true)
                         |
                         +-- FsHistoryProvider.AppListingListener.onApplicationStart
```

### データフロー図

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

SparkContext初期化 -----------> postApplicationStart() ----------> SparkListenerApplicationStart
(appName, applicationId,           |                                    |
 startTime, sparkUser,             v                                    v
 appAttemptId,               LiveListenerBus                     AppStatusStore (KVStore)
 driverLogUrls,                    |                              イベントログ (JSON)
 driverAttributes)                 v                              履歴サーバ一覧
                             リスナーへ配信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SparkListener.scala | `core/src/main/scala/org/apache/spark/scheduler/SparkListener.scala` | ソース | イベントケースクラス定義 |
| SparkListenerBus.scala | `core/src/main/scala/org/apache/spark/scheduler/SparkListenerBus.scala` | ソース | イベント配信ディスパッチ |
| SparkContext.scala | `core/src/main/scala/org/apache/spark/SparkContext.scala` | ソース | イベント発火元（postApplicationStart） |
| AppStatusListener.scala | `core/src/main/scala/org/apache/spark/status/AppStatusListener.scala` | ソース | アプリケーション情報のKVStore書き込み |
| EventLoggingListener.scala | `core/src/main/scala/org/apache/spark/scheduler/EventLoggingListener.scala` | ソース | イベントログ永続化 |
| FsHistoryProvider.scala | `core/src/main/scala/org/apache/spark/deploy/history/FsHistoryProvider.scala` | ソース | 履歴サーバのアプリケーション一覧管理 |
| JsonProtocol.scala | `core/src/main/scala/org/apache/spark/util/JsonProtocol.scala` | ソース | JSON直列化・逆直列化 |
