# 機能設計書 101-デバッグ・ログ

## 概要

本ドキュメントは、Next.jsの開発時デバッグ・ログ機能の設計を記述する。DEBUG環境変数によるデバッグログ出力、開発サーバーのリクエストログ、Server Actionログ、fetchメトリクスログの仕組みを対象とする。

### 本機能の処理概要

Next.jsの開発モードにおいて、リクエストの処理状況やfetchの実行結果、Server Actionの呼び出し情報を開発者向けにコンソールへ出力する機能である。

**業務上の目的・背景**：開発者がアプリケーションの動作をリアルタイムで把握し、問題の特定を迅速に行えるようにするために必要な機能である。リクエストのレスポンスタイム、キャッシュ状態、Server Actionの実行内容を可視化することで、パフォーマンス問題やデータフローの問題を素早く発見できる。

**機能の利用シーン**：`next dev`コマンドで開発サーバーを起動した際に自動的に有効化される。`DEBUG=next:*`環境変数を設定することで、より詳細なデバッグ情報が出力される。`next.config.js`の`logging`設定によりfetchログの表示制御が可能である。

**主要な処理内容**：
1. 受信リクエストのメソッド、URL、ステータスコード、所要時間をカラー表示付きでコンソールに出力
2. fetchメトリクスのログ出力（URL、ステータス、キャッシュヒット/ミス状態、所要時間）
3. Server Actionの関数名、引数、実行時間、ソースコード位置のログ出力
4. コンパイル時間、ミドルウェア処理時間、レンダリング時間の内訳表示
5. 特定のリクエストパターンをログ対象外にするフィルタリング機能

**関連システム・外部連携**：開発サーバー（next-dev-server）、Router Server、ミドルウェアエンジンと連携する。

**権限による制御**：開発モード（`next dev`）でのみ有効。`next.config.js`の`logging`設定および環境変数`NEXT_TELEMETRY_DEBUG`で制御可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ターミナル/コンソール | 主出力先 | ログの出力先としてstdoutに書き込み |

## 機能種別

ログ出力 / デバッグ支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| request | NodeNextRequest | Yes | 受信リクエストオブジェクト | - |
| response | NodeNextResponse | Yes | レスポンスオブジェクト | - |
| loggingConfig | LoggingConfig | Yes | ログ設定（next.config.jsのlogging項目） | - |
| requestStartTime | bigint | Yes | リクエスト受信時刻（hrtime） | - |
| requestEndTime | bigint | Yes | リクエスト完了時刻（hrtime） | - |
| devRequestTimingMiddlewareStart | bigint \| undefined | No | ミドルウェア開始時刻 | - |
| devRequestTimingMiddlewareEnd | bigint \| undefined | No | ミドルウェア終了時刻 | - |
| devRequestTimingInternalsEnd | bigint \| undefined | No | 内部処理完了時刻 | - |
| devGenerateStaticParamsDuration | bigint \| undefined | No | 静的パラメータ生成所要時間 | - |

### 入力データソース

- NodeNextRequestオブジェクト（HTTPリクエスト情報）
- NodeNextResponseオブジェクト（HTTPレスポンス情報）
- `next.config.js`の`logging`設定
- リクエストメタデータ（`getRequestMeta`経由で取得）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| リクエストログ | string | `METHOD URL STATUS in Xms (compile: Xms, render: Xms)` 形式 |
| Server Actionログ | string | `└─ f functionName(args) in Xms location` 形式 |
| fetchメトリクスログ | string | `METHOD URL STATUS in Xms (cache hit/miss/skip)` 形式 |
| キャッシュ理由 | string | `Cache skipped/missed reason: (reason)` 形式 |
| キャッシュ警告 | string | 黄色太字の警告アイコン付きメッセージ |

### 出力先

- `process.stdout`（標準出力）

## 処理フロー

### 処理シーケンス

```
1. logRequests関数が呼び出される
   └─ リクエスト完了後にRouter Serverから呼び出される
2. ignoreLoggingIncomingRequestsでフィルタリング判定
   └─ loggingConfig.incomingRequests設定およびignoreパターンをチェック
3. logIncomingRequestsでリクエスト情報をログ出力
   └─ ステータスコードに応じた色分け、各処理フェーズの時間内訳を計算
4. Server Actionログの出力判定・出力
   └─ リクエストメタデータからdevServerActionLogを取得し、存在すればログ出力
5. fetchメトリクス配列をループしてlogFetchMetricを呼び出し
   └─ キャッシュ状態、URLの切り詰め、キャッシュ理由の表示を行う
```

### フローチャート

```mermaid
flowchart TD
    A[logRequests呼び出し] --> B{ignoreLoggingIncomingRequests?}
    B -->|無視しない| C[logIncomingRequests]
    B -->|無視する| E{fetchMetrics?}
    C --> D{Server Actionログあり?}
    D -->|Yes| D1[Server Actionログ出力]
    D -->|No| E
    D1 --> E
    E -->|あり| F[fetchMetricsループ]
    E -->|なし| G[終了]
    F --> H[logFetchMetric]
    H --> I{HMRキャッシュ かつ hmrRefreshes無効?}
    I -->|Yes| J[スキップ]
    I -->|No| K{fetches設定あり?}
    K -->|Yes| L[fetch詳細ログ出力]
    K -->|No| M{cacheWarningあり?}
    M -->|Yes| N[警告ログ出力]
    M -->|No| G
    L --> G
    N --> G
    J --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-101 | ステータスコード色分け | 1xx:白, 2xx:緑, 3xx:青, 4xx:黄, 5xx:赤 | すべてのリクエストログ |
| BR-102 | URL切り詰め | 48文字超のURLはprotocol(16)+pathname(24)+search(16)に切り詰め | fetches.fullUrlがfalseの場合 |
| BR-103 | HMRキャッシュ非表示 | HMRリフレッシュ時のキャッシュヒットはデフォルトで非表示 | fetches.hmrRefreshesがfalseの場合 |
| BR-104 | RSCリクエスト正規化 | RSCリクエストのURLからRSC用クエリパラメータを除去して表示 | isRSCRequestがtrueの場合 |
| BR-105 | 無視パターン | loggingConfig.incomingRequests.ignoreの正規表現に一致するURLはログ出力しない | ignoreパターンが設定されている場合 |

### 計算ロジック

- 総リクエスト時間: `requestEndTime - requestStartTime`
- ミドルウェア時間: `devRequestTimingMiddlewareEnd - devRequestTimingMiddlewareStart`
- コンパイル時間: `devRequestTimingInternalsEnd - requestStartTime - middlewareTime`
- レンダリング時間: `requestEndTime - devRequestTimingInternalsEnd`

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

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

該当なし。本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | URLパースエラー | 不正なURL文字列がfetchメトリクスに含まれる場合 | try-catchで捕捉し、truncateUrl内でエラー発生時は元のURLをそのまま使用 |
| - | Server Action引数シリアライズエラー | 引数がシリアライズ不可能な場合 | `[unserializable]`文字列に置換 |

### リトライ仕様

リトライは不要。ログ出力の失敗はアプリケーション動作に影響しない。

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

該当なし。

## パフォーマンス要件

- ログ出力処理はリクエスト処理のクリティカルパスの外で実行される
- `safe-stable-stringify`を使用し、Server Action引数のシリアライズ深度を2、幅を3に制限することでパフォーマンスを確保

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

- 開発モード（`next dev`）でのみ有効であり、本番環境では動作しない
- Server Action引数の表示は深度制限・幅制限により過度な情報露出を防止
- fetchメトリクスのURL表示は切り詰め可能で、機密情報を含むURLの完全表示を回避できる

## 備考

- `NEXT_TELEMETRY_DEBUG`環境変数が設定されている場合、テレメトリデバッグログも標準エラー出力に表示される
- `picocolors`ライブラリを使用してターミナル上の色付け表示を実現している

---

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

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

### 推奨読解順序

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

リクエストログおよびServer Actionログで使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | base-http.ts | `packages/next/src/server/base-http.ts` | FetchMetric型（url, method, status, cacheStatus, cacheReason, start, end等）の定義 |
| 1-2 | server-action-logger.ts | `packages/next/src/server/dev/server-action-logger.ts` | ServerActionLogInfo型（functionName, args, location）の定義 |
| 1-3 | config-shared.ts | `packages/next/src/server/config-shared.ts` | LoggingConfig型（incomingRequests, fetches設定）の定義 |

**読解のコツ**: FetchMetricの`cacheStatus`は`'hmr' | 'hit' | 'miss' | 'skip'`の4値のunion型であり、`satisfies never`パターンでswitch文の網羅性を保証している。

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

ログ出力の起点となる`logRequests`関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | log-requests.ts | `packages/next/src/server/dev/log-requests.ts` | logRequests関数がすべてのログ出力のエントリーポイント |

**主要処理フロー**:
1. **54行目**: `ignoreLoggingIncomingRequests`でフィルタリング判定
2. **55-64行目**: `logIncomingRequests`でリクエスト情報をログ出力
3. **67-74行目**: Server Actionログの取得と出力（`getRequestMeta`経由）
4. **77-81行目**: fetchメトリクス配列のイテレーションと各fetchのログ出力

#### Step 3: リクエストログ出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | log-requests.ts | `packages/next/src/server/dev/log-requests.ts` | logIncomingRequests関数（84-143行目） |

**主要処理フロー**:
- **94-95行目**: RSCリクエストの判定とURL正規化
- **97-106行目**: ステータスコードに応じた色選択ロジック
- **110行目**: 総リクエスト時間の算出
- **112-138行目**: 各処理フェーズ（compile, middleware, generate-params, render）の時間計算
- **140-142行目**: 最終的なログ行の組み立てとstdout書き込み

#### Step 4: fetchメトリクスログ出力を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | log-requests.ts | `packages/next/src/server/dev/log-requests.ts` | logFetchMetric関数（145-195行目） |

**主要処理フロー**:
- **160-164行目**: HMRキャッシュの非表示判定
- **166-185行目**: fetches設定がある場合の詳細ログ出力
- **186-190行目**: fetches設定がない場合でもcacheWarningがあれば出力

#### Step 5: Server Action引数フォーマットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | server-action-logger.ts | `packages/next/src/server/dev/server-action-logger.ts` | formatArgs関数とformatArg関数 |

**主要処理フロー**:
- **4-7行目**: `safe-stable-stringify`の設定（maximumDepth: 2, maximumBreadth: 3）
- **12-25行目**: 引数のシリアライズとエラーハンドリング（`[unserializable]`フォールバック）

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

```
Router Server（リクエスト処理完了時）
    │
    ├─ logRequests()
    │      ├─ ignoreLoggingIncomingRequests()
    │      ├─ logIncomingRequests()
    │      │      ├─ getRequestMeta() [isRSCRequest判定]
    │      │      ├─ stripNextRscUnionQuery()
    │      │      ├─ hrtimeBigIntDurationToString()
    │      │      └─ writeLine()
    │      ├─ getRequestMeta() [devServerActionLog取得]
    │      ├─ formatArgs()
    │      │      └─ formatArg()
    │      │             └─ stringify() [safe-stable-stringify]
    │      └─ logFetchMetric()
    │             ├─ truncateUrl()
    │             │      └─ truncate()
    │             ├─ formatCacheStatus()
    │             └─ writeLine()
    │
    └─ removeRequestMeta() [ログ出力後のクリーンアップ]
```

### データフロー図

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

NodeNextRequest ──────────────> logRequests() ─────────────────> process.stdout
  ├─ url, method                  ├─ リクエスト情報整形            (カラー付きログ)
  ├─ fetchMetrics[]               ├─ 時間計算
  └─ requestMeta                  ├─ 色分け適用
       ├─ isRSCRequest            └─ インデント付き出力
       └─ devServerActionLog

LoggingConfig ────────────────> ignoreLoggingIncomingRequests() ─> boolean (フィルタ結果)
  ├─ incomingRequests
  │    └─ ignore: RegExp[]
  └─ fetches
       ├─ fullUrl
       └─ hmrRefreshes
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| log-requests.ts | `packages/next/src/server/dev/log-requests.ts` | ソース | リクエストログ・fetchログの出力メイン処理 |
| server-action-logger.ts | `packages/next/src/server/dev/server-action-logger.ts` | ソース | Server Action引数のフォーマット処理 |
| config-shared.ts | `packages/next/src/server/config-shared.ts` | ソース | LoggingConfig型定義 |
| base-http.ts | `packages/next/src/server/base-http.ts` | ソース | FetchMetric型定義 |
| request-meta.ts | `packages/next/src/server/request-meta.ts` | ソース | リクエストメタデータの取得・設定ユーティリティ |
| picocolors.ts | `packages/next/src/lib/picocolors.ts` | ソース | ターミナル色付けライブラリ |
| url.ts | `packages/next/src/lib/url.ts` | ソース | stripNextRscUnionQuery関数（RSCクエリパラメータ除去） |
| duration-to-string.ts | `packages/next/src/build/duration-to-string.ts` | ソース | hrtime BigInt値を人間可読な文字列に変換 |
