Console and rolling file delivery for Moon-Lander logging, with bounded async sessions
| Package | What it holds | Targets |
|---|---|---|
| moonrockz/moon-lander-logging-hosting-async | Typed settings and report values, the color decision | wasm, wasm-gc, js, native |
| moonrockz/moon-lander-logging-hosting-async/runtime | Sessions, the writer task, console streams and files (guide) | native, js (Node.js and Bun) |
| moonrockz/moon-lander-hosting/logging | The opt-in host bridge that drains before the process ends (guide) | native, js |
///|
test "settings for a console and two file formats" {
let logs = "/var/log/acme"
|> @lander_core.AbsolutePath::parse
|> @sinks.LogDirectory::from_absolute
let stem = @rolling.LogFileStem::parse("acme")
let settings = @sinks.SessionSettings::new(
console=@sinks.ConsoleSink::new(minimum=Debug),
files=[
@sinks.FileSink::new(logs, stem),
@sinks.FileSink::new(logs, stem, format=JsonLines, retention=KeepAll),
],
event_limit=@sinks.QueueEventLimit::count(4096),
)
inspect(settings.files()[1].marker_path(), content="/var/log/acme/acme.jsonl.lock")
}| Setting | Default | Rule |
|---|---|---|
| ConsoleSink stream | StandardError | StandardOutput by explicit selection |
| ConsoleSink minimum, color, theme | Information, Auto, Literate | Typed cases |
| FileSink format, policy, retention | Text, DailyAndSize(10 MiB), KeepNewest(31) | Typed cases; the count includes the active file |
| FileSink json_properties | OrderedArray | NamedObject selects schema version 2; applies only to JsonLines |
| QueueEventLimit | 1024 records | 1 or more |
| QueueByteLimit | 8 MiB | 1 or more |
| RecordByteLimit | 1 MiB | 1 or more, and not more than QueueByteLimit |
| Drain limit | 5 seconds | A TimeLimit |
| File sets | Two FileSink values cannot share a directory, stem and format |
///|
test "select named properties for a rolling JSON file" {
let logs = "/var/log/acme"
|> @lander_core.AbsolutePath::parse
|> @sinks.LogDirectory::from_absolute
let file = @sinks.FileSink::new(
logs, @rolling.LogFileStem::parse("diagnostics"),
format=JsonLines, json_properties=NamedObject,
)
assert_true(file.json_properties() is NamedObject)
assert_true(file.files().format() is JsonLines)
}| Runtime | What Auto knows |
|---|---|
| Node.js, Bun | isTTY and hasColors() of the selected stream |
| native | Nothing: the pinned moonbitlang/async has no public terminal check, so Auto stays plain. Use Always to force colors |
///|
test "Auto colors are off for an unknown terminal and with NO_COLOR" {
let console = @sinks.ConsoleSink::new()
let hints = @sinks.ColorHints::from_env(no_color=Some("1"), term=None)
let none = @sinks.ColorHints::none()
assert_true(console.render_theme(ColorTerminal, none) is Literate)
assert_true(console.render_theme(Unknown, none) is Plain)
assert_true(console.render_theme(ColorTerminal, hints) is Plain)
}pub suberror SettingsError {
InvalidQueueEventLimit(count~ : Int)
InvalidQueueByteLimit(bytes~ : Int64)
InvalidRecordByteLimit(bytes~ : Int64)
RecordLimitAboveQueueLimit(record~ : Int64, queue~ : Int64)
InvalidLogDirectory(path~ : String, rule~ : LogDirectoryRule)
DuplicateFileSet(directory~ : String, name~ : String)
} derive(Debug)fn ConsoleSink::new(stream? : ConsoleStream, minimum? : Level, color? : ColorMode, theme? : Theme) -> ConsoleSinkfn ConsoleSink::render_theme(self : ConsoleSink, capability : TerminalCapability, hints : ColorHints) -> Themeimpl Show for ConsoleStreamfn DestinationReport::new(target : SinkTarget, written~ : Int64, undelivered~ : Int64, failure? : SinkFailure, retention_failure? : SinkFailure) -> DestinationReport raise ReportErrorfn DropCounts::new(queue_full~ : Int64, oversized~ : Int64, closed~ : Int64, reentrant~ : Int64) -> DropCounts raise ReportErrorpub struct FileSink {
// private fields
}fn FileSink::new(directory : LogDirectory, stem : LogFileStem, format? : FileFormat, policy? : RollingPolicy, retention? : Retention, minimum? : Level, json_properties? : JsonProperties) -> FileSinkimpl Show for LogDirectoryfn SessionReport::new(accepted~ : Int64, dropped~ : DropCounts, destinations~ : Array[DestinationReport], drain_timed_out~ : Bool, closed~ : Bool) -> SessionReport raise ReportErrorpub struct SessionSettings {
// private fields
}fn SessionSettings::new(console? : ConsoleSink, files? : Array[FileSink], event_limit? : QueueEventLimit, byte_limit? : QueueByteLimit, record_limit? : RecordByteLimit, drain_limit? : TimeLimit) -> SessionSettings raise SettingsErrorfn SinkFailure::new(operation : SinkOperation, target : SinkTarget, subject? : String, detail : String) -> SinkFailureimpl Show for SinkOperationimpl Show for SinkTargetInstall
Download zipConsole and rolling file delivery for Moon-Lander logging, with bounded async sessions