# 通知設計書 5-TracingChannel

## 概要

本ドキュメントは、Node.jsのdiagnostics_channelモジュールにおけるTracingChannel機能の設計書である。

### 本通知の処理概要

TracingChannelは、トレーシング用の複合チャンネルを提供する機能である。start/end/asyncStart/asyncEnd/errorの5つのサブチャンネルで構成され、同期処理、Promise、コールバックベースの非同期処理を統一的にトレースできる。

**業務上の目的・背景**：分散システムやマイクロサービス環境において、リクエストの流れを追跡（トレーシング）することは、パフォーマンス分析やデバッグに不可欠である。TracingChannelは、Node.jsの様々な非同期パターンに対応した統一的なトレーシングインターフェースを提供し、APMツールやOpenTelemetryなどのオブザーバビリティツールとの連携を容易にする。

**通知の送信タイミング**：
- start: 処理開始時
- end: 同期処理完了時
- asyncStart: 非同期コールバック/Promise開始時
- asyncEnd: 非同期コールバック/Promise完了時
- error: エラー発生時

**通知の受信者**：TracingChannelに対してsubscribe()でハンドラを登録したコード。APMツール、トレーシングライブラリ、カスタム監視コードなどが想定される。

**通知内容の概要**：コンテキストオブジェクト（result、error等を含む）が各サブチャンネルに送信される。

**期待されるアクション**：購読者は受信したコンテキストを使用して、トレーススパンの作成、メトリクス収集、ログ出力などを行う。

## 通知種別

内部イベント通知（トレーシングPub/Sub機構）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（パフォーマンスクリティカル） |
| リトライ | なし（同期実行のため） |

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

TracingChannelオブジェクトのsubscribe()メソッドで登録したハンドラオブジェクトに送信される。ハンドラオブジェクトは各イベント（start/end/asyncStart/asyncEnd/error）に対応するコールバック関数を持つ。

## 通知テンプレート

### TracingChannel API

| 項目 | 内容 |
|-----|------|
| チャンネル作成 | `dc.tracingChannel('name')` または `dc.tracingChannel(channelsObj)` |
| 購読登録 | `tracingChannel.subscribe(handlers)` |
| 購読解除 | `tracingChannel.unsubscribe(handlers)` |
| 同期トレース | `tracingChannel.traceSync(fn, context, thisArg, ...args)` |
| Promiseトレース | `tracingChannel.tracePromise(fn, context, thisArg, ...args)` |
| コールバックトレース | `tracingChannel.traceCallback(fn, position, context, thisArg, ...args)` |
| 購読者有無確認 | `tracingChannel.hasSubscribers` |

### サブチャンネル構成

| サブチャンネル | タイミング | 説明 |
|--------------|---------|------|
| start | 処理開始時 | 関数実行前に発火 |
| end | 同期完了時 | 同期関数の実行後に発火 |
| asyncStart | 非同期開始時 | コールバック/Promise解決時に発火 |
| asyncEnd | 非同期完了時 | コールバック/Promise処理完了後に発火 |
| error | エラー発生時 | 例外またはエラーコールバック時に発火 |

### データ構造

```javascript
// コンテキストオブジェクト
{
  // 処理開始時に設定可能な任意のプロパティ
  // traceSync/tracePromise/traceCallbackで渡される
}

// 処理完了後に追加されるプロパティ
{
  result: any,  // 成功時の戻り値
  error: Error  // エラー発生時のエラーオブジェクト
}
```

### 添付ファイル

該当なし（プログラム内部通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| context | コンテキストオブジェクト | traceSync/tracePromise/traceCallbackの引数 | No（デフォルト: {}） |
| result | 処理の戻り値 | 関数の戻り値 | No |
| error | エラーオブジェクト | 例外/エラーコールバック | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| traceSync | 同期関数実行 | hasSubscribers == true | start→(関数実行)→end/errorの順で発火 |
| tracePromise | Promise返却関数実行 | hasSubscribers == true | start→end→asyncStart→asyncEndの順で発火 |
| traceCallback | コールバック関数実行 | hasSubscribers == true | start→end→asyncStart→asyncEndの順で発火 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 購読者なし | hasSubscribersがfalseの場合、トレースをスキップして直接関数を実行 |
| 特定イベントハンドラなし | handlersオブジェクトに該当イベントのハンドラがない場合はスキップ |

## 処理フロー

### traceSync送信フロー

```mermaid
flowchart TD
    A[traceSync呼び出し] --> B{hasSubscribers?}
    B -->|No| C[直接fn実行]
    B -->|Yes| D[start.runStores発火]
    D --> E[fn実行]
    E --> F{エラー発生?}
    F -->|Yes| G[context.error設定]
    G --> H[error.publish発火]
    H --> I[end.publish発火]
    F -->|No| J[context.result設定]
    J --> I
    I --> K[結果返却]
    C --> K
```

### tracePromise送信フロー

```mermaid
flowchart TD
    A[tracePromise呼び出し] --> B{hasSubscribers?}
    B -->|No| C[直接fn実行]
    B -->|Yes| D[start.runStores発火]
    D --> E[fn実行]
    E --> F[end.publish発火]
    F --> G{Promise結果}
    G -->|resolve| H[context.result設定]
    H --> I[asyncStart.publish発火]
    I --> J[asyncEnd.publish発火]
    G -->|reject| K[context.error設定]
    K --> L[error.publish発火]
    L --> M[asyncStart.publish発火]
    M --> N[asyncEnd.publish発火]
    C --> O[結果返却]
    J --> O
    N --> O
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | メモリ内データ構造のみ使用 |

### 内部データ構造

| 構造名 | 用途 | 説明 |
|--------|------|------|
| traceEvents | イベント名リスト | ['start', 'end', 'asyncStart', 'asyncEnd', 'error'] |
| this.start/end/... | サブチャンネル | 各イベント用のChannelインスタンス |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | データベース更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 関数内エラー | traceSync/tracePromise/traceCallback内で例外発生 | context.errorに設定してerrorチャンネルに通知後、再スロー |
| Promiseリジェクト | tracePromiseでPromiseがreject | context.errorに設定してerrorチャンネルに通知、PromiseReject返却 |
| コールバックエラー | traceCallbackでエラー引数が渡される | context.errorに設定してerrorチャンネルに通知 |
| 無効なチャンネル | tracingChannelFromに無効な引数 | ERR_INVALID_ARG_TYPE例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | なし |
| リトライ対象エラー | なし（同期処理のため） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（制限なし） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（プログラム実行中は常時利用可能）

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

- コンテキストオブジェクトには機密情報が含まれる可能性があるため、購読者は適切にデータを取り扱う必要がある
- トレーシングはパフォーマンスオーバーヘッドを伴うため、本番環境では必要な場合のみ有効化すべき
- 購読者のコールバックでエラーが発生した場合もトレース対象関数は継続して実行される

## 備考

- TracingChannelはdiagnostics_channelの高レベルAPIとして提供される
- チャンネル名を文字列で指定した場合、自動的に`tracing:{name}:{event}`形式のチャンネルが作成される
- AsyncLocalStorageとの連携により、コンテキストの自動伝播が可能（runStores経由）
- hasSubscribersはいずれかのサブチャンネルに購読者がいればtrueを返す

---

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

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

### 推奨読解順序

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

まず、TracingChannelの構成要素を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 253-259行目：traceEventsの定義、サブチャンネル名のリスト |

**読解のコツ**: 5つのイベント（start/end/asyncStart/asyncEnd/error）がTracingChannelの基本構成であることを把握する。

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

TracingChannelの作成方法を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 433-435行目：tracingChannel()関数 |
| 2-2 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 267-281行目：tracingChannelFrom()関数 |

**主要処理フロー**:
1. **433-435行目**: tracingChannel()でTracingChannelインスタンスを作成
2. **267-281行目**: 文字列またはオブジェクトからサブチャンネルを取得

#### Step 3: TracingChannelクラスを理解する

TracingChannelの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 283-431行目：TracingChannelクラス |

**主要処理フロー**:
- **284-291行目**: コンストラクタ、サブチャンネルの初期化
- **293-300行目**: hasSubscribersプロパティ
- **302-309行目**: subscribe()メソッド
- **311-324行目**: unsubscribe()メソッド

#### Step 4: トレースメソッドを理解する

各トレースメソッドの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 326-346行目：traceSync()メソッド |
| 4-2 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 348-388行目：tracePromise()メソッド |
| 4-3 | diagnostics_channel.js | `lib/diagnostics_channel.js` | 390-430行目：traceCallback()メソッド |

**主要処理フロー（traceSync）**:
1. **327-329行目**: hasSubscribersチェック、なければ直接実行
2. **331行目**: start/end/errorチャンネルの取得
3. **333-345行目**: start.runStores内で関数実行、結果/エラーを設定してend/errorを発火

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

```
dc.tracingChannel('name')
    │
    └─ tracingChannel() [433行目]
           │
           └─ new TracingChannel(nameOrChannels) [434行目]
                  │
                  └─ tracingChannelFrom() [267行目]
                         └─ channel('tracing:name:event')

tracingChannel.traceSync(fn, context, thisArg, ...args)
    │
    └─ TracingChannel.traceSync() [326行目]
           │
           ├─ hasSubscribers check [327行目]
           │
           └─ start.runStores(context, ...) [333行目]
                  │
                  ├─ start.publish(context)
                  ├─ fn.apply(thisArg, args)
                  ├─ [エラー時] error.publish(context)
                  └─ end.publish(context)
```

### データフロー図

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

traceSync/Promise/Callback
    │                 TracingChannel                各サブチャンネル購読者
    │                      │                            │
    ▼                      ▼                            ▼
context ──────────▶ start.runStores ──────────▶ start handler
    │                      │                            │
    │                      ▼                            ▼
    │               関数実行(fn)                   end handler
    │                      │                            │
    │                      ▼                            ▼
    │              [result/error]              asyncStart handler
    │                      │                            │
    │                      ▼                            ▼
    └──────────▶ context更新 ──────────────▶ asyncEnd/error handler
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| diagnostics_channel.js | `lib/diagnostics_channel.js` | ソース | TracingChannelクラスの実装 |
