mirror of
https://github.com/Nanaloveyuki/BitLogger.git
synced 2026-07-24 00:42:18 +00:00
📝 add example-first documentation paths
This commit is contained in:
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user