# 通知設計書 2-doom-log

## 概要

本ドキュメントは、Doom Emacsにおける`doom-log`マクロによるシステム内部ログ記録機能の設計を記載する。この機能は、システム内部のログメッセージを`*Messages*`バッファに記録するための通知メカニズムである。

### 本通知の処理概要

doom-logは、Doom Emacsの内部処理状況を開発者やパワーユーザーが把握するためのログ出力機能である。

**業務上の目的・背景**：Doom Emacsは複雑な初期化プロセスとモジュールシステムを持つため、内部動作の追跡が困難になることがある。doom-logは、これらの内部処理をログとして記録し、問題診断やパフォーマンス分析を可能にする。特に起動時間の最適化や、モジュール読み込み順序の確認に不可欠である。

**通知の送信タイミング**：doom-logマクロが呼び出された時点で、`doom-inhibit-log`がnilかつログレベルが`doom-log-level`以下の場合にログが出力される。非対話モードでは`init-file-debug`フラグに依存する。

**通知の受信者**：開発者またはデバッグモードを有効にしているユーザー。`*Messages*`バッファへの記録として保存される。

**通知内容の概要**：タイムスタンプ付きのログメッセージ。フォーマットは「* 秒数:コンテキスト:メッセージ」の形式で、現在のDoomコンテキスト（startup, emacs, cli等）が含まれる。

**期待されるアクション**：開発者はログを参照して問題を特定し、パフォーマンスボトルネックを発見する。通常ユーザーは特にアクションは不要。

## 通知種別

アプリ内通知（`*Messages*`バッファへのログ記録）

## 送信仕様

### 基本情報

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

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

`*Messages*`バッファに直接出力。エコーエリアへの表示は`inhibit-message`変数で制御される。

## 通知テンプレート

### ログメッセージの場合

| 項目 | 内容 |
|-----|------|
| 表示先 | *Messages*バッファ |
| 形式 | テキスト（face: font-lock-doc-face） |

### 本文テンプレート

```
* %.06f:%s:メッセージ内容
```

例：
```
* 0.123456:*:startup:emacs:Loading module...
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| タイムスタンプ | 起動からの経過秒数 | (float-time (time-subtract (current-time) before-init-time)) | Yes |
| コンテキスト | 現在のDoomコンテキスト | doom-context変数 | Yes |
| モジュールコンテキスト | 現在のモジュール情報 | doom-module-context変数 | No |
| メッセージ | ログ内容 | 呼び出し元から渡される | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| マクロ呼び出し | (doom-log MESSAGE ARGS) | doom-inhibit-log = nil | レベル2のデフォルトログ |
| マクロ呼び出し | (doom-log LEVEL MESSAGE ARGS) | level <= doom-log-level | 明示的レベル指定 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| doom-inhibit-log = t | ログ出力を完全に抑止 |
| level > doom-log-level | 指定レベルが現在のログレベルを超える |
| noninteractive かつ init-file-debug = nil | バッチモードでデバッグ無効時 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[doom-logマクロ呼び出し] --> B{doom-inhibit-log?}
    B -->|Yes| C[出力なし]
    B -->|No| D{noninteractive?}
    D -->|Yes| E{level <= doom-log-level?}
    D -->|No| F[doom--log呼び出し]
    E -->|Yes| F
    E -->|No| C
    F --> G[タイムスタンプ計算]
    G --> H[コンテキスト文字列生成]
    H --> I[message関数でログ出力]
    I --> J[終了]
    C --> J
```

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

### 参照テーブル一覧

該当なし（Emacs Lisp変数のみ使用）

### 変数参照詳細

| 変数名 | 用途 | 取得条件 |
|--------|------|---------|
| doom-inhibit-log | ログ抑止フラグ | 常時参照可能 |
| doom-log-level | 現在のログレベル（0-3） | 常時参照可能 |
| doom-context | 現在のコンテキストリスト | 常時参照可能 |
| doom-module-context | モジュールコンテキスト | モジュール処理中のみ有効 |
| before-init-time | Emacs起動時刻 | 常時参照可能 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | - | マクロは評価されない場合でも安全に動作 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | 頻繁な呼び出しでもログは全て記録 |

### 配信時間帯

制限なし

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

- ログには内部処理情報が含まれるが、外部には送信されない
- *Messages*バッファはローカルのみでアクセス可能
- message-log-maxでバッファサイズを制限可能

## 備考

- doom-logはマクロとして実装されており、条件が満たされない場合は引数が評価されない（パフォーマンス最適化）
- ログレベル: 0=なし, 1=警告, 2=通常, 3=デバッグ

---

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

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

### 推奨読解順序

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

ログ出力に関連する変数定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | doom-lib.el | `lisp/doom-lib.el` | doom-inhibit-log変数定義（38-39行目）を確認 |
| 1-2 | doom-lib.el | `lisp/doom-lib.el` | doom-log-level変数定義（41-54行目）を確認 |

**読解のコツ**: `doom-inhibit-log`のデフォルト値は`(not (or noninteractive init-file-debug))`で、対話モードかつデバッグ無効時はログを抑止する。

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

doom-logマクロの定義を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | doom-lib.el | `lisp/doom-lib.el` | doom-logマクロ定義（77-87行目）を確認 |

**主要処理フロー**:
1. **77行目**: `defmacro doom-log`でマクロ定義開始
2. **80-83行目**: レベル引数の処理（整数ならレベル、それ以外ならデフォルト2）
3. **84-87行目**: 条件チェックとdoom--log呼び出し

#### Step 3: ログ出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | doom-lib.el | `lisp/doom-lib.el` | doom--log関数（56-73行目）を確認 |

**主要処理フロー**:
- **57-59行目**: inhibit-message制御
- **60行目**: 絶対パス指定の判定
- **61-73行目**: メッセージフォーマットとコンテキスト構築

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

```
doom-log (マクロ)
    |
    +-- doom--log (内部関数)
            |
            +-- float-time (タイムスタンプ計算)
            |
            +-- time-subtract (経過時間計算)
            |
            +-- mapconcat (コンテキスト文字列生成)
            |
            +-- message (ログ出力)
```

### データフロー図

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

LEVEL ─────────────────┐
                       │
MESSAGE ───────────────┼──▶ doom-log ──▶ doom--log ──▶ *Messages*バッファ
                       │         │
ARGS ──────────────────┘         │
                                 ├──▶ タイムスタンプ追加
doom-context ───────────────────▶├──▶ コンテキスト追加
                                 │
doom-module-context ────────────▶┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| doom-lib.el | `lisp/doom-lib.el` | ソース | doom-logマクロとdoom--log関数の定義 |
| doom.el | `lisp/doom.el` | ソース | doom-contextの定義と管理 |
| debug.el | `lisp/lib/debug.el` | ソース | doom-inhibit-logの動的制御 |
