# 帳票設計書 5-ビルドコンソールログ

## 概要

本ドキュメントは、Jenkins CI/CDサーバーにおけるビルドコンソールログ機能の帳票設計書である。ビルド実行時のコンソール出力を保存・表示し、アノテーションによるリンク化やハイライトを提供する機能について記述する。

### 本帳票の処理概要

この帳票は、Jenkinsのビルド実行時に発生するコンソール出力（標準出力・標準エラー出力）を保存し、WebUI上で閲覧可能な形式で表示する。出力テキストには `ConsoleNote` によるアノテーション（ハイパーリンク、色分け、折りたたみ等）を埋め込むことができ、`AnnotatedLargeText` クラスによりHTML形式でレンダリングされる。

**業務上の目的・背景**：CI/CDパイプラインにおいて、ビルドやテストの実行結果を詳細に確認することは、問題の診断と解決に不可欠である。単なるテキスト出力ではなく、エラーメッセージのハイライト、ファイルパスへのリンク、セクションの折りたたみなど、リッチな表示機能を提供することで、開発者の問題解決を効率化する。

**帳票の利用シーン**：開発者がビルド結果を確認する際、特にビルド失敗時の原因調査、テスト実行ログの確認、デプロイ処理の進捗監視など、あらゆるビルド関連の情報確認に利用される。

**主要な出力内容**：
1. ビルド実行中のリアルタイム出力（Progressive HTML/Text）
2. ビルド完了後の完全なコンソールログ
3. ConsoleNoteによるアノテーション付きHTML出力
4. プレーンテキスト形式の出力（ダウンロード用）

**帳票の出力タイミング**：ビルド実行中はリアルタイムで更新され、ビルド完了後は静的なログとして保存される。ユーザーがコンソールページにアクセスした際に表示される。

**帳票の利用者**：開発者、QAエンジニア、DevOpsエンジニア、プロジェクトマネージャー

## 帳票種別

ビルドレポート（テキスト/HTML表示）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | コンソール出力画面 | `/job/{jobName}/{buildNumber}/console` | ページアクセス時に自動表示 |
| - | Progressive HTML | `/job/{jobName}/{buildNumber}/logText/progressiveHtml` | Ajax polling |
| - | Progressive Text | `/job/{jobName}/{buildNumber}/logText/progressiveText` | Ajax polling |
| - | プレーンテキストダウンロード | `/job/{jobName}/{buildNumber}/consoleText` | ダウンロード操作 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTML / プレーンテキスト |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | log（ビルドディレクトリ内）/ log.gz（圧縮時） |
| 出力方法 | WebUI表示 / テキストダウンロード |
| 文字コード | UTF-8（デフォルト）、ビルド設定による |

### HTML表示設定

| 項目 | 内容 |
|-----|------|
| Content-Type | text/html;charset=UTF-8（HTML）/ text/plain;charset=UTF-8（Text） |
| アノテーション | ConsoleNote によるマークアップ |
| ハイパーリンク | HyperlinkNote によるURL/ファイルパスのリンク化 |
| 折りたたみ | ExpandableDetailsNote によるセクション折りたたみ |

## 帳票レイアウト

### レイアウト概要

コンソール出力は pre/code 要素内に表示され、アノテーションによりリッチなHTML装飾が適用される。

```
┌──────────────────────────────────────────────────────┐
│ Console Output                                       │
├──────────────────────────────────────────────────────┤
│ Started by user admin                               │
│ Building in workspace /var/lib/jenkins/workspace/... │
│ [Pipeline] Start of Pipeline                        │
│ [Pipeline] node                                     │
│ ▼ Running on agent-1                                │ ← 折りたたみ可能
│   [Pipeline] {                                      │
│   ...                                               │
│ ▼ ERROR: Build failed                              │ ← エラーハイライト
│ Finished: FAILURE                                   │
└──────────────────────────────────────────────────────┘
```

### ヘッダー部

なし（ビルドページのコンテンツとして表示）

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | コンソール出力 | ビルドの標準出力/標準エラー | Run.getLogText() | テキスト（アノテーション付き） | 100% |

### フッター部

なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| start | 読み込み開始位置（バイトオフセット） | No（デフォルト: 0） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 出力順序 | 時系列（出力された順） |

### 改ページ条件

なし（スクロール表示）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照せず、ファイルシステム上のログファイルからデータを取得する。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| log ファイル | コンソール出力の保存 | ビルドディレクトリ内 |
| log.gz | 圧縮されたログ | 容量削減のため |
| AnnotatedLargeText | アノテーション付きテキスト処理 | LargeText の拡張 |

### テーブル別参照項目詳細

#### ログファイル

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| ファイル内容 | コンソール出力 | Run.getLogFile() | 非圧縮または圧縮 |
| ファイルサイズ | 読み込み範囲計算 | - | Progressive読み込みに使用 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 読み込み位置 | クライアントから受信したオフセット | - | X-Text-Size ヘッダで返却 |
| 完了状態 | !isLogUpdated() | - | X-More-Data ヘッダで返却 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コンソールページアクセス] --> B[AnnotatedLargeText取得]
    B --> C{Progressive HTML?}
    C -->|Yes| D[doProgressiveHtml]
    C -->|No| E[全体読み込み]
    D --> F[ConsoleAnnotator作成]
    F --> G[writeHtmlTo]
    G --> H[ConsoleAnnotationOutputStream]
    H --> I[ConsoleNote解釈]
    I --> J[HTMLマークアップ生成]
    J --> K[レスポンス返却]
    E --> L[writeLogTo]
    L --> K
```

### ConsoleNote処理フロー

```mermaid
flowchart TD
    A[ログ行読み込み] --> B{ConsoleNote検出?}
    B -->|Yes| C[PREAMBLE/POSTAMBLE間を抽出]
    C --> D[Base64デコード]
    D --> E[GZIP展開]
    E --> F[オブジェクトデシリアライズ]
    F --> G[MAC検証]
    G -->|OK| H[annotate メソッド呼び出し]
    G -->|NG| I[ConsoleNote無視]
    B -->|No| J[プレーンテキスト出力]
    H --> K[MarkupText変換]
    K --> L[HTML出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ログファイルなし | ビルドが開始されていない | 空の出力 | - |
| 署名検証失敗 | 不正なConsoleNote | ログメッセージを出力、Noteを無視 | - |
| デシリアライズ失敗 | 古い形式のConsoleNote | Noteを無視 | - |
| 1時間以上前のAnnotator | リプレイ攻撃防止 | Annotatorをリセット | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ビルドあたり数KB〜数百MB |
| 目標出力時間 | Progressive: 100ms以内、全体: サイズ依存 |
| 同時出力数上限 | 特に制限なし |
| キャッシュ | ConsoleAnnotatorの状態をHTTPヘッダで管理 |

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

- ConsoleNote は暗号化・署名されており、悪意のあるコンテンツの注入を防止
- MAC（メッセージ認証コード）により ConsoleNote の改ざんを検出
- 1時間以上前のタイムスタンプを持つ Annotator は拒否（リプレイ攻撃対策）
- INSECURE フラグで署名チェックを無効化可能（非推奨、テスト用）
- PREAMBLE/POSTAMBLE には ANSI エスケープシーケンスを使用し、端末での直接表示時にゴミを最小化

## 備考

- log ファイルはビルドの isLogUpdated() が false になった後、自動的に gzip 圧縮される場合がある
- HyperlinkNote、ExpandableDetailsNote、MavenErrorNote など、様々な ConsoleNote 実装が存在
- プラグインは ConsoleNote を拡張してカスタムアノテーションを追加可能
- ConsoleNote は Jenkins マスターで生成する必要がある（エージェント上での生成は署名なし）

---

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

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

### 推奨読解順序

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

まず、コンソールログの基本データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AnnotatedLargeText.java | `core/src/main/java/hudson/console/AnnotatedLargeText.java` | LargeTextの拡張、アノテーション処理 |
| 1-2 | ConsoleNote.java | `core/src/main/java/hudson/console/ConsoleNote.java` | アノテーションの基本クラス |

**読解のコツ**: `AnnotatedLargeText` は `LargeText` を継承し、コンソール出力にアノテーション機能を追加している。`ConsoleNote` は出力に埋め込まれる機械可読な情報を表現する。

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

ログ取得の起点を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Run.java | `core/src/main/java/hudson/model/Run.java` | `getLogText()` メソッド（行1513-1515） |
| 2-2 | AnnotatedLargeText.java | `core/src/main/java/hudson/console/AnnotatedLargeText.java` | `doProgressiveHtml()` メソッド（行105-111） |

**主要処理フロー**:
1. **Run.java 行1513-1515**: `getLogText()` で `AnnotatedLargeText` を生成
2. **行87-89**: コンストラクタでファイル、文字セット、完了状態、コンテキストを設定
3. **行105-111**: `doProgressiveHtml()` でHTML形式の出力を開始

#### Step 3: HTML出力ロジックを理解する

アノテーション付きHTMLの生成処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AnnotatedLargeText.java | `core/src/main/java/hudson/console/AnnotatedLargeText.java` | `writeHtmlTo()` メソッド（行243-263） |
| 3-2 | ConsoleAnnotationOutputStream.java | `core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java` | ストリーム処理 |

**主要処理フロー**:
- **行243-263**: `writeHtmlTo()` がメイン処理
- **行244-247**: `ConsoleAnnotationOutputStream` を作成、`ConsoleAnnotator` を渡す
- **行248**: `super.writeLogTo()` でログを書き出し
- **行250-261**: Annotator の状態を暗号化してHTTPヘッダに設定

#### Step 4: ConsoleNote の処理を理解する

アノテーションの埋め込みと解釈。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ConsoleNote.java | `core/src/main/java/hudson/console/ConsoleNote.java` | `encode()` / `readFrom()` メソッド |

**主要処理フロー**:
- **行182-198**: `encodeTo()` でConsoleNoteをエンコードしてストリームに書き込み
- **行201-222**: `encodeToBytes()` でGZIP圧縮、Base64エンコード、MAC付加
- **行240-292**: `readFrom()` でデコード、MAC検証、デシリアライズ
- **行325-338**: `PREAMBLE` / `POSTAMBLE` 定数（ANSIエスケープシーケンス）

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

```
コンソールページアクセス
    │
    └─ Run.getLogText()
           │
           └─ new AnnotatedLargeText(file, charset, completed, this)
                  │
                  └─ doProgressiveHtml(req, rsp)
                         │
                         └─ writeHtmlTo(start, writer)
                                │
                                ├─ createAnnotator(req)
                                │      └─ ConsoleAnnotator.initial() or デシリアライズ
                                │
                                ├─ new ConsoleAnnotationOutputStream(writer, annotator, context, charset)
                                │
                                └─ super.writeLogTo(start, caw)
                                       │
                                       └─ [各行の処理]
                                              │
                                              ├─ ConsoleNote.readFrom() [Noteがある場合]
                                              │      └─ note.annotate()
                                              │
                                              └─ annotator.annotate() [各行に対して]
```

### データフロー図

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

ビルド実行
    │
    ▼
標準出力/標準エラー ──────▶ ConsoleNote.encodeTo()
    │                              │
    │                              ▼
    │                     PREAMBLE + Base64(GZIP(MAC + data)) + POSTAMBLE
    │                              │
    └─────────────────────────────▶ log ファイル

HTTPリクエスト
    /progressiveHtml
    X-ConsoleAnnotator ────────▶ AnnotatedLargeText.doProgressiveHtml()
                                       │
                                       ▼
                               createAnnotator(req)
                                       │
                                       ▼
                               writeHtmlTo(start, writer)
                                       │
                                       ▼
                               ConsoleAnnotationOutputStream
                                       │
                                       ▼
                               ConsoleNote.readFrom() ◀─── log ファイル
                                       │
                                       ▼
                               note.annotate(context, text, pos)
                                       │
                                       ▼
                               HTMLマークアップ ─────────▶ HTTPレスポンス
                                       │                  Content-Type: text/html
                               暗号化Annotator ────────▶ X-ConsoleAnnotator ヘッダ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AnnotatedLargeText.java | `core/src/main/java/hudson/console/AnnotatedLargeText.java` | ソース | アノテーション付きテキストの基底クラス |
| ConsoleNote.java | `core/src/main/java/hudson/console/ConsoleNote.java` | ソース | アノテーションの基底クラス、エンコード/デコード |
| ConsoleAnnotator.java | `core/src/main/java/hudson/console/ConsoleAnnotator.java` | ソース | 行単位のアノテーション処理 |
| ConsoleAnnotatorFactory.java | `core/src/main/java/hudson/console/ConsoleAnnotatorFactory.java` | ソース | ConsoleAnnotatorのファクトリ |
| ConsoleAnnotationOutputStream.java | `core/src/main/java/hudson/console/ConsoleAnnotationOutputStream.java` | ソース | アノテーション処理ストリーム |
| PlainTextConsoleOutputStream.java | `core/src/main/java/hudson/console/PlainTextConsoleOutputStream.java` | ソース | ConsoleNoteを除去するストリーム |
| HyperlinkNote.java | `core/src/main/java/hudson/console/HyperlinkNote.java` | ソース | ハイパーリンクアノテーション |
| ExpandableDetailsNote.java | `core/src/main/java/hudson/console/ExpandableDetailsNote.java` | ソース | 折りたたみアノテーション |
| Run.java | `core/src/main/java/hudson/model/Run.java` | ソース | getLogText()、ログファイル管理 |
| LargeText.java | (Stapler) | 外部 | 大きなテキストファイルの処理基盤 |
