🔊 Update 1.0.0

This commit is contained in:
Nanaloveyuki
2026-06-27 10:45:36 +08:00
parent 7557e37cc8
commit c8023b0ded
55 changed files with 5734 additions and 2360 deletions
+16 -6
View File
@@ -1,6 +1,14 @@
///|
async fn main {
println("examples/async_basic is shipped as a native-only example because async fn main entry support is still limited on non-native targets, even though src-async itself keeps compatibility behavior.")
println(@lib_async.stringify_async_runtime_state(@lib_async.async_runtime_state(), pretty=true))
println(
"examples/async_basic is shipped as a native-only example because async fn main entry support is still limited on non-native targets, even though src-async itself keeps compatibility behavior.",
)
println(
@lib_async.stringify_async_runtime_state(
@lib_async.async_runtime_state(),
pretty=true,
),
)
let raw = "{\"logger\":{\"min_level\":\"info\",\"target\":\"async.demo\",\"timestamp\":true,\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"separator\":\" | \"}}},\"async_config\":{\"max_pending\":2,\"overflow\":\"DropOldest\",\"max_batch\":4,\"linger_ms\":5,\"flush\":\"Batch\"}}"
let config = @lib_async.parse_async_logger_build_config_text(raw) catch {
@@ -14,10 +22,12 @@ async fn main {
let logger = @lib_async.build_async_logger(config)
.with_context_fields([@lib.field("service", "bitlogger")])
.with_filter(@lib.target_has_prefix("async"))
.with_patch(@lib.compose_patches([
@lib.prefix_message("[async] "),
@lib.redact_fields(["token"]),
]))
.with_patch(
@lib.compose_patches([
@lib.prefix_message("[async] "),
@lib.redact_fields(["token"]),
]),
)
println(@lib_async.stringify_async_logger_state(logger.state(), pretty=true))
+1 -1
View File
@@ -1,7 +1,7 @@
import {
"Nanaloveyuki/BitLogger/src" @lib,
"Nanaloveyuki/BitLogger/src-async" @lib_async,
"moonbitlang/async" @async,
"moonbitlang/async",
}
supported_targets = "+native"
+74 -32
View File
@@ -1,10 +1,14 @@
///|
fn main {
let preset_logger = @lib.build_logger(
@lib.with_queue(
@lib.text_console(
min_level=@lib.Level::Info,
target="preset",
text_formatter=@lib.TextFormatterConfig::new(show_timestamp=false, separator=" | "),
text_formatter=@lib.TextFormatterConfig::new(
show_timestamp=false,
separator=" | ",
),
),
max_pending=2,
overflow=@lib.QueueOverflowPolicy::DropOldest,
@@ -20,8 +24,11 @@ fn main {
@lib.info("hello from BitLogger", fields=[@lib.field("mode", "demo")])
// Direct Logger::new(...) composition stays useful for custom sink graphs.
let logger = @lib.Logger::new(@lib.console_sink(), min_level=@lib.Level::Trace, target="custom")
.with_context_fields([@lib.field("service", "bitlogger")])
let logger = @lib.Logger::new(
@lib.console_sink(),
min_level=@lib.Level::Trace,
target="custom",
).with_context_fields([@lib.field("service", "bitlogger")])
logger.debug("custom logger ready", fields=[@lib.field("sink", "console")])
let bound_logger = @lib.Logger::new(
@@ -31,7 +38,11 @@ fn main {
).bind(@lib.fields([("service", "bitlogger"), ("scope", "audit")]))
bound_logger.info("bound logger ready", fields=[@lib.field("mode", "demo")])
let json_logger = @lib.Logger::new(@lib.json_console_sink(), min_level=@lib.Level::Info, target="json")
let json_logger = @lib.Logger::new(
@lib.json_console_sink(),
min_level=@lib.Level::Info,
target="json",
)
json_logger.info("json output", fields=[@lib.field("kind", "example")])
let fanout_logger = @lib.Logger::new(
@@ -55,12 +66,18 @@ fn main {
split_logger.info("normal output")
split_logger.warn("warning output")
let timed_logger = @lib.Logger::new(@lib.console_sink(), min_level=@lib.Level::Info, target="timed")
.with_timestamp()
let timed_logger = @lib.Logger::new(
@lib.console_sink(),
min_level=@lib.Level::Info,
target="timed",
).with_timestamp()
timed_logger.info("timestamp enabled", fields=[@lib.field("kind", "time")])
let child_logger = @lib.Logger::new(@lib.console_sink(), min_level=@lib.Level::Info, target="app")
.child("worker")
let child_logger = @lib.Logger::new(
@lib.console_sink(),
min_level=@lib.Level::Info,
target="app",
).child("worker")
child_logger.info("child target ready")
let callback_logger = @lib.Logger::new(
@@ -90,8 +107,8 @@ fn main {
color_mode=@lib.ColorMode::Always,
).with_style_tags(
@lib.default_style_tag_registry()
.set_tag("accent", fg=Some("#4cc9f0"), bold=true)
.define_alias("danger", "red"),
.set_tag("accent", fg=Some("#4cc9f0"), bold=true)
.define_alias("danger", "red"),
)
let styled_logger = @lib.Logger::new(
@lib.text_console_sink(styled_formatter),
@@ -109,25 +126,36 @@ fn main {
min_level=@lib.Level::Info,
target="file",
)
file_logger.info("native file sink ready", fields=[@lib.field("kind", "file")])
file_logger.info("native file sink ready", fields=[
@lib.field("kind", "file"),
])
ignore(file_logger.sink.flush())
ignore(file_logger.sink.close())
}
let buffered = @lib.buffered_sink(@lib.console_sink(), flush_limit=2)
let buffered_logger = @lib.Logger::new(buffered, min_level=@lib.Level::Info, target="buffered")
let buffered_logger = @lib.Logger::new(
buffered,
min_level=@lib.Level::Info,
target="buffered",
)
buffered_logger.info("buffered one")
buffered_logger.info("buffered two")
buffered.flush()
let filtered = @lib.filter_sink(
@lib.console_sink(),
fn(rec) {
rec.target == "kept"
},
let filtered = @lib.filter_sink(@lib.console_sink(), fn(rec) {
rec.target == "kept"
})
let kept_logger = @lib.Logger::new(
filtered,
min_level=@lib.Level::Info,
target="kept",
)
let dropped_logger = @lib.Logger::new(
filtered,
min_level=@lib.Level::Info,
target="dropped",
)
let kept_logger = @lib.Logger::new(filtered, min_level=@lib.Level::Info, target="kept")
let dropped_logger = @lib.Logger::new(filtered, min_level=@lib.Level::Info, target="dropped")
kept_logger.info("filter kept this")
dropped_logger.info("filter dropped this")
@@ -135,10 +163,12 @@ fn main {
@lib.console_sink(),
min_level=@lib.Level::Info,
target="service",
).with_filter(@lib.all_of([
@lib.target_has_prefix("service"),
@lib.message_contains("kept"),
]))
).with_filter(
@lib.all_of([
@lib.target_has_prefix("service"),
@lib.message_contains("kept"),
]),
)
filtered_logger.info("logger filter dropped this")
filtered_logger.child("api").info("logger filter kept this")
@@ -146,12 +176,17 @@ fn main {
@lib.console_sink(),
min_level=@lib.Level::Info,
target="auth",
).with_patch(@lib.compose_patches([
@lib.prefix_message("[safe] "),
@lib.redact_fields(["token"]),
@lib.append_fields([@lib.field("service", "bitlogger")]),
]))
patched_logger.info("login", fields=[@lib.field("user", "alice"), @lib.field("token", "secret")])
).with_patch(
@lib.compose_patches([
@lib.prefix_message("[safe] "),
@lib.redact_fields(["token"]),
@lib.append_fields([@lib.field("service", "bitlogger")]),
]),
)
patched_logger.info("login", fields=[
@lib.field("user", "alice"),
@lib.field("token", "secret"),
])
let config_logger = @lib.parse_and_build_logger(
"{\"min_level\":\"debug\",\"target\":\"config.demo\",\"timestamp\":true,\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"field_separator\":\",\",\"template\":\"[{level}] {target} {message} :: {fields}\"}},\"queue\":{\"max_pending\":2,\"overflow\":\"DropOldest\"}}",
@@ -165,7 +200,10 @@ fn main {
config_logger.info("configured from json")
ignore(config_logger.flush())
let queue_config = @lib.QueueConfig::new(4, overflow=@lib.QueueOverflowPolicy::DropOldest)
let queue_config = @lib.QueueConfig::new(
4,
overflow=@lib.QueueOverflowPolicy::DropOldest,
)
println(@lib.stringify_queue_config(queue_config))
let formatter_config = @lib.TextFormatterConfig::new(
@@ -195,13 +233,17 @@ fn main {
let file_runtime_logger = @lib.build_logger(
@lib.LoggerConfig::new(
sink=@lib.SinkConfig::new(kind=@lib.SinkKind::File, path="bitlogger-runtime-demo.log"),
sink=@lib.SinkConfig::new(
kind=@lib.SinkKind::File,
path="bitlogger-runtime-demo.log",
),
queue=Some(@lib.QueueConfig::new(8)),
),
)
file_runtime_logger.info("runtime file logger ready")
match file_runtime_logger.file_runtime_state() {
Some(snapshot) => println(@lib.stringify_runtime_file_state(snapshot, pretty=true))
Some(snapshot) =>
println(@lib.stringify_runtime_file_state(snapshot, pretty=true))
None => ()
}
ignore(file_runtime_logger.file_close())
+1
View File
@@ -1,3 +1,4 @@
///|
fn main {
let config = @lib.parse_logger_config_text(
"{\"min_level\":\"debug\",\"target\":\"demo.config\",\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"separator\":\" | \",\"template\":\"[{level}] {target} {message}\"}},\"queue\":{\"max_pending\":2,\"overflow\":\"DropOldest\"}}",
+1
View File
@@ -1,3 +1,4 @@
///|
fn main {
let logger = @lib.build_logger(
@lib.console(min_level=@lib.Level::Info, target="demo.console"),
+4 -1
View File
@@ -1,6 +1,9 @@
///|
fn main {
if !@lib.native_files_supported() {
println("native file sink is not available on this backend; examples/presets stays portable, while file_rotation remains native-focused")
println(
"native file sink is not available on this backend; examples/presets stays portable, while file_rotation remains native-focused",
)
return
}
+7 -2
View File
@@ -1,3 +1,4 @@
///|
fn main {
let config = @lib.with_queue(
@lib.text_console(
@@ -36,10 +37,14 @@ fn main {
}
let file_logger = @lib.build_logger(file_config)
file_logger.info("file preset ready", fields=[@lib.field("kind", "native-only")])
file_logger.info("file preset ready", fields=[
@lib.field("kind", "native-only"),
])
ignore(file_logger.flush())
ignore(file_logger.file_close())
} else {
println("file presets are skipped on this backend because native file support is unavailable")
println(
"file presets are skipped on this backend because native file support is unavailable",
)
}
}
+2 -3
View File
@@ -1,3 +1,4 @@
///|
fn main {
let logger = @lib.build_logger(
@lib.text_console(
@@ -6,9 +7,7 @@ fn main {
text_formatter=@lib.TextFormatterConfig::new(
show_timestamp=false,
color_mode=@lib.ColorMode::Always,
style_tags={
"accent": @lib.text_style(fg=Some("#4cc9f0"), bold=true),
},
style_tags={ "accent": @lib.text_style(fg=Some("#4cc9f0"), bold=true) },
),
),
)
+5 -1
View File
@@ -1,3 +1,4 @@
///|
fn main {
let logger = @lib.build_logger(
@lib.text_console(
@@ -11,5 +12,8 @@ fn main {
),
),
)
logger.info("formatted output", fields=[@lib.field("user", "alice"), @lib.field("request_id", "42")])
logger.info("formatted output", fields=[
@lib.field("user", "alice"),
@lib.field("request_id", "42"),
])
}