A structured logger for MoonBit.
let logger = Logger::new(console_sink(), min_level=Level::Info, target="demo")
.with_timestamp()
.with_context_fields([field("service", "bitlogger")])
logger.info("starting", fields=[field("port", "8080")])let worker = Logger::new(console_sink(), target="app").child("worker")
worker.info("job ready")let hook = Logger::new(
callback_sink(fn(rec) {
println("callback saw [\{rec.target}] \{rec.message}")
}),
target="hook",
)
hook.info("hello")let sink = buffered_sink(console_sink(), flush_limit=2)
let logger = Logger::new(sink, target="buffered")
logger.info("one")
logger.info("two")
sink.flush()let sink = filter_sink(console_sink(), fn(rec) {
rec.target == "kept"
})
let kept = Logger::new(sink, target="kept")
let dropped = Logger::new(sink, target="dropped")
kept.info("visible")
dropped.info("hidden")let logger = Logger::new(console_sink(), target="service")
.with_filter(all_of([
target_has_prefix("service"),
message_contains("visible"),
]))
logger.info("hidden")
logger.child("api").info("visible")let logger = Logger::new(console_sink(), target="auth")
.with_patch(compose_patches([
prefix_message("[safe] "),
redact_fields(["token"]),
append_fields([field("service", "bitlogger")]),
]))
logger.info("login", fields=[field("user", "alice"), field("token", "secret")])let logger = Logger::new(console_sink(), target="audit")
.bind(fields([("service", "bitlogger"), ("scope", "login")]))
logger.info("accepted", fields=[field("user", "alice")])let logger = Logger::new(console_sink(), target="queue")
.with_queue(max_pending=2, overflow=QueueOverflowPolicy::DropOldest)
logger.info("one")
logger.info("two")
logger.info("three")
ignore(logger.sink.flush())let logger = Logger::new(
split_by_level(
callback_sink(fn(rec) {
println("high priority: \{rec.level.label()} \{rec.message}")
}),
console_sink(),
min_level=Level::Warn,
),
min_level=Level::Trace,
target="split",
)
logger.info("normal output")
logger.warn("warning output")let formatter = text_formatter(
show_timestamp=false,
field_separator=",",
template="[{level}] {target} {message} :: {fields}",
color_mode=ColorMode::Always,
)
let logger = Logger::new(text_console_sink(formatter), target="pretty")
logger.info("hello", fields=[field("mode", "pretty")])let formatter = text_formatter(
show_timestamp=false,
color_mode=ColorMode::Always,
).with_style_tags(
default_style_tag_registry()
.set_tag("accent", fg=Some("#4cc9f0"), bold=true)
.define_alias("danger", "red"),
)
let logger = Logger::new(text_console_sink(formatter), target="styled")
logger.info("<accent>styled</> output and <danger>alert</>")let formatter = text_formatter(
color_mode=ColorMode::Always,
).without_style_markup()
let logger = Logger::new(text_console_sink(formatter), target="raw")
logger.info("<red>kept as raw text</>")let config = parse_logger_config_text(
"{\"min_level\":\"debug\",\"target\":\"config.demo\",\"timestamp\":true,\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"field_separator\":\",\",\"template\":\"[{level}] {target} {message} :: {fields}\",\"color_mode\":\"always\"}},\"queue\":{\"max_pending\":2,\"overflow\":\"DropOldest\"}}",
)
let logger = build_logger(config)
logger.info("configured from json")
ignore(logger.flush())let config = parse_logger_config_text(
"{\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"color_mode\":\"always\",\"style_tags\":{\"accent\":{\"fg\":\"#4cc9f0\",\"bold\":true}}}}}",
)
let logger = build_logger(config)
logger.info("<accent>styled from json</>")let config = parse_logger_config_text(
"{\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"color_mode\":\"always\",\"style_markup\":\"disabled\"}}}",
)
let logger = build_logger(config)
logger.info("<red>still raw</>")if native_files_supported() {
let logger = Logger::new(
file_sink("bitlogger.log", rotation=Some(file_rotation(128, max_backups=2))),
target="file",
)
logger.info("hello", fields=[field("kind", "file")])
ignore(logger.sink.flush())
ignore(logger.sink.close())
}let logger = build_logger(
LoggerConfig::new(
sink=SinkConfig::new(kind=SinkKind::File, path="bitlogger-runtime.log"),
queue=Some(QueueConfig::new(16)),
),
)
logger.info("queued hello")
match logger.file_runtime_state() {
Some(snapshot) => println(stringify_runtime_file_state(snapshot, pretty=true))
None => ()
}