From 72e29f5b690b97dc1bd6ccfd7d1fe768c475bf83 Mon Sep 17 00:00:00 2001 From: Nanaloveyuki Date: Sun, 14 Jun 2026 08:03:26 +0800 Subject: [PATCH] :memo: clarify parsed async target behavior --- .../parse-and-build-application-async-logger.md | 15 +++++++++++++++ docs/api/parse-and-build-library-async-logger.md | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/api/parse-and-build-application-async-logger.md b/docs/api/parse-and-build-application-async-logger.md index 0129a37..11c980f 100644 --- a/docs/api/parse-and-build-application-async-logger.md +++ b/docs/api/parse-and-build-application-async-logger.md @@ -42,6 +42,7 @@ Detailed rules explaining key parameters and behaviors - That includes preserving a parsed sync queue configuration inside the resulting `RuntimeSink` variant rather than collapsing it away during application-alias construction. - Because the result is the `ApplicationAsyncLogger` alias over `AsyncLogger[@bitlogger.RuntimeSink]`, this parse-and-build path returns the same underlying async logger value that `parse_async_logger_build_config_text(...)` plus `build_async_logger(...)` would produce, without narrowing the helper surface. - The returned logger keeps the full async lifecycle and state helpers directly. +- The returned logger also keeps the ordinary async logger target rules unchanged: `log(..., target=...)` can override the target for one call, while severity helpers such as `info(...)`, `warn(...)`, and `error(...)` continue to use the stored logger target unless a derived logger was created first with `with_target(...)` or `child(...)`. - In the current parsed-builder coverage, that direct equivalence also holds for serialized async state snapshots, runtime-sink variant choice, queue counters, lifecycle flags, and later failure fields after worker execution. - Parsed file-backed runtime helpers remain available on the returned logger with the same behavior as the direct `build_async_logger(parse_async_logger_build_config_text(input))` path. - Use `parse_and_build_library_async_logger(...)` instead when the same parsed runtime-sink result should be wrapped and narrowed for a library boundary. @@ -76,6 +77,20 @@ ignore(logger.state()) In this example, no unwrap step is needed because the application result is an alias, not a narrowing facade. +#### When Need A Per-call Target Override After JSON Boot + +When parsed app configuration should keep the same direct target override behavior as the ordinary async logger: +```moonbit +let logger = parse_and_build_application_async_logger(raw) catch { + err => return +} +logger.log(@bitlogger.Level::Error, "boom", target="app.audit") +``` + +In this example, the emitted record uses `app.audit` for that call. + +And later `info(...)`, `warn(...)`, or `error(...)` calls still use the logger's stored target unless code derives another logger first with `with_target(...)` or `child(...)`. + ### Error Case e.g.: diff --git a/docs/api/parse-and-build-library-async-logger.md b/docs/api/parse-and-build-library-async-logger.md index 2405e27..8fa5cad 100644 --- a/docs/api/parse-and-build-library-async-logger.md +++ b/docs/api/parse-and-build-library-async-logger.md @@ -41,6 +41,7 @@ Detailed rules explaining key parameters and behaviors - The returned facade wraps the same underlying `AsyncLogger[@bitlogger.RuntimeSink]` value that `parse_async_logger_build_config_text(...)` plus `build_async_logger(...)` would produce directly. - The resulting facade keeps library-facing async operations such as `run()` and `shutdown()` while exposing a smaller public surface. - The narrower facade does not change the underlying runtime-sink queue counters, failure state, sink shape, or runtime-dependent post-close behavior; it only hides the broader helper surface until `to_async_logger()` is used. +- The narrower facade also preserves the underlying target rules on its exposed write methods: `log(..., target=...)` can override the target for one call, while `info(...)`, `warn(...)`, and `error(...)` continue using the stored logger target unless the facade first derived another logger with `with_target(...)` or `child(...)`. - In the current parsed-builder coverage, unwrapping this facade yields the same async state snapshot, runtime-sink variant, queue counters, lifecycle flags, and failure fields as `build_async_logger(parse_async_logger_build_config_text(input))`. - Parsed file-backed runtime helpers also remain aligned after unwrap instead of being rebuilt into a different facade-specific sink state. - Async state helpers such as `pending_count()`, `dropped_count()`, `state()`, `wait_idle()`, and failure-status inspection stay on the underlying `AsyncLogger`, not on the returned facade itself. @@ -77,6 +78,20 @@ ignore(full.pending_count()) In this example, the caller unwraps the library async facade before using async state helpers. +#### When Need A Per-call Target Override Through The Library Facade + +When parsed library configuration should still allow a one-call target override without unwrapping first: +```moonbit +let logger = parse_and_build_library_async_logger(raw) catch { + err => return +} +logger.log(@bitlogger.Level::Error, "boom", target="lib.audit") +``` + +In this example, the emitted record uses `lib.audit` for that call. + +And later `info(...)`, `warn(...)`, or `error(...)` calls still use the facade's stored target unless code derives another facade first with `with_target(...)` or `child(...)`. + ### Error Case e.g.: