📝 add example-first documentation paths

This commit is contained in:
Nanaloveyuki
2026-07-17 16:24:06 +08:00
parent c6962fe71a
commit 4e2ef69b11
14 changed files with 480 additions and 66 deletions
+47
View File
@@ -0,0 +1,47 @@
# Async Logger Lifecycle
Use the async package when a native application needs logging to run through an async queue. The library supports broader targets, but the shipped `async fn main` example is native-focused.
## Import Both Packages
```moonbit
import {
"Nanaloveyuki/BitLogger/src" @log,
"Nanaloveyuki/BitLogger/src-async" @async_log,
"moonbitlang/async",
}
```
## Build, Run, Then Shut Down
```moonbit
async fn main {
let raw = "{\"logger\":{\"min_level\":\"info\",\"target\":\"service.async\",\"sink\":{\"kind\":\"text_console\"}},\"async_config\":{\"max_pending\":64,\"overflow\":\"DropOldest\",\"max_batch\":16,\"linger_ms\":5,\"flush\":\"Batch\"}}"
let config = @async_log.parse_async_logger_build_config_text(raw) catch {
err => {
ignore(err)
return
}
}
let logger = @async_log.build_async_logger(config)
@async.with_task_group(group => {
group.spawn_bg(allow_failure=true, () => logger.run())
logger.info("worker started", fields=[@log.field("mode", "async")])
logger.shutdown()
})
}
```
`run()` owns the worker loop. Start it before producing records, then call `shutdown()` so pending work can follow the configured flush policy.
## Run The Repository Example
```bash
moon run examples/async_basic --target native
```
## Next Steps
- Inspect queue policy and flush choices in [Queueing](../extend/queue.md).
- Reference: [`parse_async_logger_build_config_text(...)`](../api/parse-async-logger-build-config-text.md), [`build_async_logger(...)`](../api/build-async-logger.md), [`run()`](../api/async-logger-run.md), and [`shutdown()`](../api/async-logger-shutdown.md).
+35
View File
@@ -0,0 +1,35 @@
# Configuration-Driven Logging
Use configuration when deployment should select levels, output, formatting, or queue behavior without changing application code.
## Parse, Build, Then Log
```moonbit
let raw = "{\"min_level\":\"info\",\"target\":\"service\",\"sink\":{\"kind\":\"text_console\",\"text_formatter\":{\"show_timestamp\":false,\"separator\":\" | \"}},\"queue\":{\"max_pending\":64,\"overflow\":\"DropOldest\"}}"
let config = @log.parse_logger_config_text(raw) catch {
err => {
ignore(err)
println("invalid logger configuration")
return
}
}
let logger = @log.build_logger(config)
logger.info("configured logger ready")
ignore(logger.flush())
```
Parsing validates the data before runtime construction. Keep the raw configuration outside application code in a real deployment, but handle parsing errors at the boundary where configuration enters the process.
## Run The Repository Example
```bash
moon run examples/config_build
```
## Next Steps
- Use [Queueing](../extend/queue.md) to choose overflow behavior deliberately.
- Use [Async lifecycle](./async.md) when the queue needs a background worker.
- Reference: [`parse_logger_config_text(...)`](../api/parse-logger-config-text.md), [`build_logger(...)`](../api/build-logger.md), and [`with_queue(...)`](../api/with-queue.md).
+51
View File
@@ -0,0 +1,51 @@
# Console And Structured Fields
Use this flow for command-line tools and services that need a human-readable starting point. A record always has a level, target, message, and optional fields.
## Install And Import
```bash
moon add Nanaloveyuki/BitLogger@0.7.0
```
```moonbit
import {
"Nanaloveyuki/BitLogger/src" @log,
}
```
## Build A Console Logger
```moonbit
fn main {
let logger = @log.build_logger(
@log.console(min_level=@log.Level::Info, target="service.http"),
)
logger.info("listening", fields=[
@log.field("port", "8080"),
@log.field("environment", "development"),
])
logger.warn("slow request", fields=[@log.field("path", "/health")])
}
```
`min_level` filters records before they reach the sink. `target` identifies the subsystem, while fields carry queryable context without interpolating it into the message.
## Switch To JSON
Keep the logging calls unchanged and replace the preset:
```moonbit
let logger = @log.build_logger(
@log.json_console(min_level=@log.Level::Info, target="service.http"),
)
```
This is the preferred output for a collector that consumes one structured record per line.
## Next Steps
- Use [Text formatting](../extend/formatting.md) for a custom terminal format.
- Use [Configuration](./config.md) when levels, targets, and sinks come from JSON.
- Reference: [`console(...)`](../api/console.md), [`json_console(...)`](../api/json-console.md), [`field(...)`](../api/field.md), and [`build_logger(...)`](../api/build-logger.md).
+51
View File
@@ -0,0 +1,51 @@
# File Output And Rotation
File output is for native applications that need local persistence. Treat it as a native-only capability and keep a console fallback for portable code.
## Check The Capability
```moonbit
if !@log.native_files_supported() {
println("file logging is unavailable on this target")
return
}
```
## Build A Rotating File Logger
```moonbit
let config = @log.with_file_rotation(
@log.file(
"service.log",
min_level=@log.Level::Info,
target="service.file",
auto_flush=true,
) catch {
err => {
ignore(err)
return
}
},
1024 * 1024,
max_backups=3,
)
let logger = @log.build_logger(config)
logger.info("file logger ready")
ignore(logger.flush())
ignore(logger.file_close())
```
The rotation limit is the size of the active file in bytes. `max_backups=3` retains the rotated backup chain. Always close a file-backed logger during orderly application shutdown.
## Run The Repository Example
```bash
moon run examples/file_rotation --target native
```
## Next Steps
- Add a bounded queue with [Queueing](../extend/queue.md) when bursts should not write synchronously.
- Read [Target boundaries](../extend/targets.md) before sharing the same logging setup with web targets.
- Reference: [`file(...)`](../api/file.md), [`with_file_rotation(...)`](../api/with-file-rotation.md), and [`file_close(...)`](../api/configured-logger-file-close.md).
+24
View File
@@ -0,0 +1,24 @@
# Examples
Examples are the primary BitLogger learning path. Each page starts from an application concern, shows the complete minimum code, and then points to the API reference for exact contracts.
## Choose A Flow
| Need | Start here | Then extend with |
| --- | --- | --- |
| Print structured logs to a terminal | [Console and fields](./console.md) | [Text formatting](../extend/formatting.md) |
| Keep local logs with bounded disk use | [File rotation](./file-rotation.md) | [Target boundaries](../extend/targets.md) |
| Build logging from app configuration | [Configuration](./config.md) | [Queueing](../extend/queue.md) |
| Avoid blocking a native application on writes | [Async lifecycle](./async.md) | [Sink composition](../extend/composition.md) |
## Repository Examples
The runnable sources live under `examples/`. The guides below explain their intended use instead of duplicating every API detail:
- `examples/console_basic` for terminal and JSON records
- `examples/config_build` for parsed configuration
- `examples/file_rotation` for native file output
- `examples/async_basic` for the async lifecycle
- `examples/presets`, `examples/text_formatter`, and `examples/style_tags` for follow-on customization
Use the [API reference](../api/index.md) when a guide links to a symbol and you need its full signature or edge-case behavior.