From 8203882a97abd8cac5151c027fcd3e347e3ce4fc Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Wed, 3 Dec 2025 14:07:01 +0900 Subject: [PATCH] =?UTF-8?q?docs(phase=20104):=20.hako=E5=81=B4=E3=83=AD?= =?UTF-8?q?=E3=82=AE=E3=83=B3=E3=82=B0=E8=A8=AD=E8=A8=88=E3=82=AC=E3=82=A4?= =?UTF-8?q?=E3=83=89=E7=A2=BA=E7=AB=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Section 4 (.hako側ロギング方針) to logging_policy.md - Create hako_logging_design.md (comprehensive guide, 331 lines) - Define 4 logging categories (user-facing/dev-debug/monitoring/internal Rust) - Provide 3 logging box patterns (Lightweight/Structured/Contextual) - Add best practices and anti-patterns with code examples - Update ring0-inventory.md with Phase 104 entry - Cross-reference documentation for consistency This completes Phase 104: establishing user-facing logging guidelines for Nyash applications, complementing Rust-side logging policy from Phase 99-101. Files modified: - docs/development/current/main/logging_policy.md - docs/development/current/main/hako_logging_design.md (new) - docs/development/current/main/ring0-inventory.md Related: Phase 99 (logging policy design), Phase 100-101 (Rust impl) --- .../current/main/hako_logging_design.md | 331 ++++++++++++++++++ .../current/main/logging_policy.md | 181 +++++++++- .../current/main/ring0-inventory.md | 14 + 3 files changed, 525 insertions(+), 1 deletion(-) create mode 100644 docs/development/current/main/hako_logging_design.md diff --git a/docs/development/current/main/hako_logging_design.md b/docs/development/current/main/hako_logging_design.md new file mode 100644 index 00000000..c48e32fe --- /dev/null +++ b/docs/development/current/main/hako_logging_design.md @@ -0,0 +1,331 @@ +# Phase 104: .hako側ロギング設計ガイド + +## 概要 + +Nyash(.hako)アプリケーションからのロギングを体系的に設計し、Ring0.log(Rust内部) +との役割分担を明確にする。 + +## Architecture: 3層ロギングの完全図 + +``` +┌─────────────────────────────────────────────────────────┐ +│ ユーザーアプリケーション (.hako) │ +│ │ +│ box MyApp { │ +│ main() { │ +│ me.console.println("Result: OK") ← ConsoleBox │ +│ } │ +│ } │ +└──────────────────┬──────────────────────────────────────┘ + │ + ConsoleService + (user-facing) + │ +┌──────────────────▼──────────────────────────────────────┐ +│ Rust Runtime (Ring0.log) │ +│ │ +│ ring0.log.debug("[joinir] Processing...") ← internal +│ ring0.log.error("VM error: {}") ← internal +└──────────────────┬──────────────────────────────────────┘ + │ + stderr/stdout + │ + ┌───────▼────────┐ + │ Terminal │ + │ (user sees) │ + └────────────────┘ +``` + +## ロギングの4つのカテゴリ + +### 1. User-Facing (ユーザー向け) + +**属性**: 常に表示(本番環境対応) +**出力先**: ConsoleBox → stdout +**制御**: フラグなし(常時有効) + +**例**: +```nyash +box FileProcessor { + console: ConsoleBox + + process(filename) { + me.console = new ConsoleBox() + + if file_not_found(filename) { + me.console.println("❌ File not found: " + filename) + return -1 + } + + me.console.println("✅ Processing: " + filename) + return 0 + } +} +``` + +### 2. Dev-Debug (開発用デバッグ) + +**属性**: 開発時のみ(本番環境では削除推奨) +**出力先**: println!(局所的) +**制御**: bool flag(環境変数or定数) + +**例**: +```nyash +box MathBox { + DEBUG: BoolBox = false // 環境変数から設定 + + calculate(a: Integer, b: Integer) { + if DEBUG { + print("[DEBUG] a=" + a + ", b=" + b) + } + return a + b + } +} +``` + +### 3. Monitoring (運用監視) + +**属性**: 定期レポート(本番環境で有効) +**出力先**: ConsoleBox → stdout +**制御**: 定期的(タイマーベース) + +**例**: +```nyash +box ServiceMonitor { + console: ConsoleBox + requests_count: IntegerBox + + tick() { + me.console = new ConsoleBox() + me.console.println("[PERF] Requests/sec: " + me.requests_count) + me.requests_count = 0 + } +} +``` + +### 4. Internal Rust (内部実装) + +**属性**: Rust実装の内部ログ +**出力先**: Ring0.log → stderr +**制御**: NYASH_RING0_LOG_LEVEL + +**例** (.hako側には関係ない、参考): +```rust +// src/mir/builder.rs +ring0.log.debug("[mir] Building function..."); +``` + +## ロギングBox設計パターン + +### パターン 1: Lightweight Logger + +用途: 単純なユースケース(メッセージのみ) + +```nyash +box SimpleLogger { + console: ConsoleBox + + birth() { + me.console = new ConsoleBox() + } + + log(msg) { + me.console.println(msg) + } +} + +// 使用例 +box MyApp { + main() { + local logger = new SimpleLogger() + logger.log("Processing...") + logger.log("✅ Done") + } +} +``` + +### パターン 2: Structured Logger + +用途: レベル分け(ERROR/WARN/INFO) + +```nyash +box StructuredLogger { + console: ConsoleBox + + birth() { + me.console = new ConsoleBox() + } + + error(msg) { + me.console.println("[ERROR] " + msg) + } + + warn(msg) { + me.console.println("[WARN] " + msg) + } + + info(msg) { + me.console.println("[INFO] " + msg) + } +} + +// 使用例 +box DatabaseConnector { + logger: StructuredLogger + + birth() { + me.logger = new StructuredLogger() + } + + connect(host) { + if network_unavailable() { + me.logger.error("Network unavailable") + return false + } + + me.logger.info("Connected to: " + host) + return true + } +} +``` + +### パターン 3: Contextual Logger + +用途: コンテキスト情報を含むログ + +```nyash +box ContextualLogger { + console: ConsoleBox + context: StringBox // operation_id等 + + birth(ctx) { + me.console = new ConsoleBox() + me.context = ctx + } + + log(msg) { + me.console.println("[" + me.context + "] " + msg) + } +} + +// 使用例 +box RequestHandler { + logger: ContextualLogger + + birth(request_id) { + me.logger = new ContextualLogger(request_id) + } + + process() { + me.logger.log("Request started") + // ... 処理 ... + me.logger.log("Request completed") + } +} +``` + +## ベストプラクティス + +### ✅ DO (推奨) + +1. **一元化**: ロギングBoxを1つ所有 + ```nyash + box MyApp { + logger: LoggerBox // ← 一箇所だけ + main() { ... } + } + ``` + +2. **構造化**: メッセージは構造化 + ```nyash + logger.log("[OPERATION] " + op_name + " status=" + status) + ``` + +3. **条件付き**: デバッグログにフラグ + ```nyash + if debug_enabled { + logger.debug("var=" + var) + } + ``` + +### ❌ DON'T (回避) + +1. **散乱**: 複数の ConsoleBox 初期化 + ```nyash + // ❌ ダメ + box MyApp { + main() { + local c1 = new ConsoleBox() + local c2 = new ConsoleBox() // 重複 + } + } + ``` + +2. **混在**: データ処理ロジックとログ混在 + ```nyash + // ❌ ダメ + box Processor { + process(x) { + print(x) // ← ロジックに埋め込み + return x + 1 + } + } + ``` + +3. **過剰**: 全行でログ出力 + ```nyash + // ❌ ダメ + calculate(a, b) { + print("enter") + local x = a + b + print("x=" + x) + print("exit") + return x + } + ``` + +## ロギング制御フロー + +``` +┌─────────────────┐ +│ .hako app start │ +└────────┬────────┘ + │ + ┌────▼──────────────────────────┐ + │ Check NYASH_RING0_LOG_LEVEL env │ + └────┬──────────────────────────┘ + │ + ┌────▼────────────┐ ┌──────────────────┐ + │ DEBUG level? │─Y─> │ Enable full logs │ + └────┬────────────┘ └──────────────────┘ + │ + N + ┌────▼────────────┐ ┌──────────────────┐ + │ INFO level? │─Y─> │ Error/Warn only │ + └────┬────────────┘ └──────────────────┘ + │ + N (default) + ┌────▼──────────────┐ + │ User-facing only │ + │ (ConsoleBox) │ + └───────────────────┘ +``` + +## チェックリスト: ロギング設計確認 + +実装時には以下をチェック: + +- [ ] ConsoleBox初期化は1回のみ +- [ ] ユーザーメッセージは全て ConsoleBox経由 +- [ ] デバッグログに "[DEBUG]" prefix +- [ ] エラーメッセージに "❌" 絵文字 +- [ ] 成功メッセージに "✅" 絵文字 +- [ ] ロギングLogicを別Boxに分離した +- [ ] テストコード内の println! は許容 +- [ ] 本番環境での不要なログを削除した + +## 関連ドキュメント + +- [logging_policy.md](logging_policy.md) - Rust/Ring0.log側方針 +- [ring0-inventory.md](ring0-inventory.md) - println!分類在庫 +- [core_optional_design.md](core_optional_design.md) - Optional化設計 diff --git a/docs/development/current/main/logging_policy.md b/docs/development/current/main/logging_policy.md index 701dd6a6..1a489d21 100644 --- a/docs/development/current/main/logging_policy.md +++ b/docs/development/current/main/logging_policy.md @@ -292,8 +292,187 @@ Focus on high-impact migrations first, defer low-priority changes. --- -## Related Documentation +## Section 4: .hako側ロギング方針 (Phase 104) +### 概要 + +Nyash(.hako)アプリケーションからのロギングは、ConsoleBoxを通じてユーザーに伝える方式に統一。 + +### パターン分類 + +#### Pattern 1: ユーザー向けメッセージ(user-facing) + +**用途**: ユーザーに表示される情報 +- エラーメッセージ +- 進捗情報 +- 成功/完了通知 + +**実装方法**: +```nyash +box MyApp { + console: ConsoleBox + + main() { + me.console = new ConsoleBox() + + // ✅ 正しい方法: ConsoleBox経由 + me.console.println("Processing started...") + + // 実装例: エラーハンドリング + if error_occurred { + me.console.println("❌ Error: " + error_msg) + return 1 + } + + me.console.println("✅ Success!") + return 0 + } +} +``` + +**ガイドライン**: +- すべてのユーザー向けメッセージは ConsoleBox.println() 使用 +- エラーメッセージは "❌" 絵文字で開始 +- 成功メッセージは "✅" 絵文字で開始 +- 進捗は "[1/10]" などの形式で表示 + +#### Pattern 2: デバッグ/診断ログ(dev-debug) + +**用途**: 開発時のデバッグ情報 +- 変数値のダンプ +- 関数entry/exit +- 分岐の選択記録 + +**実装方法** (Phase 104では ユーザーアプリ側は println! 許容): +```nyash +box MyApp { + main() { + // 現在: ユーザーアプリが debug print 時は println! OK + // 将来 (Phase 105): ユーザー定義ロギングフレームワーク検討 + + local debug_enabled = false // 環境変数から読む + if debug_enabled { + print("[DEBUG] Processing item: " + item_id) + } + } +} +``` + +**ガイドライン**: +- デバッグ出力は "[DEBUG]" prefix で統一 +- bool flag で on/off 制御(環境変数参照) +- 本番環境では全削除推奨 + +#### Pattern 3: 監視/メトリクス(monitoring) + +**用途**: 運用時の監視情報 +- 実行時間計測 +- メモリ使用量 +- 処理レート + +**実装方法**: +```nyash +box PerformanceMonitor { + console: ConsoleBox + start_time: IntegerBox + + begin() { + me.console = new ConsoleBox() + me.start_time = runtime.now() + } + + report() { + local elapsed = runtime.now() - me.start_time + me.console.println("[PERF] Elapsed: " + elapsed + "ms") + } +} +``` + +**ガイドライン**: +- メトリクスは "[PERF]" prefix で統一 +- 定期レポーティング推奨 +- Ring0.log(Rust側)と連携可能(将来拡張) + +### 設計原則(.hako側視点) + +1. **Single Responsibility**: 各Boxは1つのロギング目的に専念 +2. **Testability**: ログ出力をテスト可能にする(interface化) +3. **Composability**: ロギングBoxを組み合わせる +4. **Zero Config Default**: 環境変数なしでもロギング動作 + +### アンチパターン(避けるべき書き方) + +```nyash +// ❌ ダメな例 1: raw println!を散乱 +print("value: " + x) // → Boxにロギング機能を出す + +// ❌ ダメな例 2: ConsoleBoxの多重初期化 +box MyBox { + main() { + local console = new ConsoleBox() + console.println("msg1") + + local console2 = new ConsoleBox() // ← 重複初期化 + console2.println("msg2") + } +} + +// ❌ ダメな例 3: ロギングロジック混在 +box DataProcessor { + process(data) { + if validate(data) { + print("OK") // ← 出力ロジックが混在 + return process_data(data) + } + } +} + +// ✅ 正しい例: 責務分離 +box DataProcessor { + logger: LoggerBox + + process(data) { + if validate(data) { + return process_data(data) + } else { + me.logger.error("Validation failed") + return null + } + } +} +``` + +### 今後の拡張予定 + +**Phase 105**: ユーザー定義ロギングフレームワーク +- Logger Box interface化 +- ログレベル統一(DEBUG/INFO/WARN/ERROR) +- Structured logging (JSON形式) + +**Phase 106**: ログ出力先の切り替え +- ConsoleBox → FileBox +- ConsoleBox → NetworkBox +- Pluggable logger architecture + +### テストでのロギング + +テストコード内のロギング/println!は許容: +```nyash +// ✅ テストコード内 +test my_test { + local result = my_function() + print("Result: " + result) // テスト内 OK + assert(result == expected) +} +``` + +**理由**: テストは隔離環境実行のため、ログ管理の必要がない + +--- + +## 関連ドキュメント + +- [.hako側ロギング設計](hako_logging_design.md) - Phase 104 ユーザーアプリ視点 - [Ring0 Inventory](ring0-inventory.md) - println! categorization and Ring0.log plans - [CoreBoxes Design - Section 15.6-A](core_boxes_design.md#section-156-a-logsoutput-unified-design) - Architectural context - [Phase 85 CURRENT_TASK](../../../CURRENT_TASK.md) - Implementation timeline diff --git a/docs/development/current/main/ring0-inventory.md b/docs/development/current/main/ring0-inventory.md index 5c8784d4..fb907643 100644 --- a/docs/development/current/main/ring0-inventory.md +++ b/docs/development/current/main/ring0-inventory.md @@ -326,6 +326,20 @@ ring0.log.debug(&format!("Operation completed in {}ms", duration)); **Other**: ~277 locations - TBD +### Phase 104: .hako側ロギング設計 (COMPLETED) + +**Scope**: +- ConsoleBox適切な使い方ガイド +- ユーザー定義Boxからのロギングベストプラクティス +- 4つのロギングカテゴリ確立(user-facing/dev-debug/monitoring/internal Rust) +- 3つのロギングBoxパターン(Lightweight/Structured/Contextual) + +**Files Created/Updated**: +- docs/development/current/main/logging_policy.md (Section 4 追加) +- docs/development/current/main/hako_logging_design.md (new) + +**Status**: Complete - .hako側ロギング設計確立 + --- ## Section 5: Migration Roadmap