# 機能設計書 30-trace_events

## 概要

本ドキュメントは、Node.jsのtrace_eventsモジュールの機能設計について記述する。trace_eventsモジュールは、V8、Node.jsコア、ユーザー空間コードによって生成されたトレースイベントを一元的に収集するための機能を提供する。Chrome DevToolsのトレーシング機能（chrome://tracing）と互換性のある形式でイベントを出力する。

### 本機能の処理概要

**業務上の目的・背景**：trace_eventsモジュールは、アプリケーションのパフォーマンス分析とデバッグのためのトレーシング機能を提供する。V8エンジン、Node.jsコア、ユーザーコードの実行を時系列で記録し、Chrome DevToolsで可視化・分析できる。

**機能の利用シーン**：
- アプリケーションの実行トレースを取得する際
- 特定のカテゴリのイベントのみを収集する際
- パフォーマンスボトルネックを特定する際
- 非同期処理の実行順序を分析する際
- V8の最適化/脱最適化イベントを監視する際

**主要な処理内容**：
1. `createTracing(options)` - Tracingオブジェクトの作成
2. `tracing.enable()` - トレーシングの有効化
3. `tracing.disable()` - トレーシングの無効化
4. `tracing.enabled` - トレーシングの有効状態を取得
5. `tracing.categories` - 監視カテゴリを取得
6. `getEnabledCategories()` - 現在有効なカテゴリ文字列を取得

**関連システム・外部連携**：
- internalBinding('trace_events') - ネイティブトレースイベント機能
- internalBinding('config').hasTracing - トレーシング機能の有効性チェック
- Chrome DevTools（chrome://tracing）- トレースデータの可視化

**権限による制御**：メインスレッドでのみ使用可能。ワーカースレッドからは使用不可（ERR_TRACE_EVENTS_UNAVAILABLE）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | System Analyzer | 補助機能 | トレースイベントの可視化 |
| 4 | Turbolizer | 補助機能 | V8最適化トレースの分析 |

## 機能種別

トレーシング / パフォーマンス分析 / デバッグ支援

## 入力仕様

### 入力パラメータ

#### createTracing

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options | Object | Yes | オプションオブジェクト | validateObject |
| options.categories | string[] | Yes | トレースカテゴリの配列 | validateStringArray, 長さ > 0 |

### 利用可能なトレースカテゴリ

主なカテゴリ：
- `node` - Node.jsコアイベント
- `node.async_hooks` - async_hooksイベント
- `node.bootstrap` - 起動イベント
- `node.perf` - パフォーマンスイベント
- `node.console` - consoleイベント
- `v8` - V8エンジンイベント

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| createTracing()戻り値 | Tracing | Tracingオブジェクト |
| tracing.enabled | boolean | トレーシングの有効状態 |
| tracing.categories | string | カンマ区切りのカテゴリ文字列 |
| getEnabledCategories()戻り値 | string \| undefined | 有効なカテゴリ文字列、または無効時undefined |

### 出力先

- トレースデータはNode.jsプロセスの--trace-event-file-patternで指定されたファイルに出力
- デフォルト: node_trace.{rotation}.log（JSONフォーマット）

## 処理フロー

### 処理シーケンス

```
1. Tracingオブジェクト作成（createTracing）
   └─ CategorySetネイティブハンドル生成
   └─ カテゴリ配列を保存
2. トレーシング有効化（enable）
   └─ ネイティブhandle.enable()呼び出し
   └─ enabledTracingObjectsに追加
   └─ 10個超で警告
3. イベント発生
   └─ V8/Node.jsコア/ユーザーコードからイベント記録
4. トレーシング無効化（disable）
   └─ ネイティブhandle.disable()呼び出し
   └─ enabledTracingObjectsから削除
```

### フローチャート

```mermaid
flowchart TD
    A[createTracing] --> B[options検証]
    B --> C{categories.length > 0?}
    C -->|いいえ| D[ERR_TRACE_EVENTS_CATEGORY_REQUIRED]
    C -->|はい| E[CategorySetハンドル生成]
    E --> F[Tracingオブジェクト返却]

    G[tracing.enable] --> H{既に有効?}
    H -->|はい| I[何もしない]
    H -->|いいえ| J[handle.enable]
    J --> K[enabledTracingObjectsに追加]
    K --> L{10個超?}
    L -->|はい| M[メモリリーク警告]
    L -->|いいえ| N[完了]

    O[tracing.disable] --> P{有効?}
    P -->|いいえ| Q[何もしない]
    P -->|はい| R[handle.disable]
    R --> S[enabledTracingObjectsから削除]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | メインスレッド限定 | ワーカースレッドでは使用不可 | ownsProcessState = false |
| BR-002 | トレーシング機能必須 | hasTracing = falseで使用不可 | コンパイル時設定 |
| BR-003 | カテゴリ必須 | categories配列は空不可 | createTracing時 |
| BR-004 | メモリリーク警告 | 有効なTracingが10個超で警告 | enable時 |
| BR-005 | 冪等性 | enable/disableは複数回呼び出しても安全 | 状態チェック |

### 計算ロジック

特になし。

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

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_TRACE_EVENTS_UNAVAILABLE | Error | トレーシング機能が利用不可 | Node.jsをトレーシング有効でビルド |
| ERR_TRACE_EVENTS_UNAVAILABLE | Error | ワーカースレッドから呼び出し | メインスレッドから呼び出す |
| ERR_TRACE_EVENTS_CATEGORY_REQUIRED | TypeError | categories配列が空 | 少なくとも1つのカテゴリを指定 |
| ERR_INVALID_ARG_TYPE | TypeError | optionsがオブジェクトでない | オブジェクトを渡す |
| ERR_INVALID_ARG_TYPE | TypeError | categoriesが文字列配列でない | 文字列配列を渡す |

### リトライ仕様

リトライ処理は行わない。

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

トランザクション処理は行わない。

## パフォーマンス要件

- トレーシングはオーバーヘッドが発生するため、本番環境での常時有効化は非推奨
- 必要な期間のみenableすることを推奨
- enabledTracingObjectsの上限チェック（10個）

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

- トレースデータにはアプリケーションの内部動作情報が含まれる
- トレースファイルへのアクセス権限に注意

## 備考

- trace_events_async_hooksモジュールでasync_hooksベースのトレーシングを提供
- ChromeのDevToolsでトレースファイルを開くことで可視化可能
- --trace-event-categoriesコマンドラインオプションでも有効化可能
- --trace-event-file-patternでトレースファイルのパターンを指定可能

---

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

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

### 推奨読解順序

#### Step 1: モジュール初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | trace_events.js | `lib/trace_events.js` | モジュール初期化（8-19行目） |

**読解のコツ**: モジュールロード時にhasTracingとownsProcessStateをチェックし、どちらかがfalseの場合はERR_TRACE_EVENTS_UNAVAILABLEをスローする。これによりワーカースレッドやトレーシング無効ビルドでの使用を防止する。

**主要処理フロー**:
- **8行目**: internalBinding('config').hasTracingでトレーシング機能の有無を確認
- **17行目**: internal/workerからownsProcessStateを取得
- **18-19行目**: hasTracing && ownsProcessStateでなければエラー

#### Step 2: Tracingクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | trace_events.js | `lib/trace_events.js` | Tracingクラス（31-81行目） |

**主要処理フロー**:
- **32-34行目**: プライベートフィールド（#handle, #categories, #enabled）
- **36-39行目**: コンストラクタ - CategorySetネイティブハンドル生成
- **41-53行目**: enable() - 有効化、enabledTracingObjectsに追加、10個超警告
- **55-61行目**: disable() - 無効化、enabledTracingObjectsから削除
- **63-65行目**: enabledゲッター - 有効状態を返却
- **67-69行目**: categoriesゲッター - カンマ区切り文字列を返却
- **71-80行目**: customInspectSymbol - inspect用フォーマット

#### Step 3: createTracing関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | trace_events.js | `lib/trace_events.js` | createTracing関数（83-91行目） |

**主要処理フロー**:
- **84行目**: validateObjectでoptions検証
- **85行目**: validateStringArrayでoptions.categories検証
- **87-88行目**: categories.length <= 0でERR_TRACE_EVENTS_CATEGORY_REQUIRED
- **90行目**: new Tracing(options.categories)でインスタンス生成

#### Step 4: async_hooksベースのトレーシングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | trace_events_async_hooks.js | `lib/internal/trace_events_async_hooks.js` | createHook関数（38-97行目） |

**主要処理フロー**:
- **32行目**: nativeProviders - ネイティブで処理されるProviderを除外
- **36行目**: Promiseはネイティブではないため除外リストから削除
- **43-79行目**: async_hooks.createHookでinit/before/after/destroyフック作成
- **48-53行目**: init - kBeforeEventでトレース開始
- **56-61行目**: before - コールバック開始をトレース
- **63-68行目**: after - コールバック終了をトレース
- **70-78行目**: destroy - kEndEventでトレース終了、typeMemoryクリーンアップ
- **81-96行目**: enable/disable - hookの有効化/無効化

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

```
lib/trace_events.js
    │
    ├─ モジュール初期化 [8-19行目]
    │      ├─ internalBinding('config').hasTracing
    │      ├─ ownsProcessState (internal/worker)
    │      └─ ERR_TRACE_EVENTS_UNAVAILABLE
    │
    ├─ Tracing クラス [31-81行目]
    │      ├─ constructor(categories) [36-39行目]
    │      │      └─ new CategorySet(categories)
    │      │
    │      ├─ enable() [41-53行目]
    │      │      ├─ this.#handle.enable()
    │      │      ├─ enabledTracingObjects.add(this)
    │      │      └─ process.emitWarning (10個超)
    │      │
    │      ├─ disable() [55-61行目]
    │      │      ├─ this.#handle.disable()
    │      │      └─ enabledTracingObjects.delete(this)
    │      │
    │      ├─ get enabled [63-65行目]
    │      │
    │      └─ get categories [67-69行目]
    │             └─ ArrayPrototypeJoin
    │
    ├─ createTracing(options) [83-91行目]
    │      ├─ validateObject
    │      ├─ validateStringArray
    │      └─ new Tracing(options.categories)
    │
    └─ module.exports [93-96行目]
           ├─ createTracing
           └─ getEnabledCategories (internalBinding)

lib/internal/trace_events_async_hooks.js
    │
    └─ createHook() [38-97行目]
           ├─ async_hooks.createHook [43-79行目]
           │      ├─ init - trace(kBeforeEvent, ...)
           │      ├─ before - trace(kBeforeEvent, type_CALLBACK)
           │      ├─ after - trace(kEndEvent, type_CALLBACK)
           │      └─ destroy - trace(kEndEvent, ...)
           │
           └─ enable/disable [81-96行目]
                  └─ hook.enable/disable
```

### データフロー図

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

options.categories ───▶ createTracing ───▶ Tracing
                              │
                              └── new CategorySet(categories)

───▶ tracing.enable ───▶ handle.enable
           │
           ├── enabledTracingObjects.add
           └── 10個超警告

───▶ tracing.disable ───▶ handle.disable
           │
           └── enabledTracingObjects.delete

───▶ getEnabledCategories ───▶ string | undefined

[async_hooksベース]
asyncId, type ───▶ init hook ───▶ trace(kBeforeEvent, ...)
asyncId ───▶ before hook ───▶ trace(kBeforeEvent, type_CALLBACK)
asyncId ───▶ after hook ───▶ trace(kEndEvent, type_CALLBACK)
asyncId ───▶ destroy hook ───▶ trace(kEndEvent, ...)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| trace_events.js | `lib/trace_events.js` | ソース | モジュールエントリーポイント |
| trace_events_async_hooks.js | `lib/internal/trace_events_async_hooks.js` | ソース | async_hooksベースのトレーシング |
| errors.js | `lib/internal/errors.js` | ソース | ERR_TRACE_EVENTS_* エラー定義 |
| worker.js | `lib/internal/worker.js` | ソース | ownsProcessState |
| validators.js | `lib/internal/validators.js` | ソース | validateObject, validateStringArray |
| util.js | `lib/internal/util.js` | ソース | customInspectSymbol |
| inspect.js | `lib/internal/util/inspect.js` | ソース | format関数 |
