# バッチ設計書 13-Telemetry.TelemetryReporter

## 概要

本ドキュメントは、Jenkins における Telemetry.TelemetryReporter バッチの設計書である。このバッチは AsyncPeriodicWork を継承し、匿名の利用統計データを収集して Jenkins プロジェクトに送信する。ユーザーが明示的に有効化した場合のみ動作する。

### 本バッチの処理概要

Telemetry.TelemetryReporter は JEP-214 で定義されたテレメトリフレームワークの一部として、Jenkins の利用状況データを収集・送信するバッチ処理である。プライバシーに配慮し、匿名化されたデータのみを収集する。

**業務上の目的・背景**：Jenkins プロジェクトでは、ユーザーの利用状況を把握することで、開発リソースの優先順位付けや機能改善の判断材料を得ている。例えば、どのプラグインが多く使われているか、どの機能に問題が発生しやすいかなどを統計的に分析する。このデータ収集はオプトイン方式であり、ユーザーの明示的な同意がなければ送信されない。

**バッチの実行タイミング**：24時間ごとに実行。ただし、テレメトリ収集が無効化されている場合は、処理を即座にスキップする。

**主要な処理内容**：
1. テレメトリ収集の有効/無効を確認
2. 登録されているすべての Telemetry 拡張ポイントを走査
3. 各テレメトリコレクターの有効期間（開始日〜終了日）を確認
4. 有効期間内のコレクターから createContent() でデータを収集
5. 収集したデータを JSON 形式でラップし、相関 ID を付加
6. HTTPS POST リクエストで Jenkins テレメトリエンドポイントに送信

**前後の処理との関連**：このバッチは独立して動作する。収集されたデータは Jenkins プロジェクトのサーバーで集約・分析されるが、Jenkins インスタンス側での後続処理はない。

**影響範囲**：ネットワーク通信を伴うため、ファイアウォール設定やプロキシ設定の影響を受ける。送信先は uplink.jenkins.io であり、この通信が遮断されていても Jenkins の動作自体には影響しない。

## バッチ種別

テレメトリ収集 / データ送信

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次（24時間間隔） |
| 実行時刻 | 不定（起動時刻からの相対） |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | AsyncPeriodicWork（内部タイマー） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Jenkins起動済み | Jenkins インスタンスが起動し、AsyncPeriodicWork スケジューラが動作していること |
| テレメトリ有効 | UsageStatistics.DISABLED が false で、かつ jenkins.isUsageStatisticsCollected() が true であること |
| ネットワーク接続 | uplink.jenkins.io への HTTPS 通信が可能であること |

### 実行可否判定

execute() メソッド開始時に Telemetry.isDisabled() をチェックし、無効の場合は即座に return する。個々のテレメトリコレクターについても、開始日・終了日による有効期間チェックを行う。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| ENDPOINT | String | No | https://uplink.jenkins.io/events | テレメトリ送信先 URL（システムプロパティで変更可能） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Telemetry.all() | Java オブジェクト | 登録されている全テレメトリコレクターのリスト |
| Correlator | Java オブジェクト | インスタンス識別用の相関 ID を提供 |
| Jenkins.getVersion() | VersionNumber | Jenkins コアのバージョン |
| PluginManager.getPlugins() | List<PluginWrapper> | インストール済みプラグインのリスト |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| uplink.jenkins.io | HTTPS POST (JSON) | テレメトリデータの送信 |
| ログファイル | テキスト | 処理結果のログ出力 |

### 出力ファイル仕様

バッチ自体はローカルファイル出力を行わない。HTTP レスポンスのステータスコードをログに記録する。

| 項目 | 内容 |
|-----|------|
| 送信形式 | application/json; charset=utf-8 |
| エンドポイント | https://uplink.jenkins.io/events |

### JSON 送信フォーマット

```json
{
  "type": "{テレメトリID}",
  "payload": { /* テレメトリコレクターが生成したデータ */ },
  "correlator": "{SHA256ハッシュ化された相関ID}"
}
```

## 処理フロー

### 処理シーケンス

```
1. execute() メソッド開始
   └─ TelemetryReporter が AsyncPeriodicWork により呼び出される
2. 有効性チェック
   └─ Telemetry.isDisabled() で収集可否を確認
3. 無効時の処理
   └─ INFO ログを出力して即座に return
4. 全テレメトリコレクターの走査
   └─ Telemetry.all().forEach() で各コレクターを処理
5. 有効期間チェック（開始日）
   └─ getStart().isAfter(LocalDate.now()) なら スキップ
6. 有効期間チェック（終了日）
   └─ getEnd().isBefore(LocalDate.now()) ならスキップ
7. データ収集
   └─ telemetry.createContent() を呼び出し
8. 空データチェック
   └─ 戻り値が null なら スキップ
9. JSON ラッピング
   └─ type, payload, correlator を含む JSONObject 生成
10. HTTP リクエスト送信
    └─ HttpClient.send() で POST リクエスト
11. レスポンス処理
    └─ ステータスコードをログに記録
```

### フローチャート

```mermaid
flowchart TD
    A[TelemetryReporter.execute 開始] --> B{isDisabled?}
    B -->|Yes| C[INFO ログ出力して終了]
    B -->|No| D[Telemetry.all で全コレクター取得]
    D --> E{次のコレクターあり?}
    E -->|No| Z[処理終了]
    E -->|Yes| F{開始日 > 今日?}
    F -->|Yes| G[CONFIG ログ: 開始前]
    G --> E
    F -->|No| H{終了日 < 今日?}
    H -->|Yes| I[CONFIG ログ: 終了済み]
    I --> E
    H -->|No| J[createContent 呼び出し]
    J --> K{例外発生?}
    K -->|Yes| L[WARNING ログ]
    L --> E
    K -->|No| M{data == null?}
    M -->|Yes| N[CONFIG ログ: データなし]
    N --> E
    M -->|No| O[JSON ラップ処理]
    O --> P[correlator 生成・追加]
    P --> Q[HTTP POST 送信]
    Q --> R{送信成功?}
    R -->|Yes| S[CONFIG ログ: レスポンスコード]
    R -->|No| T[CONFIG ログ: 送信失敗]
    S --> E
    T --> E
```

## データベース操作仕様

### 操作別データベース影響一覧

このバッチはデータベース操作を行わない。Jenkins の内部データ構造をメモリ上で参照するのみ。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RuntimeException | createContent() での例外発生 | WARNING ログを出力し、該当コレクターをスキップ |
| - | IOException | HTTP 送信失敗 | CONFIG ログを出力し、該当コレクターをスキップ |
| - | InterruptedException | HTTP 送信中の割り込み | CONFIG ログを出力し、該当コレクターをスキップ |
| - | URISyntaxException | エンドポイント URL 不正 | CONFIG ログを出力し、該当コレクターをスキップ |

### リトライ仕様

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

リトライは行わない。次回の定期実行（24時間後）で再度処理される。一時的なインフラ障害は許容する設計。

### 障害時対応

1. ネットワーク接続エラー: プロキシ設定（ProxyConfiguration）を確認
2. 継続的な送信失敗: ファイアウォールで uplink.jenkins.io への HTTPS 通信が許可されているか確認
3. createContent() のエラー: 該当するテレメトリプラグインのバージョンを確認・更新

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | トランザクション管理なし |
| コミットタイミング | - |
| ロールバック条件 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数十のテレメトリコレクター |
| 目標処理時間 | 数分以内（ネットワーク依存） |
| メモリ使用量上限 | 最小限（JSON シリアライズ分） |

## 排他制御

- AsyncPeriodicWork により単一スレッドで実行される
- 同時実行の競合はない
- HTTP 通信はブロッキングで順次実行

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| INFO | 無効時 | "Collection of anonymous usage statistics is disabled, skipping telemetry collection and submission" |
| CONFIG | 開始日前 | "Skipping telemetry for '{id}' as it is configured to start later" |
| CONFIG | 終了日後 | "Skipping telemetry for '{id}' as it is configured to end in the past" |
| WARNING | createContent 例外 | "Failed to build telemetry content for: '{id}'" |
| CONFIG | データなし | "Skipping telemetry for '{id}' as it has no data" |
| FINEST | JSON 送信前 | "Submitting JSON: {body}" |
| CONFIG | 送信成功 | "Telemetry submission received response {statusCode} for: {id}" |
| CONFIG | 送信失敗 | "Failed to submit telemetry: {id} to: {endpoint}" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| なし | - | - |

テレメトリ送信の失敗は管理者への通知を行わない。これは意図的な設計で、一時的なインフラ問題でログが汚れることを防いでいる。

## 備考

- TelemetryReporter は @Extension アノテーションにより自動登録される
- JEP-214 に基づく実装であり、プライバシーに配慮した匿名データのみを収集
- 送信先エンドポイントはシステムプロパティ `jenkins.telemetry.Telemetry.endpoint` で変更可能（開発用）
- correlator は `SHA256(correlationId + telemetryId)` で計算され、異なるテレメトリタイプ間でのデータリンクを防止
- isAnyTrialActive() メソッドで現在アクティブなテレメトリ収集があるかを確認可能
- buildComponentInformation() で Jenkins コアおよび全プラグインのバージョン情報を取得可能
- ProxyConfiguration.newHttpClient() および newHttpRequestBuilder() でプロキシ設定を自動適用
