# 機能設計書 55-StressLogAnalyzer

## 概要

本ドキュメントは、.NETランタイムにおけるStressLogAnalyzer（ストレスログ解析ツール）の機能設計を記述する。StressLogAnalyzerは、.NETランタイム（CoreCLR）のストレスログをメモリマップドファイルから読み取り、フィルタリング・解析・表示するツールである。

### 本機能の処理概要

StressLogAnalyzerは、ランタイムが生成したストレスログ（デバッグ・診断用の内部ログ）をメモリマップドファイルから読み込み、指定された条件でフィルタリングして表示する機能である。

**業務上の目的・背景**：.NETランタイム開発者がGC（ガベージコレクション）やその他のランタイム動作を診断・デバッグする際に、ストレスログは重要な情報源となる。本ツールは、大量のログメッセージから関心のある情報を効率的に抽出することを目的とする。

**機能の利用シーン**：
- GC動作の詳細解析
- ランタイム内部の処理フロー追跡
- パフォーマンス問題の診断
- ランタイムバグの調査

**主要な処理内容**：
1. メモリマップドファイルからストレスログヘッダの読み取り
2. スレッドごとのストレスログの列挙
3. 時間範囲、値、スレッド等によるフィルタリング
4. GCスレッドの識別とマッピング
5. メッセージのフォーマットと出力

**関連システム・外部連携**：
- Microsoft.Diagnostics.DataContractReader（データコントラクト読み取り）
- System.CommandLine（コマンドライン解析）
- メモリマップドファイルAPI

**権限による制御**：ストレスログファイルの読み取り権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | StressLogAnalyzerはCLIツールのため、直接的なUI関連はない |

## 機能種別

開発・診断ツール / ログ解析

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| log file | FileInfo | Yes | メモリマップドストレスログファイル | 存在する有効なログ |
| -output, -o | FileInfo | No | 出力ファイルパス | 書き込み可能 |
| -values, -v | hex range[] | No | 検索する16進値または範囲 | 有効な16進数 |
| --time, -t | time range | No | 時間範囲フィルタ | 有効な時間形式 |
| --all, -a | bool | No | 全メッセージを出力 | - |
| --level, -l | int range | No | dprintレベルフィルタ | 有効なレベル |
| --gc, -g | int range | No | GCインデックスフィルタ | 有効なGC番号 |
| --threads, -tid | thread[] | No | スレッドフィルタ | 有効なスレッドID |
| --format, -f | string[] | No | フォーマット文字列フィルタ | - |
| --prefix, -p | string[] | No | フォーマット文字列プレフィックス | - |

### 入力データソース

- メモリマップドストレスログファイル（.NETランタイムが生成）

### ストレスログファイル構造

```
StressLogHeader
├─ magic: "LRTS"
├─ version: 0x00010001 or 0x00010002
├─ memoryBase: ログデータの開始アドレス
├─ memoryLimit: ログデータの終了アドレス
├─ memoryCur: 現在の書き込み位置
├─ logs: スレッドログへのポインタ
├─ moduleTable: モジュール情報テーブル
└─ tickFrequency: タイムスタンプ周波数
```

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| messages | text | フィルタリングされたログメッセージ |
| summary | text | 処理サマリー（件数、サイズ等） |

### 出力形式例

```
  2.345678s GC12: GC#5 starting
  2.345680s GC12: heap 0 mark phase
  ...
Number of messages processed: 1.234567 million, printed: 12.345 thousand
```

## 処理フロー

### 処理シーケンス

```
1. コマンドライン解析
   └─ System.CommandLineでオプション解析
   └─ Optionsオブジェクト構築

2. ストレスログオープン
   └─ MemoryMappedFile.CreateFromFile()
   └─ StressLogHeader検証

3. データコントラクトターゲット作成
   └─ ContractDescriptorTarget.Create()
   └─ IStressLogコントラクト取得

4. フィルタ構築
   └─ メッセージフィルタチェーン構築
   └─ 時間範囲フィルタ設定

5. 並列ログ解析
   └─ Parallel.ForEachAsyncでスレッドログを並列処理
   └─ 各スレッドのメッセージを時系列で走査
   └─ フィルタ条件でメッセージをフィルタリング

6. 結果出力
   └─ フィルタ通過メッセージの出力
   └─ サマリー情報の出力
```

### フローチャート

```mermaid
flowchart TD
    A[ログファイル入力] --> B[MemoryMappedFile.CreateFromFile]
    B --> C[StressLogHeader検証]
    C --> D{ヘッダ有効?}
    D -->|No| E[エラー終了]
    D -->|Yes| F[DataContractTarget作成]
    F --> G[フィルタ構築]
    G --> H[Parallel.ForEachAsync]
    H --> I[スレッドログ走査]
    I --> J{フィルタ通過?}
    J -->|Yes| K[メッセージ収集]
    J -->|No| L[スキップ]
    K --> M{次のメッセージ?}
    L --> M
    M -->|Yes| I
    M -->|No| N[結果出力]
    N --> O[サマリー出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-1 | ヘッダ検証 | magicが"LRTS"でない場合は無効 | 常時 |
| BR-55-2 | バージョン確認 | サポートバージョンは0x00010001/0x00010002 | 常時 |
| BR-55-3 | 時間フィルタ | 負の値は「最後のN秒」を意味 | --time指定時 |
| BR-55-4 | GCスレッド識別 | GCスレッドは"GCn"形式で表示 | デフォルト |

### フィルタ優先順位

フィルタは以下の順序で適用される：
1. 時間範囲フィルタ（TimeTracker）
2. スレッドフィルタ（ThreadFilter）
3. 値フィルタ（ValueFilter）
4. レベルフィルタ（DPrintLevelFilter）
5. フォーマット文字列フィルタ（InterestingMessageFilter）

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

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

StressLogAnalyzerはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 無効なログファイル | ヘッダが無効 | 正しいログファイルを指定 |
| 1 | サイズ不足 | ファイルサイズがヘッダ未満 | 完全なログファイルを指定 |

### インタラクティブモード

デフォルトでは解析後に対話プロンプトを表示：
- `q`: 終了
- `r[args]`: 新しいオプションで再実行

`--single-run`オプションで単一実行モードに設定可能。

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

StressLogAnalyzerはトランザクション処理を行わない。読み取り専用の操作のみ。

## パフォーマンス要件

- 並列処理によりマルチコアCPUを活用
- 数GBのログファイルでも効率的に処理可能
- メモリマップドファイルにより大規模ログをサポート

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

- ストレスログには内部アドレス情報が含まれる可能性
- 本番環境のログには機密情報が含まれる可能性

## 備考

StressLogAnalyzerは.NETランタイム開発者向けの内部ツールである。ストレスログはランタイムのCOMPLUS_StressLog環境変数で有効化される。

---

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

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

### 推奨読解順序

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

まず、ストレスログのデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | StressLogHeader.cs | `src/tools/StressLogAnalyzer/src/StressLogHeader.cs` | ログヘッダ構造体 |
| 1-2 | Options.cs | `src/tools/StressLogAnalyzer/src/Options.cs` | コマンドラインオプション |
| 1-3 | IntegerRange.cs | `src/tools/StressLogAnalyzer/src/Filters/IntegerRange.cs` | 範囲フィルタ型 |

**読解のコツ**: StressLogHeaderはunsafe構造体で定義されており、メモリレイアウトに注意が必要。

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

処理の開始点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Program.cs | `src/tools/StressLogAnalyzer/src/Program.cs` | メイン処理、CLI定義 |

**主要処理フロー**:
- **57-88行目**: Main()でコマンドライン解析と対話ループ
- **100-343行目**: CreateRootCommand()でCLIオプション定義
- **345-404行目**: AnalyzeStressLog()でログ解析実行
- **475-501行目**: CreateTarget()でデータコントラクトターゲット作成

#### Step 3: ログ解析処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | StressLogAnalyzer.cs | `src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs` | ログ解析コア処理 |

**主要処理フロー**:
- **20-25行目**: StressLogAnalyzerクラスのコンストラクタパラメータ
- **27行目**: AnalyzeLogsAsync()が解析のメインメソッド
- **55-100行目以降**: Parallel.ForEachAsyncで並列処理

#### Step 4: フィルタリングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | IMessageFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/IMessageFilter.cs` | フィルタインターフェース |
| 4-2 | ValueFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/ValueFilter.cs` | 値フィルタ |
| 4-3 | TimeTracker.cs | `src/tools/StressLogAnalyzer/src/TimeTracker.cs` | 時間追跡 |

**主要処理フロー**:
- **446-473行目(Program.cs)**: CreateMessageFilter()でフィルタチェーン構築

#### Step 5: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | IStressMessageOutput.cs | `src/tools/StressLogAnalyzer/src/Output/IStressMessageOutput.cs` | 出力インターフェース |
| 5-2 | StressMessageWriter.cs | `src/tools/StressLogAnalyzer/src/Output/StressMessageWriter.cs` | メッセージ書き込み |

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

```
Program.Main()
    │
    ├─ CreateRootCommand()
    │      └─ RootCommand定義（オプション、引数）
    │
    └─ InvokeAsync()
           │
           └─ AnalyzeStressLog()
                  │
                  ├─ MemoryMappedFile.CreateFromFile()
                  │
                  ├─ CreateTarget()
                  │      └─ ContractDescriptorTarget.Create()
                  │
                  ├─ CreateMessageFilter()
                  │      ├─ AllMessagesFilter
                  │      ├─ ValueFilter
                  │      ├─ DPrintLevelFilter
                  │      └─ InterestingMessageFilter
                  │
                  └─ StressLogAnalyzer.AnalyzeLogsAsync()
                         │
                         ├─ Parallel.ForEachAsync(logs)
                         │      │
                         │      └─ GetStressMessages()
                         │             └─ messageFilter.IncludeMessage()
                         │
                         └─ StressMessageWriter.WriteMessage()
```

### データフロー図

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

ログファイル         ───▶ MemoryMappedFile       ───▶ StressLogHeader
                          (メモリマップ)

StressLogHeader      ───▶ CreateTarget           ───▶ IStressLog
                          (コントラクト作成)

IStressLog           ───▶ GetThreadStressLogs    ───▶ ThreadStressLogData[]
                          (スレッドログ取得)

ThreadStressLogData  ───▶ GetStressMessages      ───▶ StressMsgData
                          (メッセージ取得)

StressMsgData        ───▶ MessageFilter          ───▶ フィルタ済みメッセージ
                          (フィルタリング)

フィルタ済み         ───▶ StressMessageWriter    ───▶ コンソール/ファイル
メッセージ                 (出力)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Program.cs | `src/tools/StressLogAnalyzer/src/Program.cs` | ソース | メインエントリ、CLI定義 |
| StressLogAnalyzer.cs | `src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs` | ソース | ログ解析コア |
| Options.cs | `src/tools/StressLogAnalyzer/src/Options.cs` | ソース | オプション定義 |
| StressLogHeader.cs | `src/tools/StressLogAnalyzer/src/StressLogHeader.cs` | ソース | ヘッダ構造体 |
| TimeTracker.cs | `src/tools/StressLogAnalyzer/src/TimeTracker.cs` | ソース | 時間追跡 |
| GCThreadMap.cs | `src/tools/StressLogAnalyzer/src/GCThreadMap.cs` | ソース | GCスレッドマッピング |
| IMessageFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/IMessageFilter.cs` | ソース | フィルタインターフェース |
| AllMessagesFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/AllMessagesFilter.cs` | ソース | 全メッセージフィルタ |
| ValueFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/ValueFilter.cs` | ソース | 値フィルタ |
| DPrintLevelFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/DPrintLevelFilter.cs` | ソース | レベルフィルタ |
| ThreadFilter.cs | `src/tools/StressLogAnalyzer/src/Filters/ThreadFilter.cs` | ソース | スレッドフィルタ |
| IntegerRange.cs | `src/tools/StressLogAnalyzer/src/Filters/IntegerRange.cs` | ソース | 整数範囲型 |
| TimeRange.cs | `src/tools/StressLogAnalyzer/src/Filters/TimeRange.cs` | ソース | 時間範囲型 |
| IStressMessageOutput.cs | `src/tools/StressLogAnalyzer/src/Output/IStressMessageOutput.cs` | ソース | 出力インターフェース |
| StressMessageWriter.cs | `src/tools/StressLogAnalyzer/src/Output/StressMessageWriter.cs` | ソース | メッセージ書き込み |
| InterestingStringFinder.cs | `src/tools/StressLogAnalyzer/src/InterestingStringFinder.cs` | ソース | 重要文字列検索 |
