birch/handler/async
Async handler for non-blocking log output.
This module provides asynchronous logging capabilities where log records are queued and written by a background process/task, preventing I/O from blocking application logic.
Erlang Target (OTP Actor Pattern)
On Erlang, this uses a proper OTP actor with gleam_otp Subjects for message passing, providing:
- True non-blocking behavior with natural backpressure via actor mailbox
- Clean integration with OTP supervision trees
- Proper flush semantics with synchronous confirmation
JavaScript Target
On JavaScript, records are queued in memory and processed via setTimeout/setImmediate batching. This allows the main thread to continue while logs are written asynchronously.
Usage
import birch/handler/async
import birch/handler/console
// Wrap any handler to make it async
let async_console =
console.handler()
|> async.make_async(async.config())
// Use with custom configuration
let config =
async.config()
|> async.with_queue_size(5000)
|> async.with_flush_interval(50)
|> async.with_overflow(async.Block)
let handler = async.make_async(console.handler(), config)
// Before shutdown, ensure all logs are written
async.flush()
Types
Configuration for async handlers.
pub type AsyncConfig {
AsyncConfig(
queue_size: Int,
flush_interval_ms: Int,
overflow: OverflowBehavior,
)
}
Constructors
-
AsyncConfig( queue_size: Int, flush_interval_ms: Int, overflow: OverflowBehavior, )Arguments
- queue_size
-
Maximum number of pending messages in the queue
- flush_interval_ms
-
Flush interval in milliseconds (for batch writes)
- overflow
-
What to do when the queue is full
Behavior when the async queue is full.
pub type OverflowBehavior {
DropOldest
DropNewest
Block
}
Constructors
-
DropOldestDrop the oldest message in the queue to make room
-
DropNewestDrop the newest message (the one being added)
-
BlockBlock until there is room in the queue (use with caution)
Values
pub fn flush() -> Nil
Flush all pending log messages (Erlang implementation).
This function blocks until all queued messages have been written. Use this before application shutdown to ensure no logs are lost.
pub fn flush_handler(name: String) -> Nil
Flush a specific async handler by name (Erlang implementation).
pub fn get_subject(
name: String,
) -> Result(process.Subject(@internal Message), Nil)
Get the OTP Subject for an async handler (Erlang only).
This allows advanced users to interact directly with the actor, for example to add it to a supervision tree.
pub fn make_async(
base_handler: handler.Handler,
async_config: AsyncConfig,
) -> handler.Handler
Wrap a handler to make it asynchronous (Erlang implementation).
Uses an OTP actor with gleam_otp Subject for message passing.
pub fn shutdown_all() -> Nil
Shutdown all async handlers gracefully (Erlang only).
This flushes pending records and stops all async actors. Call this during application shutdown.
pub fn shutdown_handler(name: String) -> Nil
Shutdown a specific async handler (Erlang only).
pub fn with_flush_interval(
config: AsyncConfig,
interval_ms: Int,
) -> AsyncConfig
Set the flush interval in milliseconds.
pub fn with_overflow(
config: AsyncConfig,
overflow: OverflowBehavior,
) -> AsyncConfig
Set the overflow behavior.
pub fn with_queue_size(
config: AsyncConfig,
size: Int,
) -> AsyncConfig
Set the maximum queue size.