- Create logger_box_design.md: comprehensive Logger Box framework design - Define 3 reference patterns (Lightweight/Structured/Contextual) - Add pseudo-code examples for each pattern (reference only) - Update logging_policy.md: add Logger Box reference - Update hako_logging_design.md: Logger Box integration with Phase 104 - Update ring0-inventory.md: Phase 105 entry - Update CURRENT_TASK.md: Phase 105 completion + Phase 106+ backlog Design principles: - Logger Box provides level-based logging (DEBUG/INFO/WARN/ERROR) - Phase 105 scope: ConsoleBox output only - Phase 106 scope: output redirection (FileBox/NetworkBox) - Reference examples for documentation (execution testing Phase 106+) This completes the structured logging framework design, building on Phase 99 (logging policy), Phase 100-101 (Rust logging), Phase 104 (.hako patterns), and Phase 105.5 (console macro unification).
9.7 KiB
9.7 KiB
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 制御: フラグなし(常時有効)
例:
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定数)
例:
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 制御: 定期的(タイマーベース)
例:
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側には関係ない、参考):
// src/mir/builder.rs
ring0.log.debug("[mir] Building function...");
ロギングBox設計パターン
パターン 1: Lightweight Logger
用途: 単純なユースケース(メッセージのみ)
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)
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
用途: コンテキスト情報を含むログ
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 (推奨)
-
一元化: ロギングBoxを1つ所有
box MyApp { logger: LoggerBox // ← 一箇所だけ main() { ... } } -
構造化: メッセージは構造化
logger.log("[OPERATION] " + op_name + " status=" + status) -
条件付き: デバッグログにフラグ
if debug_enabled { logger.debug("var=" + var) }
❌ DON'T (回避)
-
散乱: 複数の ConsoleBox 初期化
// ❌ ダメ box MyApp { main() { local c1 = new ConsoleBox() local c2 = new ConsoleBox() // 重複 } } -
混在: データ処理ロジックとログ混在
// ❌ ダメ box Processor { process(x) { print(x) // ← ロジックに埋め込み return x + 1 } } -
過剰: 全行でログ出力
// ❌ ダメ 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! は許容
- 本番環境での不要なログを削除した
Phase 105: Logger Box Framework Integration
Phase 105 で Logger Box フレームワークが導入され、以下のパターンが正式化されました:
- LightweightLoggerBox: メッセージのみの単純ロギング
- StructuredLoggerBox: DEBUG/INFO/WARN/ERROR レベル付きロギング
- ContextualLoggerBox: context(request ID等)付きロギング
詳細な設計と実装例は Logger Box Design を参照してください。
Integration with Phase 104 Categories
Logger Box は以下のカテゴリに対応:
| Phase 104 Category | Logger Box Pattern | Use Case |
|---|---|---|
| user-facing | Direct ConsoleBox (no Logger Box needed) | 単純なユーザーメッセージ |
| dev-debug | StructuredLogger (DEBUG level) | デバッグ出力 |
| monitoring | StructuredLogger (INFO level) | 監視情報 |
| internal Rust | Ring0.log | Rust側の内部ログ |
関連ドキュメント
- logger_box_design.md - Phase 105 Logger Box フレームワーク
- logging_policy.md - Rust/Ring0.log側方針
- ring0-inventory.md - println!分類在庫
- core_optional_design.md - Optional化設計