# 通知設計書 12-コンソールログ通知

## 概要

本ドキュメントは、Bun DevServerにおけるコンソールログ通知の設計を記載する。ブラウザからのconsole.log/console.errorをサーバー側に転送する機能である。

### 本通知の処理概要

コンソールログ通知は、クライアントサイド（ブラウザ）で発生したconsole.logやconsole.errorの出力を、DevServerを経由してサーバー側のターミナルに転送する機能である。

**業務上の目的・背景**：フロントエンド開発時、ブラウザのコンソール出力をサーバー側でも確認したいケースがある。特にSSR（Server-Side Rendering）環境では、クライアントとサーバー両方のログを一元管理することで、デバッグ効率が大幅に向上する。また、WebKit Inspector統合によるリモートデバッグをサポートする。

**通知の送信タイミング**：クライアント側のHMRランタイムがconsole.log/console.errorをインターセプトし、WebSocket経由でDevServerに`console_log`メッセージとして送信する。このメッセージを受信した時点でサーバー側に出力される。

**通知の受信者**：DevServerプロセスが受信し、2つの経路で処理される。(1) Inspectorエージェントを通じてデバッガフロントエンドに転送、(2) `broadcast_console_log_from_browser_to_server`オプションが有効な場合、サーバーのターミナルに直接出力。

**通知内容の概要**：ログの種類（log/error）とログメッセージ本文を含む。シンプルなテキストベースのメッセージとして転送される。

**期待されるアクション**：開発者はサーバーのターミナルでブラウザのコンソール出力を確認できる。デバッグ時にブラウザとターミナルを行き来する必要がなくなり、開発効率が向上する。

## 通知種別

アプリ内通知（WebSocket経由でのサーバー転送 + ターミナル出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 低 |
| リトライ | なし |

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

1. Inspectorエージェント: 常に通知（有効な場合）
2. ターミナル出力: `broadcast_console_log_from_browser_to_server`オプションがtrueの場合のみ

## 通知テンプレート

### WebSocket通知の場合

| 項目 | 内容 |
|-----|------|
| プロトコル | WebSocket (Binary) |
| メッセージID | `console_log` |
| フォーマット | 1バイト目: メッセージID、2バイト目: 種類('l'=log, 'e'=error)、3バイト目以降: メッセージ本文 |

### ターミナル出力フォーマット

```
[browser] {メッセージ内容}
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| kind | ログ種別（log/err） | メッセージの2バイト目 | Yes |
| data | ログメッセージ本文 | メッセージの3バイト目以降 | Yes |
| devServerId | DevServer識別子 | DevServer.inspector_server_id | Yes（Inspector通知時） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| WebSocketメッセージ | `console_log`受信 | メッセージ長が2バイト以上 | クライアントからのコンソールログ転送 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| メッセージ長不足 | メッセージが2バイト未満の場合、WebSocketを閉じる |
| 不正な種別 | 2バイト目が'l'でも'e'でもない場合、WebSocketを閉じる |
| オプション無効 | `broadcast_console_log_from_browser_to_server`がfalseの場合、ターミナル出力をスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[HmrSocket: console_logメッセージ受信] --> B{メッセージ長 >= 2?}
    B -->|No| C[WebSocketを閉じる]
    B -->|Yes| D{種別チェック: l or e?}
    D -->|その他| C
    D -->|l| E[kind = log]
    D -->|e| F[kind = err]
    E --> G[データ抽出: msg 3バイト目以降]
    F --> G
    G --> H{Inspectorエージェント有効?}
    H -->|Yes| I[notifyConsoleLog呼び出し]
    H -->|No| J{broadcast_console_log有効?}
    I --> J
    J -->|Yes| K{kind == log?}
    J -->|No| L[処理終了]
    K -->|Yes| M[Output.pretty: [browser] メッセージ]
    K -->|No| N[Output.prettyError: [browser] メッセージ]
    M --> O[Output.flush]
    N --> O
    O --> L
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。DevServer設定とランタイム状態から情報を取得する。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| DevServer.broadcast_console_log_from_browser_to_server | 機能有効フラグ | bool型 |
| DevServer.inspector_server_id | DevServer識別 | DebuggerId型 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| メッセージ短すぎ | msg.len < 2 | WebSocketを閉じる |
| 不正なログ種別 | msg[1] != 'l' かつ msg[1] != 'e' | WebSocketを閉じる |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

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

### 配信時間帯

開発サーバー稼働中は常時受信可能

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

- ローカル開発環境での使用を想定しており、本番環境では無効化推奨
- 機密情報がログに含まれる可能性があるため、ログ内容の取り扱いに注意
- WebSocket接続はローカルホストからのみを推奨

## 備考

- HMRランタイムクライアント（hmr-runtime-client.ts）でconsole.log/console.errorをオーバーライドして実装
- デフォルトでは`broadcast_console_log_from_browser_to_server`はOptions経由で設定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DevServer.zig | `src/bake/DevServer.zig` | ConsoleLogKind列挙型、broadcast_console_log_from_browser_to_serverフィールド |
| 1-2 | HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | IncomingMessageIdのconsole_log定義 |

**読解のコツ**: DevServer.Options構造体で設定オプションの流れを追うと、機能の有効/無効の制御が理解できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | onMessageメソッドでconsole_logケースの処理 |

**主要処理フロー**:
1. **172-206行目**: `console_log`メッセージ受信時の全体処理
2. **178-185行目**: ログ種別の判定
3. **189-193行目**: Inspectorへの通知
4. **195-205行目**: ターミナル出力

#### Step 3: Inspector連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InspectorBunFrontendDevServerAgent.zig | `src/bun.js/api/server/InspectorBunFrontendDevServerAgent.zig` | notifyConsoleLogメソッド（101-105行目） |

**主要処理フロー**:
- **101-105行目**: Zig側からC++関数を呼び出してInspectorに通知

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

```
HmrSocket.onMessage()
    │
    ├─ IncomingMessageId.console_log ケース
    │      │
    │      ├─ メッセージ長・種別チェック
    │      │      └─ 不正な場合: ws.close()
    │      │
    │      ├─ ConsoleLogKind判定 (log/err)
    │      │
    │      ├─ dev.inspector() [Optional]
    │      │      └─ agent.notifyConsoleLog()
    │      │             └─ InspectorBunFrontendDevServerAgent__notifyConsoleLog (C++)
    │      │
    │      └─ dev.broadcast_console_log_from_browser_to_server [条件分岐]
    │             ├─ kind == .log
    │             │      └─ Output.pretty("[browser] {data}")
    │             │
    │             └─ kind == .err
    │                    └─ Output.prettyError("[browser] {data}")
    │
    └─ Output.flush()
```

### データフロー図

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

ブラウザ                 HmrSocket                    2つの出力先
console.log() ───▶ WebSocket ───▶ onMessage() ───▶ ┬─▶ Inspector (DevTools)
console.error()    console_log      │               │
                   メッセージ       │               └─▶ ターミナル [browser]
                                    │
                                    ├─ 種別判定 (l/e)
                                    └─ オプションチェック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | ソース | WebSocketメッセージ処理、console_logハンドリング |
| DevServer.zig | `src/bake/DevServer.zig` | ソース | DevServer設定、ConsoleLogKind定義 |
| InspectorBunFrontendDevServerAgent.zig | `src/bun.js/api/server/InspectorBunFrontendDevServerAgent.zig` | ソース | notifyConsoleLog実装 |
| hmr-runtime-client.ts | `src/bake/hmr-runtime-client.ts` | ソース | クライアント側でのconsole.*オーバーライド |
| ServerConfig.zig | `src/bun.js/api/server/ServerConfig.zig` | ソース | broadcast_console_log_from_browser_to_server設定 |
