Async-logger-with-filter
Attach a record predicate to an async logger so only matching records are enqueued. This is the main API for async routing-by-predicate without rewriting sink implementations.
Interface
pub fn[S] AsyncLogger::with_filter(
self : AsyncLogger[S],
predicate : (@bitlogger.Record) -> Bool,
) -> AsyncLogger[S] {}input
self : AsyncLogger[S]- Base async logger to constrain.predicate : (Record) -> Bool- Record predicate that decides whether a record should be enqueued.
output
AsyncLogger[S]- A new async logger value that only enqueues matching records.
Explanation
Detailed rules explaining key parameters and behaviors
- Filtering happens after record construction and patch application but before enqueue.
- Existing filter logic is preserved and combined with the new predicate using logical
and. - The returned logger is derived from
self; the original async logger value is not mutated. - Only the stored filter pipeline changes. Target, minimum level, queue configuration, and lifecycle/failure state stay on the same
AsyncLogger[S]surface. - Filtering avoids unnecessary queue pressure for records that should never be delivered.
- In the current direct async coverage, derived filters can compose target, level, and message predicates together while the original logger still accepts writes according to its previous filter state.
How to Use
Here are some specific examples provided.
When Keep Only One Async Target Namespace
When an async logger should only enqueue records from a specific subsystem:
let logger = async_logger(console_sink(), target="service")
.with_filter(@bitlogger.target_has_prefix("service.api"))In this example, non-matching records are dropped before they reach the async queue.
And the returned async logger still keeps the same queue-facing API surface as the source logger.
When Combine Several Async Filter Rules
When filtering depends on multiple conditions:
let logger = async_logger(console_sink(), target="api")
.with_filter(fn(rec) {
rec.level.enabled(@bitlogger.Level::Warn) && rec.message.contains("timeout")
})In this example, only warning-or-higher timeout records are enqueued.
Error Case
e.g.:
If the predicate always returns
false, the logger silently drops every record before enqueue.If the predicate always returns
true, the wrapper behaves like a pass-through filter.
Notes
Use this API for selection logic, not record mutation.
Async filtering is especially useful when queue capacity should be reserved for high-value records.
State helpers such as
pending_count(),dropped_count(),is_closed(), andhas_failed()remain available on the returned logger because the visible async logger surface is preserved.Use a derived logger value when one branch should enforce extra filter rules and the base async logger should stay unchanged.