Files
BitLogger/docs/api/library-async-logger.md
T
2026-06-14 08:41:06 +08:00

5.6 KiB

name, group, category, update-time, description, key-word
name group category update-time description key-word
library-async-logger api facade 20260614 Public library-facing async logger facade type used to expose a narrower surface than AsyncLogger while preserving sink typing.
library
async
facade
public

Library-async-logger

LibraryAsyncLogger[S] is the public library-facing async logger facade type. It wraps AsyncLogger[S] and keeps queue-backed async logging behavior while intentionally exposing a narrower public surface for package boundaries.

Interface

pub struct LibraryAsyncLogger[S] {
  inner : AsyncLogger[S]
}

output

  • LibraryAsyncLogger[S] - Public library-oriented async logger wrapper over a concrete sink type S.

Explanation

Detailed rules explaining key parameters and behaviors

  • This is a public facade struct, not a type alias.
  • The wrapped sink type S is preserved, so sink-specific typing remains available through the facade type parameter.
  • The facade keeps common library-safe async operations such as new(...), with_target(...), child(...), bind(...), is_enabled(...), run(), shutdown(), and the main async write methods log(...), info(...), warn(...), and error(...).
  • LibraryAsyncLogger::new(...) delegates to async_logger(...), so the same async queue, raising flush callback, and runtime-dependent lifecycle behavior still exist behind the narrower facade.
  • The facade also preserves the wrapped async logger's 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 derives another logger with with_target(...) or child(...).
  • Most facade reshaping helpers keep the same visible sink type, and unlike synchronous LibraryLogger, async with_context_fields(...) and bind(...) also preserve the visible LibraryAsyncLogger[S] type because they update stored async context metadata instead of changing the exposed sink wrapper.
  • It does not expose the wider AsyncLogger[S] composition surface or the async state and lifecycle inspection helpers directly.
  • Call to_async_logger() when later code must recover the full underlying AsyncLogger[S] surface.
  • That recovered logger is the same live async value, so queue counters, retained failure state, runtime-dependent shutdown outcomes, and sink helper access are preserved rather than recomputed.

How to Use

Here are some specific examples provided.

When Need A Narrower Public Async Logger Type

When a package should expose async logging capability without publishing the full AsyncLogger[S] API:

let logger : LibraryAsyncLogger[@bitlogger.ConsoleSink] = LibraryAsyncLogger::new(
  @bitlogger.console_sink(),
  target="lib.async",
)

In this example, the package boundary exposes the library async facade instead of the full async logger type.

When Need A One-call Target Override Through The Library Facade

When package code should keep the same library-facing async value but emit one record under a different target:

logger.log(@bitlogger.Level::Error, "boom", target="lib.async.audit")

In this example, the emitted record uses lib.async.audit only for that one 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(...).

When Need Shared Async Context Without Changing The Visible Facade Type

When package code should attach stable metadata but still keep the same visible LibraryAsyncLogger[S] shape:

let request_logger = logger.bind([@bitlogger.field("request_id", "req-42")])

In this example, later writes automatically prepend request_id.

And unlike synchronous LibraryLogger, the returned async facade still has the visible type LibraryAsyncLogger[S] rather than a different sink wrapper spelling.

When Need To Recover The Full Async Logger Later

When a library-facing async facade should later be adapted back into the ordinary async logger surface:

let full = logger.to_async_logger()
ignore(full.pending_count())

In this example, the facade can be unwrapped when broader async lifecycle or state operations are needed internally.

Error Case

e.g.:

  • LibraryAsyncLogger[S] itself does not have a runtime failure mode.

  • Runtime behavior still depends on the wrapped sink S and async runtime support, so sink-specific or target-specific limitations remain unchanged behind the facade.

  • Post-close logging behavior, queue state, and failure-state behavior remain those of the wrapped AsyncLogger[S]; the facade only narrows what is directly exposed.

  • If the wrapped async logger later ends in a mixed diagnostic state such as has_failed=true with retained backlog, unwrapping exposes that exact state instead of a library-specific translation.

  • Helpers such as pending_count(), dropped_count(), is_closed(), is_running(), has_failed(), last_error(), flush_policy(), state(), and wait_idle() remain on the underlying AsyncLogger[S] and require to_async_logger() first.

Notes

  1. Use LibraryAsyncLogger::new(...), build_library_async_logger(...), or parse_and_build_library_async_logger(...) when you need a value of this type.

  2. Use AsyncLogger[S] directly when exposing the full async lifecycle and state surface is acceptable.

  3. Use to_async_logger() when internal code later needs the broader lifecycle/state helpers without changing the facade type exposed at the package boundary.