# 通知設計書 28-ブラウザパフォーマンスマーク

## 概要

本ドキュメントは、Tailwind CSSのブラウザ環境向けパッケージ（`@tailwindcss/browser`）において、`performance.mark()`および`performance.measure()`を使用してCSS生成処理の各フェーズの開始・終了・エラーをブラウザのPerformance APIに記録する通知の設計を定義する。

### 本通知の処理概要

ブラウザ環境でのTailwind CSS実行時に、`Instrumentation`クラスの`start`、`end`、`hit`、`error`メソッドを通じて、処理の各フェーズ（コンパイル、スキャン、CSS生成など）のタイミング情報をブラウザのPerformance APIに記録する通知処理である。

**業務上の目的・背景**：Tailwind CSSはブラウザ環境でも動作可能であり（`@tailwindcss/browser`パッケージ）、Tailwind PlayやSvelteなどのブラウザベースの開発環境で使用される。開発者やフレームワーク開発者がCSS生成のパフォーマンスボトルネックを特定するために、標準的なPerformance APIを通じてタイミング情報を収集できるようにすることが本通知の目的である。ブラウザのDevToolsのPerformanceタブやPerformance Observerを通じてこれらの情報を取得できる。

**通知の送信タイミング**：`start(label)`でイベント開始時、`end(label)`でイベント終了時、`hit(label)`で単発イベント発生時、`error(error)`でエラー発生時にそれぞれ`performance.mark()`または`performance.measure()`が呼び出される。

**通知の受信者**：ブラウザのPerformance API経由で、DevToolsのPerformanceタブ、Performance Observer API、サードパーティのモニタリングツールが受信可能。直接的には開発者やフレームワーク開発者が対象。

**通知内容の概要**：`start`で`"{label} (start)"`マーク、`end`で`"{label} (end)"`マーク+`performance.measure`による経過時間計測、`hit`で`"{label}"`マーク（detail付き）、`error`で`"(error)"`マーク（エラー詳細付き）が記録される。

**期待されるアクション**：開発者はDevToolsのPerformanceタブでタイミング情報を確認し、ボトルネックを特定する。Performance Observerを使用してプログラム的に情報を収集し、パフォーマンスメトリクスとして報告することも可能。

## 通知種別

ブラウザPerformance API（`performance.mark` / `performance.measure`）。コンソールには直接出力されない。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Performance API呼び出し） |
| 優先度 | 低（パフォーマンス計測用であり処理の成否には影響しない） |
| リトライ | 無 |

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

全てのメソッド呼び出しが無条件にPerformance APIに記録される。呼び出し元の判断で記録の有無が決定される（例：PostCSSプラグインのDEBUGモード時など）。

## 通知テンプレート

### メール通知の場合

本通知はメール送信ではなく、ブラウザPerformance API記録である。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A |
| 送信元名称 | N/A |
| 件名 | N/A |
| 形式 | Performance APIエントリ |

### 本文テンプレート

start呼び出し時：
```
performance.mark("{label} (start)")
```

end呼び出し時：
```
performance.mark("{label} (end)")
performance.measure("{label}", { start: "{label} (start)", end: "{label} (end)", detail: {detail} })
```

hit呼び出し時：
```
performance.mark("{label}", { detail: {detail} })
```

error呼び出し時：
```
performance.mark("(error)", { detail: { error: "{error}" } })
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| label | 計測対象の識別ラベル | 呼び出し元が指定 | Yes（error以外） |
| detail | 追加の詳細情報 | 呼び出し元が指定 | No |
| error | エラーオブジェクト | catchされたエラー | Yes（errorメソッドのみ） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `I.start(label)` | 無条件 | 処理フェーズ開始のマーク |
| API呼び出し | `I.end(label, detail?)` | 無条件 | 処理フェーズ終了のマーク+経過時間計測 |
| API呼び出し | `I.hit(label, detail?)` | 無条件 | 単発イベントのマーク |
| API呼び出し | `I.error(error)` | 無条件 | エラー発生のマーク（エラーは再throw） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 呼び出し元が呼ばない | Instrumentationインスタンスのメソッドが呼ばれなければ記録されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["Instrumentationインスタンス生成"] --> B{"メソッド呼び出し"}
    B -->|"start(label)"| C["performance.mark('{label} (start)')"]
    B -->|"end(label)"| D["performance.mark('{label} (end)')"]
    D --> E["performance.measure(label, {start, end, detail})"]
    B -->|"hit(label)"| F["performance.mark(label, {detail})"]
    B -->|"error(error)"| G["performance.mark('(error)', {detail: {error}})"]
    G --> H["throw error（再throw）"]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | データベースは使用しない |

### テーブル別参照項目詳細

本通知ではデータベースを参照しない。

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| エラー再throw | `error()`メソッド呼び出し時 | マーク記録後にエラーが再throwされる。呼び出し元でキャッチが必要 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。ブラウザ環境でのCSS処理中に即座に記録される。

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

Performance APIのエントリはブラウザタブ内で共有されるため、同一ページ内の他のスクリプトからアクセス可能。エラー情報がdetailに含まれる場合は注意が必要。ただし、通常はラベル文字列と計測値のみが記録される。

## 備考

- `Instrumentation`クラスはNode.js版（`@tailwindcss-node`）とブラウザ版（`@tailwindcss-browser`）で異なる実装を持つが、同じインターフェースを提供する。
- ブラウザ版は`performance.mark()`と`performance.measure()`を使用し、Node.js版は`process.hrtime.bigint()`と`process.stderr.write()`を使用する。
- `error()`メソッドはマーク記録後にエラーを再throwするため、呼び出し元での例外処理は中断されない。
- ブラウザ版のInstrumentationクラスはDisposableインターフェースを実装しておらず、明示的な`dispose`処理は不要。

---

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

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

### 推奨読解順序

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

Instrumentationクラスのメソッドインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | 1-29行目の全体。`start`, `end`, `hit`, `error`の4メソッドを持つシンプルなクラス |

**読解のコツ**: ブラウザ版はグローバルの`performance`オブジェクトを直接使用する。各メソッドは1-3行程度の短い実装で、Performance APIの薄いラッパーとして機能する。

#### Step 2: 各メソッドの実装を理解する

4つのメソッドそれぞれの具体的な動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | 2-4行目: `start(label)` — `performance.mark(\`${label} (start)\`)`を呼び出し |
| 2-2 | instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | 6-13行目: `end(label, detail?)` — endマーク+`performance.measure`で経過時間計測 |
| 2-3 | instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | 16-20行目: `hit(label, detail?)` — 単発マーク |
| 2-4 | instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | 22-28行目: `error(error)` — エラーマーク+再throw |

**主要処理フロー**:
- **3行目**: `performance.mark(\`${label} (start)\`)`
- **7行目**: `performance.mark(\`${label} (end)\`)`
- **9-13行目**: `performance.measure(label, { start, end, detail })`
- **17-19行目**: `performance.mark(label, { detail })`
- **23-25行目**: `performance.mark('(error)', { detail: { error: \`${error}\` } })`
- **27行目**: `throw error` — エラー再throw

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

```
Instrumentation (browser版)
    |
    +-- start(label) (instrumentation.ts:2)
    |      |
    |      +-- performance.mark(`${label} (start)`) (instrumentation.ts:3)
    |
    +-- end(label, detail?) (instrumentation.ts:6)
    |      |
    |      +-- performance.mark(`${label} (end)`) (instrumentation.ts:7)
    |      +-- performance.measure(label, {start, end, detail}) (instrumentation.ts:9-13)
    |
    +-- hit(label, detail?) (instrumentation.ts:16)
    |      |
    |      +-- performance.mark(label, {detail}) (instrumentation.ts:17-19)
    |
    +-- error(error) (instrumentation.ts:22)
           |
           +-- performance.mark("(error)", {detail: {error}}) (instrumentation.ts:23-25)
           +-- throw error (instrumentation.ts:27)
```

### データフロー図

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

呼び出し元                 Instrumentation            ブラウザ Performance API
(label, detail?)  ───>     .start()              ───>  performance.mark
                           .end()                      performance.measure
                           .hit()                           ↓
                           .error()                    DevTools Performance タブ
                                                       Performance Observer API
                                                       サードパーティツール
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| instrumentation.ts (browser) | `packages/@tailwindcss-browser/src/instrumentation.ts` | ソース | ブラウザ版Instrumentationクラスの実装（全29行） |
| instrumentation.ts (node) | `packages/@tailwindcss-node/src/instrumentation.ts` | ソース | Node.js版Instrumentationクラス（比較参照用） |
