📝 Align API docs with updated interface template

This commit is contained in:
Nanaloveyuki
2026-05-12 13:20:36 +08:00
parent 8dbadd5938
commit 4d913aa642
47 changed files with 2228 additions and 406 deletions
+152
View File
@@ -0,0 +1,152 @@
---
name: example-api
group: dev
category: example-group
update-time: 20260512
description: An example API file to show how to write API doc.
key-word:
- example
- async
- sync
- public
- doc
---
**ONE API ONE FILE**
## Example-api-name
long discription.
### Interface
```moonbit
pub fn function_name(input) -> output {}
```
#### input
- `args : type` - Explain
#### output
- `output : type` - Explain
---
> `---` Just when interface has double or more write. Used to separate two different APIs.
<!--
e.g.:
```moonbit
pub fn target_is(target : String) -> RecordPredicate {}
```
#### input
- `target : String` - the expected target value
#### output
- `RecordPredicate` - a predicate used for filtering records
---
-->
> Use<! --The content packaged with -->does not actually need to be written in the official document, it is only used as an example for reference.
It is not necessary to write the complete function implementation.
### Explanation
Detailed rules explaining key parameters and behaviors
- ...
### How to Use
Here are some specific examples provided.
e.g.:
#### <What-Time-To-Use>
> title like: `#### When Need Colorful Formatter`
When sometime ...:
```moonbit
impl
```
In this example, <something> will <do-what>.
And <extra-info>.
#### <Next-Use-Method>
...
### Error Case
e.g.:
- If `target` is empty, returns a predicate that always evaluates to false.
- ...
...
### Notes
Notes are here.
1. ...
2. ...
3. ...
4. ...
...
---
## API MARKDOWN YAML HEADER
> This just is an example, `---` in fact has yaml grammer error.
```yaml
---
name: example-api
group: dev
category: example-group
update-time: 20260512
description: An example API file to show how to write API doc.
key-word:
- example
- async
- sync
- public
- doc
---
```
It has 6 key:
- `name` - short and clear api name
- `group` - in static doc template site will use this key to render how to fold and group
- `category` - fastly search category in repo and will be used in template site
- `update-time` - full number use YYYYMMdd(year, month, day)
- `discription` - short discription
- `key-word` - use 2~5 key-words to help user fastly search
## Title Capitalization Standards
NO `# ...`
- `## ...` use `Abcd`
- `### ...` use `Abcd`
- `#### ...` use `abcd`
NO `##### ...`
@@ -31,23 +31,6 @@ pub fn async_logger_build_config_to_json(
- `JsonValue` - Structured JSON representation of the full async build config.
---
e.g.:
```moonbit
pub fn async_logger_build_config_to_json(config : AsyncLoggerBuildConfig) -> @json_parser.JsonValue {}
```
#### input
- `config : AsyncLoggerBuildConfig` - Combined logger and async config.
#### output
- `JsonValue` - JSON-exportable build payload.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-17
View File
@@ -29,23 +29,6 @@ pub fn async_logger_config_to_json(config : AsyncLoggerConfig) -> @json_parser.J
- `JsonValue` - Structured JSON representation of the async config.
---
e.g.:
```moonbit
pub fn async_logger_config_to_json(config : AsyncLoggerConfig) -> @json_parser.JsonValue {}
```
#### input
- `config : AsyncLoggerConfig` - Typed async config.
#### output
- `JsonValue` - JSON-exportable async configuration.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+96
View File
@@ -0,0 +1,96 @@
---
name: async-logger-config
group: api
category: async
update-time: 20260512
description: Build the queue, batching, linger, and flush policy config used by async loggers.
key-word:
- async
- config
- queue
- public
---
## Async-logger-config
Create an `AsyncLoggerConfig` value describing queue capacity, overflow behavior, batching size, linger timing, and flush policy for async logger construction.
### Interface
```moonbit
pub fn AsyncLoggerConfig::new(
max_pending~ : Int = 0,
overflow~ : AsyncOverflowPolicy = AsyncOverflowPolicy::Blocking,
max_batch~ : Int = 1,
linger_ms~ : Int = 0,
flush~ : AsyncFlushPolicy = AsyncFlushPolicy::Never,
) -> AsyncLoggerConfig {}
```
#### input
- `max_pending : Int` - Maximum queued records.
- `overflow : AsyncOverflowPolicy` - Queue overflow strategy.
- `max_batch : Int` - Maximum records drained per batch.
- `linger_ms : Int` - Optional wait window for batch accumulation.
- `flush : AsyncFlushPolicy` - Flush behavior for batch/shutdown phases.
#### output
- `AsyncLoggerConfig` - Async runtime config object used by `async_logger(...)` or async build helpers.
### Explanation
Detailed rules explaining key parameters and behaviors
- `max_batch <= 1` is normalized to `1`.
- `linger_ms < 0` is normalized to `0`.
- `overflow` and `flush` define the most important queue/runtime behavior tradeoffs.
- This type is used directly by `async_logger(...)` and embedded in `AsyncLoggerBuildConfig`.
### How to Use
Here are some specific examples provided.
#### When Tune Async Queue Backlog And Batch Size
When async behavior should be explicit in code:
```moonbit
let config = AsyncLoggerConfig::new(
max_pending=128,
overflow=AsyncOverflowPolicy::DropOldest,
max_batch=8,
linger_ms=10,
flush=AsyncFlushPolicy::Batch,
)
```
In this example, queue pressure, batch size, and flush timing are configured together.
#### When Export Async Config
When async policy should be serialized or logged:
```moonbit
println(stringify_async_logger_config(AsyncLoggerConfig::new(max_pending=8)))
```
In this example, the config becomes a stable JSON payload.
### Error Case
e.g.:
- If `max_batch` is set to `0` or below, runtime config normalizes it to `1`.
- If `linger_ms` is negative, it is normalized to `0`.
### Notes
Notes are here.
1. This type controls async runtime behavior, not synchronous queue wrapping.
2. Prefer explicit values for production services so overflow and flush semantics are visible.
3. Use `stringify_async_logger_config(...)` when exporting diagnostics or generated config.
4. This API is reused by `AsyncLoggerBuildConfig` rather than duplicated.
-17
View File
@@ -29,23 +29,6 @@ pub fn async_logger_state_to_json(state : AsyncLoggerState) -> @json_parser.Json
- `JsonValue` - Structured JSON representation of the async logger snapshot.
---
e.g.:
```moonbit
pub fn async_logger_state_to_json(state : AsyncLoggerState) -> @json_parser.JsonValue {}
```
#### input
- `state : AsyncLoggerState` - Async logger runtime snapshot.
#### output
- `JsonValue` - JSON-exportable state value.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+86
View File
@@ -0,0 +1,86 @@
---
name: async-logger-state
group: api
category: async
update-time: 20260512
description: Read and serialize a full async logger runtime snapshot including queue counters, lifecycle flags, and runtime mode.
key-word:
- async
- state
- diagnostics
- public
---
## Async-logger-state
Read a complete async logger runtime snapshot and serialize it for diagnostics. This API is the preferred way to export queue backlog, dropped counts, lifecycle status, and runtime mode in startup logs, health endpoints, or failure reports.
### Interface
```moonbit
pub fn[S] AsyncLogger::state(self : AsyncLogger[S]) -> AsyncLoggerState {}
```
#### input
- `self : AsyncLogger[S]` - The async logger whose runtime snapshot should be read.
#### output
- `AsyncLoggerState` - A snapshot containing runtime mode, worker support, queue counts, lifecycle flags, last error, and flush policy.
### Explanation
Detailed rules explaining key parameters and behaviors
- `AsyncLoggerState` includes `runtime`, `pending_count`, `dropped_count`, `is_closed`, `is_running`, `has_failed`, `last_error`, and `flush_policy`.
- `state()` returns a point-in-time snapshot rather than a live handle.
- `async_logger_state_to_json(...)` and `stringify_async_logger_state(...)` convert the snapshot to stable diagnostic output.
- `runtime` embeds the result of `async_runtime_state()` so callers do not need to join separate helpers manually.
### How to Use
Here are some specific examples provided.
#### When Need Startup Diagnostics
When you want to expose current async logger mode and queue state at startup:
```moonbit
let logger = build_async_logger(config)
println(stringify_async_logger_state(logger.state(), pretty=true))
```
In this example, the snapshot can be printed directly without extra manual formatting.
And downstream operators can see both runtime mode and queue-related status together.
#### When Need Failure Investigation Data
When diagnosing async delivery issues:
```moonbit
let state = logger.state()
if state.has_failed {
println(stringify_async_logger_state(state, pretty=true))
}
```
In this example, the same snapshot object works for conditional diagnostics and serialization.
### Error Case
e.g.:
- If no error has occurred, `last_error` is just an empty string.
- If the queue is empty, `pending_count` is `0`; this is normal and not a special error condition.
### Notes
Notes are here.
1. Prefer this API over manually combining `pending_count()`, `dropped_count()`, and runtime-mode helpers.
2. Use `pretty=true` when emitting logs for humans and the compact form for machine-oriented payloads.
3. This snapshot is especially useful in cross-target deployments where async behavior differs by backend.
4. `AsyncLoggerState` is diagnostics-oriented and does not control the logger.
+105
View File
@@ -0,0 +1,105 @@
---
name: async-logger
group: api
category: async
update-time: 20260512
description: Create an async logger with bounded queueing, overflow policy, lifecycle helpers, and background run control.
key-word:
- async
- logger
- queue
- public
---
## Async-logger
Create an `AsyncLogger[S]` on top of a sink and async queue configuration. This API is the main entry for queue-backed async logging, including overflow policy, batching, lifecycle control, and runtime observability.
### Interface
```moonbit
pub fn[S] async_logger(
sink : S,
config~ : AsyncLoggerConfig = AsyncLoggerConfig::new(),
min_level~ : @bitlogger.Level = @bitlogger.Level::Info,
target~ : String = "",
flush~ : (S) -> Int = fn(_) { 0 },
) -> AsyncLogger[S] {}
```
#### input
- `sink : S` - Underlying sink used after queue drain.
- `config : AsyncLoggerConfig` - Queue size, overflow behavior, batching, linger, and flush policy.
- `min_level : Level` - Level gate applied before enqueue.
- `target : String` - Default target for emitted records.
- `flush : (S) -> Int` - Flush callback used by batch/shutdown flush policies.
#### output
- `AsyncLogger[S]` - A queue-backed async logger with lifecycle and state helpers.
### Explanation
Detailed rules explaining key parameters and behaviors
- `async_logger(...)` only builds the logger. Actual background draining is started by `run()`.
- In non-native targets, the implementation uses compatibility behavior while keeping the same public surface.
- `flush` is used only when batch or shutdown policy wants explicit flushing.
- Queue overflow behavior depends on `AsyncOverflowPolicy`.
### How to Use
Here are some specific examples provided.
#### When Need Background Queue Drain
When your sink should not be written directly on the caller path:
```moonbit
let logger = async_logger(callback_sink(fn(rec) { println(rec.message) }))
@async.with_task_group(group => {
group.spawn_bg(() => logger.run())
logger.info("hello")
logger.shutdown()
})
```
In this example, the worker drains queued records in the background and `shutdown()` waits for completion.
And the logging call path stays queue-oriented rather than direct-sink oriented.
#### When Need Configurable Overflow And Flush Behavior
When queue semantics matter for service durability and load:
```moonbit
let logger = async_logger(
console_sink(),
config=AsyncLoggerConfig::new(
max_pending=128,
overflow=AsyncOverflowPolicy::DropOldest,
max_batch=8,
flush=AsyncFlushPolicy::Batch,
),
)
```
In this example, queue pressure and flush timing are both explicit.
### Error Case
e.g.:
- If the logger is closed, further enqueue attempts stop being normal active logging operations.
- If queue drain fails internally, runtime state can reflect that through `has_failed()` and `last_error()`.
### Notes
Notes are here.
1. `async_logger(...)` is the async counterpart to `Logger::new(...)`.
2. Use `state()`, `pending_count()`, and `dropped_count()` for runtime diagnostics.
3. Prefer `shutdown()` over raw `close()` in normal graceful shutdown paths.
4. On cross-target code paths, pair this API with `async_runtime_mode()` or `async_runtime_state()` when behavior differences matter.
+80
View File
@@ -0,0 +1,80 @@
---
name: async-runtime-mode-label
group: api
category: async
update-time: 20260512
description: Convert AsyncRuntimeMode into a stable string label for logs, JSON, and diagnostics.
key-word:
- async
- runtime
- label
- public
---
## Async-runtime-mode-label
Convert `AsyncRuntimeMode` into a stable string label. This helper is useful when runtime mode should be logged, serialized, or exposed through human-readable diagnostics.
### Interface
```moonbit
pub fn async_runtime_mode_label(mode : AsyncRuntimeMode) -> String {}
```
#### input
- `mode : AsyncRuntimeMode` - Runtime mode enum value.
#### output
- `String` - Stable mode label such as `native_worker` or `compatibility`.
### Explanation
Detailed rules explaining key parameters and behaviors
- The returned value is intended for diagnostics and stable output, not just debugging prints.
- It keeps mode serialization logic in one place.
- This helper is used by async runtime JSON helpers.
- Labels are more stable for telemetry and docs than ad hoc manual matching at call sites.
### How to Use
Here are some specific examples provided.
#### When Need A Stable Log Label
When the mode should be included in structured or plain logs:
```moonbit
println(async_runtime_mode_label(async_runtime_mode()))
```
In this example, the label is directly usable in diagnostics.
#### When Build Custom Serialization
When callers want to embed the mode into their own payloads:
```moonbit
let label = async_runtime_mode_label(async_runtime_mode())
```
In this example, code gets a stable string without duplicating enum matching logic.
### Error Case
e.g.:
- This API assumes a valid `AsyncRuntimeMode` input and does not expose a normal runtime error path.
- If callers need the whole runtime object rather than a string label, use `async_runtime_state()`.
### Notes
Notes are here.
1. Prefer this helper over repeated manual `match` blocks when only a label is needed.
2. The label format is especially useful for JSON and telemetry.
3. This API complements `async_runtime_mode()` and `async_runtime_state()`.
4. Keep downstream consumers aligned with these stable labels rather than inventing local variants.
+83
View File
@@ -0,0 +1,83 @@
---
name: async-runtime-mode
group: api
category: async
update-time: 20260512
description: Read the current async runtime mode and distinguish native worker behavior from compatibility behavior.
key-word:
- async
- runtime
- mode
- public
---
## Async-runtime-mode
Read the current backend-specific async runtime mode. This API is the narrowest capability probe when you only care whether the current build is running native worker semantics or compatibility behavior.
### Interface
```moonbit
pub fn async_runtime_mode() -> AsyncRuntimeMode {}
```
#### input
- `none` - No arguments are required.
#### output
- `AsyncRuntimeMode` - Either `NativeWorker` or `Compatibility`.
### Explanation
Detailed rules explaining key parameters and behaviors
- The return value is determined by the active backend implementation.
- `async_runtime_mode_label(...)` converts the enum into a stable string value.
- `async_runtime_supports_background_worker()` is a narrower boolean probe built on the same idea.
- This API is intentionally small and useful for lightweight branching.
### How to Use
Here are some specific examples provided.
#### When Need A Small Capability Branch
When behavior should differ between native worker mode and compatibility mode:
```moonbit
match async_runtime_mode() {
AsyncRuntimeMode::NativeWorker => println("native worker")
AsyncRuntimeMode::Compatibility => println("compat")
}
```
In this example, the branch is explicit and readable.
#### When Need Stable String Output
When the mode should be included in logs or telemetry labels:
```moonbit
println(async_runtime_mode_label(async_runtime_mode()))
```
In this example, the output becomes a stable string instead of an enum pattern-match requirement.
### Error Case
e.g.:
- This API does not have a normal runtime failure mode; it reflects the compiled backend behavior.
- If you need worker support as a direct boolean, use `async_runtime_supports_background_worker()` instead.
### Notes
Notes are here.
1. Use this API for minimal mode branching.
2. Use `async_runtime_state()` when you also want worker support packaged into one object.
3. Use `AsyncLogger::state()` when you need logger instance counters and lifecycle flags too.
4. The enum is intentionally small to keep capability branching simple.
-17
View File
@@ -29,23 +29,6 @@ pub fn async_runtime_state_to_json(state : AsyncRuntimeState) -> @json_parser.Js
- `JsonValue` - Structured JSON representation of the runtime state.
---
e.g.:
```moonbit
pub fn async_runtime_state_to_json(state : AsyncRuntimeState) -> @json_parser.JsonValue {}
```
#### input
- `state : AsyncRuntimeState` - Runtime snapshot to export.
#### output
- `JsonValue` - JSON-exportable state object.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+83
View File
@@ -0,0 +1,83 @@
---
name: async-runtime-state
group: api
category: async
update-time: 20260512
description: Read and serialize the current backend-specific async runtime mode and worker capability.
key-word:
- async
- runtime
- diagnostics
- public
---
## Async-runtime-state
Read the current backend-specific async runtime state and serialize it for diagnostics. This API focuses on the environment-level async mode rather than any one logger instance.
### Interface
```moonbit
pub fn async_runtime_state() -> AsyncRuntimeState {}
```
#### input
- `none` - This API reads the current backend mode and does not require logger input.
#### output
- `AsyncRuntimeState` - Runtime snapshot containing `mode` and `background_worker` capability.
### Explanation
Detailed rules explaining key parameters and behaviors
- `mode` is derived from the active backend implementation.
- `background_worker` tells callers whether native worker semantics are available.
- `async_runtime_state_to_json(...)` and `stringify_async_runtime_state(...)` serialize this state.
- This API is environment-scoped and does not depend on a particular `AsyncLogger` instance.
### How to Use
Here are some specific examples provided.
#### When Need Startup Diagnostics
When startup logs should reveal async backend behavior:
```moonbit
println(stringify_async_runtime_state(async_runtime_state(), pretty=true))
```
In this example, backend mode is exposed before any logger is started.
#### When Branch Behavior By Runtime Capability
When code should react differently depending on worker support:
```moonbit
let runtime = async_runtime_state()
if runtime.background_worker {
println("native worker path")
}
```
In this example, branch decisions are based on actual runtime capability instead of assumptions.
### Error Case
e.g.:
- This API does not normally expose a dynamic error path; it reports the currently compiled backend behavior.
- If callers need richer runtime state, they should use `AsyncLogger::state()` on a logger instance instead.
### Notes
Notes are here.
1. Use this API for environment-level diagnostics.
2. Use `AsyncLogger::state()` for logger-instance diagnostics.
3. Serialization helpers make this API suitable for health output and startup logs.
4. This API is especially valuable in cross-target deployments.
@@ -0,0 +1,82 @@
---
name: async-runtime-supports-background-worker
group: api
category: async
update-time: 20260512
description: Return whether the current backend provides native async background worker support.
key-word:
- async
- runtime
- worker
- public
---
## Async-runtime-supports-background-worker
Return a boolean telling callers whether the current backend provides native background worker semantics for `bitlogger_async`. This is the narrowest capability probe when only worker support matters.
### Interface
```moonbit
pub fn async_runtime_supports_background_worker() -> Bool {}
```
#### input
- `none` - No explicit arguments are required.
#### output
- `Bool` - `true` when native background worker semantics are available, otherwise `false`.
### Explanation
Detailed rules explaining key parameters and behaviors
- `true` indicates native worker capability.
- `false` indicates compatibility-mode behavior.
- This helper is derived from backend-specific async runtime implementation choice.
- Use it when an enum branch is unnecessary and a boolean capability check is enough.
### How to Use
Here are some specific examples provided.
#### When Need A Simple Capability Branch
When logic only depends on worker availability:
```moonbit
if async_runtime_supports_background_worker() {
println("native worker available")
}
```
In this example, callers avoid a more verbose mode match.
#### When Add Diagnostics Labels
When capability should be surfaced in diagnostics:
```moonbit
println(if async_runtime_supports_background_worker() { "worker" } else { "compat" })
```
In this example, a simple boolean can drive compact status output.
### Error Case
e.g.:
- This API does not normally fail at runtime; it reflects compiled backend behavior.
- If you need the exact mode name rather than a boolean, use `async_runtime_mode()` or `async_runtime_state()`.
### Notes
Notes are here.
1. Use this helper for minimal capability checks.
2. Prefer `async_runtime_state()` when you want the same information in a richer object.
3. Prefer `AsyncLogger::state()` when logger-instance counters matter too.
4. This helper is intentionally small and should stay cheap to call.
+86
View File
@@ -0,0 +1,86 @@
---
name: build-async-logger
group: api
category: async
update-time: 20260512
description: Build an async logger from combined logger and async config without manually wiring the runtime sink.
key-word:
- async
- config
- builder
- public
---
## Build-async-logger
Build an async logger directly from `AsyncLoggerBuildConfig`. This is the config-driven async entry point that bridges synchronous logger config, sink creation, and async queue setup in one call.
### Interface
```moonbit
pub fn build_async_logger(config : AsyncLoggerBuildConfig) -> AsyncLogger[@bitlogger.RuntimeSink] {}
```
#### input
- `config : AsyncLoggerBuildConfig` - Combined synchronous logger config plus async queue/flush config.
#### output
- `AsyncLogger[RuntimeSink]` - A config-built async logger with runtime sink control preserved.
### Explanation
Detailed rules explaining key parameters and behaviors
- The `logger` section is built through the same config machinery used by synchronous configured loggers.
- The resulting async logger inherits `min_level`, `target`, and timestamp behavior from the built synchronous logger.
- File, queue, and formatter choices all come from config rather than direct code-side sink wiring.
- The returned sink type is `RuntimeSink`, which keeps configured control helpers available where relevant.
### How to Use
Here are some specific examples provided.
#### When Need Fully Config-driven Async Bootstrapping
When your application should build async logging entirely from configuration:
```moonbit
let config = parse_async_logger_build_config_text(raw) catch {
err => return
}
let logger = build_async_logger(config)
```
In this example, parsing and async runtime wiring are separated cleanly.
And the returned logger can immediately be started with `run()`.
#### When Need Runtime Sink Features After Async Build
When the sink shape is configured but runtime features still matter:
```moonbit
let logger = build_async_logger(config)
println(stringify_async_logger_state(logger.state(), pretty=true))
```
In this example, the built async logger remains introspectable even though construction was config-driven.
### Error Case
e.g.:
- If the config text was invalid, error handling should happen earlier in `parse_async_logger_build_config_text(...)`.
- If the configured sink shape is unsupported for a specific capability, the resulting runtime behavior follows the existing sink/runtime rules rather than inventing a separate builder-only failure model.
### Notes
Notes are here.
1. Prefer this API when applications externalize both sync sink choice and async queue behavior.
2. Use `async_logger(...)` directly when you want explicit code-defined sink wiring.
3. This API is the async counterpart to `build_logger(...)`.
4. The runtime diagnostics surface remains useful after config-built construction.
+90
View File
@@ -0,0 +1,90 @@
---
name: build-logger
group: api
category: config
update-time: 20260512
description: Build a configured runtime logger from a LoggerConfig while preserving queue and file control helpers.
key-word:
- logger
- config
- runtime
- public
---
## Build-logger
Build a `ConfiguredLogger` from `LoggerConfig`. This is the main config-to-runtime bridge for synchronous logging and is the builder used before async wrapping in config-driven async flows.
### Interface
```moonbit
pub fn build_logger(config : LoggerConfig) -> ConfiguredLogger {}
```
#### input
- `config : LoggerConfig` - Fully assembled logger config including level, target, timestamp, sink, and optional queue wrapper.
#### output
- `ConfiguredLogger` - A runtime logger backed by `RuntimeSink`, with queue and file control helpers preserved.
### Explanation
Detailed rules explaining key parameters and behaviors
- `build_logger(...)` constructs the runtime sink shape based on `SinkConfig` and optional queue wrapper.
- The returned logger still supports normal logging methods because `ConfiguredLogger` is `Logger[RuntimeSink]`.
- Queue metrics and file controls remain available through forwarding helpers on the configured logger.
- This API is deterministic and data-driven, making it suitable for bootstrapping from parsed config.
### How to Use
Here are some specific examples provided.
#### When Need Structured Config-first Bootstrapping
When config is already assembled as typed values:
```moonbit
let logger = build_logger(
LoggerConfig::new(
min_level=Level::Info,
target="svc",
sink=SinkConfig::new(kind=SinkKind::TextConsole),
),
)
```
In this example, no JSON parsing is required because config objects were built directly.
And the runtime logger is ready immediately.
#### When Need Config-built Queue Or File Runtime Helpers
When the sink shape comes from config but runtime controls still matter:
```moonbit
let logger = build_logger(config)
ignore(logger.pending_count())
ignore(logger.file_runtime_state())
```
In this example, config-driven construction does not remove observability or control helpers.
### Error Case
e.g.:
- If config contains a file sink on a non-native backend, callers must still respect backend capability behavior.
- If queue is not configured, queue-related counters simply reflect the non-queued runtime shape.
### Notes
Notes are here.
1. Use this API when config is already typed as `LoggerConfig`.
2. Use `parse_and_build_logger(...)` when the starting point is raw JSON text.
3. `ConfiguredLogger` is still a logger, not a separate opaque runtime object.
4. This API is the sync runtime builder paired with `build_async_logger(...)` for async use cases.
+81
View File
@@ -0,0 +1,81 @@
---
name: fields
group: api
category: record
update-time: 20260512
description: Build structured field arrays ergonomically from key-value tuples.
key-word:
- fields
- record
- helper
- public
---
## Fields
Create an `Array[Field]` from an array of `(String, String)` tuples. This helper reduces repetitive `field(...)` calls when binding context or constructing event fields.
### Interface
```moonbit
pub fn fields(entries : Array[(String, String)]) -> Array[Field] {}
```
#### input
- `entries : Array[(String, String)]` - Tuple entries where `.0` is the field key and `.1` is the field value.
#### output
- `Array[Field]` - Structured field array ready for logger APIs.
### Explanation
Detailed rules explaining key parameters and behaviors
- Each tuple becomes one `Field` value.
- Order is preserved.
- This helper is purely ergonomic and does not add validation beyond normal string handling.
- It is commonly used with `bind(...)`, `with_context_fields(...)`, and per-event field arguments.
### How to Use
Here are some specific examples provided.
#### When Build Reusable Context Fields
When binding stable metadata to a logger:
```moonbit
let logger = Logger::new(console_sink(), target="audit")
.bind(fields([("service", "billing"), ("scope", "login")]))
```
In this example, tuple syntax is shorter and easier to scan than repeated `field(...)` calls.
#### When Build Small Per-event Field Arrays
When logging a few fields inline:
```moonbit
logger.info("accepted", fields=fields([("user", "alice"), ("status", "ok")]))
```
In this example, the helper keeps call sites compact.
### Error Case
e.g.:
- If `entries` is empty, the result is just an empty field array.
- Duplicate keys are preserved rather than collapsed.
### Notes
Notes are here.
1. Use `field(...)` when only one field is needed.
2. Use `fields(...)` when tuple syntax improves readability.
3. This helper preserves order.
4. No special deduplication or normalization is performed.
+86
View File
@@ -0,0 +1,86 @@
---
name: file-rotation
group: api
category: sink
update-time: 20260512
description: Create a size-based file rotation policy for native file sinks.
key-word:
- file
- rotation
- policy
- public
---
## File-rotation
Create a size-based file rotation policy for `file_sink(...)`. This helper defines how large a file may grow before rotation and how many historical backups should be retained.
### Interface
```moonbit
pub fn file_rotation(max_bytes : Int, max_backups~ : Int = 1) -> FileRotation {}
```
#### input
- `max_bytes : Int` - Maximum active file size threshold before rotation.
- `max_backups : Int` - Number of retained backup files.
#### output
- `FileRotation` - Rotation policy usable by direct file sinks or config-driven sink state.
### Explanation
Detailed rules explaining key parameters and behaviors
- `max_bytes <= 0` is normalized to `1`.
- `max_backups <= 0` is normalized to `1`.
- Rotation is size-based only.
- This policy is consumed by `file_sink(...)`, file policy helpers, and config-driven file sink assembly.
### How to Use
Here are some specific examples provided.
#### When Need Bounded Local Log Files
When a file should not grow without limit:
```moonbit
let sink = file_sink(
"app.log",
rotation=Some(file_rotation(1024 * 1024, max_backups=3)),
)
```
In this example, the file rotates after the configured size threshold.
And up to three backup files are retained.
#### When Need Runtime Policy Composition
When file sink policy is assembled explicitly:
```moonbit
let policy = FileSinkPolicy::new(rotation=Some(file_rotation(4096, max_backups=2)))
```
In this example, rotation can be bundled with append and auto-flush settings.
### Error Case
e.g.:
- If `max_bytes` is non-positive, it is clamped to `1`.
- If `max_backups` is non-positive, it is clamped to `1`.
### Notes
Notes are here.
1. This API defines policy only; it does not open files by itself.
2. Rotation currently focuses on size thresholds rather than time schedules or compression.
3. Use with `file_sink(...)` on native-capable backends only.
4. Policy values can later be inspected through file sink state helpers.
+98
View File
@@ -0,0 +1,98 @@
---
name: file-sink
group: api
category: sink
update-time: 20260512
description: Create a native file sink with append, auto-flush, rotation, reopen, and runtime observability helpers.
key-word:
- file
- sink
- native
- public
---
## File-sink
Create a native file sink for text-oriented or custom-formatted file logging. This API includes lifecycle controls, rotation configuration, reopen behavior, policy inspection, and failure counters.
### Interface
```moonbit
pub fn file_sink(
path : String,
append~ : Bool = true,
auto_flush~ : Bool = true,
rotation~ : FileRotation? = None,
formatter~ : RecordFormatter = fn(rec) { format_text(rec) },
) -> FileSink {}
```
#### input
- `path : String` - Destination file path.
- `append : Bool` - Whether opening/reopening should append rather than truncate.
- `auto_flush : Bool` - Whether flush is attempted after each write.
- `rotation : FileRotation?` - Optional size-based rotation policy.
- `formatter : RecordFormatter` - Formatter used to render each record before writing.
#### output
- `FileSink` - A native-only sink with write, flush, close, reopen, policy, and state helpers.
### Explanation
Detailed rules explaining key parameters and behaviors
- This sink is only available on `native/llvm`; use `native_files_supported()` for capability detection.
- `append` is persistent policy state and also affects later reopen behavior.
- `auto_flush` trades durability for more flush work per record.
- Rotation is currently size-based and rename-retention-oriented, not time-based.
### How to Use
Here are some specific examples provided.
#### When Need Persistent Local Logs
When logs should be written to a host filesystem:
```moonbit
if native_files_supported() {
let sink = file_sink("app.log")
let logger = Logger::new(sink, target="file")
logger.info("started")
ignore(sink.flush())
}
```
In this example, the sink writes normal text-formatted records to `app.log`.
And capability detection prevents non-native misuse.
#### When Need Rotation And Runtime Inspection
When you want bounded local log retention plus observability:
```moonbit
let sink = file_sink("app.log", rotation=Some(file_rotation(1024, max_backups=3)))
let state = sink.state()
```
In this example, rotation policy and sink health can both be read through runtime helpers.
### Error Case
e.g.:
- If the backend is non-native, file availability is not provided and callers should not expect writes to succeed.
- If open, write, flush, or rotation fails, the sink records failure counters instead of exposing a large exception surface.
### Notes
Notes are here.
1. Always pair this API with `native_files_supported()` in cross-target code.
2. Prefer `state()`, `policy()`, and failure counters when integrating diagnostics.
3. Use `reopen_append()` and `reopen_truncate()` for common recovery flows instead of raw `reopen(...)` where possible.
4. For config-driven file logging, the mirrored control surface is exposed through `ConfiguredLogger` and `RuntimeSink`.
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::child(self : Logger[S], target : String) -> Logger[S] {}
- `Logger[S]` - A new logger whose default target is the composed child path.
---
e.g.:
```moonbit
pub fn[S] Logger::child(self : Logger[S], target : String) -> Logger[S] {}
```
#### input
- `self : Logger[S]` - Parent logger.
- `target : String` - Child suffix.
#### output
- `Logger[S]` - Logger with combined target.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-17
View File
@@ -29,23 +29,6 @@ pub fn logger_config_to_json(config : LoggerConfig) -> @json_parser.JsonValue {}
- `JsonValue` - JSON representation of the logger config.
---
e.g.:
```moonbit
pub fn logger_config_to_json(config : LoggerConfig) -> @json_parser.JsonValue {}
```
#### input
- `config : LoggerConfig` - Config to export.
#### output
- `JsonValue` - Structured JSON value.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+96
View File
@@ -0,0 +1,96 @@
---
name: logger-config
group: api
category: config
update-time: 20260512
description: Build the main logger configuration object used by config-driven runtime logger assembly.
key-word:
- logger
- config
- runtime
- public
---
## Logger-config
Create a `LoggerConfig` value describing level, target, timestamp behavior, sink shape, and optional queue wrapping. This is the main typed configuration object consumed by `build_logger(...)` and async build helpers.
### Interface
```moonbit
pub fn LoggerConfig::new(
min_level~ : Level = Level::Info,
target~ : String = "",
timestamp~ : Bool = false,
sink~ : SinkConfig = default_sink_config(),
queue~ : QueueConfig? = None,
) -> LoggerConfig {}
```
#### input
- `min_level : Level` - Global level gate.
- `target : String` - Default target namespace.
- `timestamp : Bool` - Whether the built logger should emit timestamps.
- `sink : SinkConfig` - Configured sink shape.
- `queue : QueueConfig?` - Optional synchronous queue wrapper.
#### output
- `LoggerConfig` - Main logger configuration object.
### Explanation
Detailed rules explaining key parameters and behaviors
- `LoggerConfig` is the top-level typed representation for synchronous config-driven logging.
- `sink` describes the final sink shape before optional queue wrapping.
- `queue=None` means no configured synchronous queue layer.
- This same type is embedded into async build config as the synchronous sink/runtime portion.
### How to Use
Here are some specific examples provided.
#### When Build Config In Code Instead Of JSON
When application bootstrapping prefers typed config values:
```moonbit
let config = LoggerConfig::new(
min_level=Level::Warn,
target="svc",
timestamp=true,
sink=SinkConfig::new(kind=SinkKind::TextConsole),
)
```
In this example, the logger configuration is explicit and strongly typed.
#### When Prepare Config For A Later Builder
When config is assembled in one place and built later:
```moonbit
let config = LoggerConfig::new(queue=Some(QueueConfig::new(16)))
let logger = build_logger(config)
```
In this example, the config object becomes the handoff boundary between assembly and runtime construction.
### Error Case
e.g.:
- If `sink` describes a capability-limited backend shape such as native file output on a non-native target, later runtime behavior still follows backend support rules.
- If `target` is empty, the configuration is still valid.
### Notes
Notes are here.
1. This is the core typed config object for sync logger assembly.
2. Prefer this API when config is generated in code rather than parsed from text.
3. Use `logger_config_to_json(...)` and `stringify_logger_config(...)` for export.
4. `AsyncLoggerBuildConfig` reuses this type rather than inventing a second sync logger schema.
+87
View File
@@ -0,0 +1,87 @@
---
name: logger-new
group: api
category: logging
update-time: 20260512
description: Create a typed logger with level filtering, target binding, and optional later composition.
key-word:
- logger
- sync
- public
- target
---
## Logger-new
Create a `Logger[S]` from any sink implementation. This is the main entry for synchronous logging pipelines and the base object used by most chainable helpers such as `with_context_fields(...)`, `with_filter(...)`, `with_patch(...)`, and `with_queue(...)`.
### Interface
```moonbit
pub fn[S] Logger::new(sink : S, min_level~ : Level = Level::Info, target~ : String = "") -> Logger[S] {}
```
#### input
- `sink : S` - Any sink value implementing the `Sink` trait, such as `console_sink()`, `json_console_sink()`, `file_sink(...)`, or a composed sink.
- `min_level : Level` - Minimum enabled level. Messages below this threshold are ignored.
- `target : String` - Default target attached to emitted records when `log(...)` does not override it.
#### output
- `Logger[S]` - A typed logger that keeps the original sink type and can be further composed.
### Explanation
Detailed rules explaining key parameters and behaviors
- `Logger::new(...)` does not mutate the sink. It stores the sink value as part of the returned logger.
- `min_level` applies before any sink write occurs.
- `target` is just a default value. Later calls may override it with `with_target(...)`, `child(...)`, or `log(..., target=...)`.
- `timestamp` is disabled by default and is only enabled through `with_timestamp()`.
### How to Use
Here are some specific examples provided.
#### When Create Basic Application Logger
When you need a simple typed logger with a default target:
```moonbit
let logger = Logger::new(console_sink(), min_level=Level::Info, target="app")
logger.info("started")
```
In this example, `logger` will emit `INFO` and above to the console with target `app`.
And later composition still preserves the typed logger workflow.
#### When Start A Composed Logging Pipeline
When you want to build a richer logging chain from a single root logger:
```moonbit
let logger = Logger::new(text_console_sink(text_formatter()), target="service")
.with_timestamp()
.with_context_fields([field("service", "billing")])
```
In this example, the root logger becomes the stable base for additional context and formatting features.
### Error Case
e.g.:
- If `min_level` is set too high, lower-severity records are intentionally dropped.
- If `target` is empty, records are still valid and simply omit the target unless later overridden.
### Notes
Notes are here.
1. This API is synchronous and does not create buffering or background execution by itself.
2. The returned sink type stays visible in `Logger[S]`, which is useful for typed composition.
3. Prefer `Logger::new(...)` over global helpers when you want explicit control over sink, target, and level.
4. `Logger::new(...)` is the correct starting point for both public app logging and internal composed sink pipelines.
+88
View File
@@ -0,0 +1,88 @@
---
name: logger-with-context-fields
group: api
category: logging
update-time: 20260512
description: Attach reusable structured fields to a logger so every emitted record inherits them.
key-word:
- logger
- fields
- context
- public
---
## Logger-with-context-fields
Bind shared structured fields to a logger. This is the standard way to attach stable metadata such as service name, component, region, request scope, or subsystem identity without repeating them for every log call.
### Interface
```moonbit
pub fn[S] Logger::with_context_fields(self : Logger[S], fields : Array[Field]) -> Logger[ContextSink[S]] {}
```
#### input
- `self : Logger[S]` - The base logger that should gain shared fields.
- `fields : Array[Field]` - Structured fields that will be prepended to each emitted record.
#### output
- `Logger[ContextSink[S]]` - A new logger wrapping the original sink with context-field merging behavior.
### Explanation
Detailed rules explaining key parameters and behaviors
- Context fields are merged at write time, not by mutating previously created records.
- When a log call also passes per-record fields, the context fields are placed before those per-call fields.
- This API returns a new typed logger wrapper; it does not mutate the original logger variable.
- `bind(...)` is an ergonomic alias for this same behavior.
### How to Use
Here are some specific examples provided.
#### When Need Stable Service Metadata
When every record from a logger should carry service-level metadata:
```moonbit
let logger = Logger::new(console_sink(), target="billing")
.with_context_fields([field("service", "billing"), field("region", "cn")])
logger.info("started")
```
In this example, both `service` and `region` are automatically included on every record.
And callers only need to provide fields that actually vary per event.
#### When Build Child Loggers For Subsystems
When a subsystem has both a target and fixed fields:
```moonbit
let worker = Logger::new(console_sink(), target="app")
.child("worker")
.with_context_fields([field("component", "worker")])
```
In this example, target composition and field binding stay separate but work together cleanly.
### Error Case
e.g.:
- If `fields` is empty, the logger remains valid and just adds no extra metadata.
- If duplicate field keys are provided, all fields are still emitted; conflict handling is left to the consumer/formatter side.
### Notes
Notes are here.
1. Use this for stable metadata, not highly dynamic event-specific values.
2. Prefer `fields([("k", "v")])` when you want a more ergonomic call site.
3. This API composes naturally with `with_filter(...)`, `with_patch(...)`, and `with_queue(...)`.
4. If you want an alias with the same semantics, use `bind(...)`.
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::with_filter(self : Logger[S], predicate : (Record) -> Bool) ->
- `Logger[FilterSink[S]]` - A new logger that only forwards matching records.
---
e.g.:
```moonbit
pub fn[S] Logger::with_filter(self : Logger[S], predicate : (Record) -> Bool) -> Logger[FilterSink[S]] {}
```
#### input
- `self : Logger[S]` - Logger to filter.
- `predicate : (Record) -> Bool` - Acceptance rule.
#### output
- `Logger[FilterSink[S]]` - Logger with predicate filtering.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::with_min_level(self : Logger[S], min_level : Level) -> Logger[
- `Logger[S]` - A new logger value carrying the updated threshold.
---
e.g.:
```moonbit
pub fn[S] Logger::with_min_level(self : Logger[S], min_level : Level) -> Logger[S] {}
```
#### input
- `self : Logger[S]` - Current logger.
- `min_level : Level` - New threshold.
#### output
- `Logger[S]` - Level-updated logger.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::with_patch(self : Logger[S], patch : RecordPatch) -> Logger[Pa
- `Logger[PatchSink[S]]` - A new logger that rewrites emitted records.
---
e.g.:
```moonbit
pub fn[S] Logger::with_patch(self : Logger[S], patch : RecordPatch) -> Logger[PatchSink[S]] {}
```
#### input
- `self : Logger[S]` - Logger to transform.
- `patch : RecordPatch` - Rewrite logic.
#### output
- `Logger[PatchSink[S]]` - Logger with transformation behavior.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -35,24 +35,6 @@ pub fn[S] Logger::with_queue(
- `Logger[QueuedSink[S]]` - A logger using an explicit synchronous queue wrapper.
---
e.g.:
```moonbit
pub fn[S] Logger::with_queue(self : Logger[S], max_pending~ : Int = 0, overflow~ : QueueOverflowPolicy = QueueOverflowPolicy::DropNewest) -> Logger[QueuedSink[S]] {}
```
#### input
- `max_pending : Int` - Queue bound.
- `overflow : QueueOverflowPolicy` - Backlog overflow behavior.
#### output
- `Logger[QueuedSink[S]]` - Queue-wrapped logger.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::with_target(self : Logger[S], target : String) -> Logger[S] {}
- `Logger[S]` - A new logger value carrying the updated target.
---
e.g.:
```moonbit
pub fn[S] Logger::with_target(self : Logger[S], target : String) -> Logger[S] {}
```
#### input
- `self : Logger[S]` - Current logger.
- `target : String` - Replacement target.
#### output
- `Logger[S]` - Retargeted logger.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn[S] Logger::with_timestamp(self : Logger[S], enabled~ : Bool = true) -> Lo
- `Logger[S]` - A new logger value with updated timestamp behavior.
---
e.g.:
```moonbit
pub fn[S] Logger::with_timestamp(self : Logger[S], enabled~ : Bool = true) -> Logger[S] {}
```
#### input
- `self : Logger[S]` - Current logger.
- `enabled : Bool` - Timestamp toggle.
#### output
- `Logger[S]` - Logger with updated timestamp behavior.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+93
View File
@@ -0,0 +1,93 @@
---
name: parse-and-build-logger
group: api
category: config
update-time: 20260512
description: Parse logger JSON config and immediately build a runtime logger with a stable control surface.
key-word:
- config
- logger
- json
- public
---
## Parse-and-build-logger
Parse a JSON logger definition and build a ready-to-use `ConfiguredLogger`. This is the most direct API when configuration is loaded from files, environment-derived JSON, or external settings systems.
### Interface
```moonbit
pub fn parse_and_build_logger(input : String) -> ConfiguredLogger raise ConfigError {}
```
#### input
- `input : String` - JSON text following the supported `LoggerConfig` schema.
#### output
- `ConfiguredLogger` - A runtime logger with normal logging methods plus queue/file control helpers.
### Explanation
Detailed rules explaining key parameters and behaviors
- Parsing and building are done in one step, which is useful when you do not need to inspect the intermediate `LoggerConfig`.
- The returned `ConfiguredLogger` is just `Logger[RuntimeSink]`, so it still supports regular logging calls.
- Queue wrapping and file control helpers remain available after config assembly.
- Errors are surfaced as `ConfigError` rather than silent fallback.
### How to Use
Here are some specific examples provided.
#### When Load Logger From JSON Text
When configuration comes from a file, environment variable, or settings service:
```moonbit
let logger = parse_and_build_logger(
"{\"min_level\":\"info\",\"target\":\"api\",\"sink\":{\"kind\":\"text_console\"}}",
) catch {
err => {
ignore(err)
return
}
}
```
In this example, config parsing and logger construction happen in one place.
And the resulting value can immediately emit logs.
#### When Need Config-built File Or Queue Controls
When the sink shape is chosen by config but runtime introspection is still required:
```moonbit
let logger = parse_and_build_logger(raw) catch {
err => return
}
ignore(logger.pending_count())
ignore(logger.file_runtime_state())
```
In this example, the configured runtime surface is still operational after building.
### Error Case
e.g.:
- If `input` is not valid JSON, a `ConfigError` is raised.
- If supported keys have wrong types or unsupported enum text, a `ConfigError` is raised.
### Notes
Notes are here.
1. Use `parse_logger_config_text(...)` first if you want to validate and inspect config separately.
2. Prefer this API for app bootstrapping paths that read config once and then construct the runtime logger.
3. `ConfiguredLogger` keeps queue and file helper methods, so config-driven logging does not lose control surface.
4. Keep the JSON schema limited to supported built-in sink shapes when designing external config files.
@@ -0,0 +1,86 @@
---
name: parse-async-logger-build-config-text
group: api
category: async
update-time: 20260512
description: Parse combined sync logger and async runtime JSON into a typed async build configuration.
key-word:
- async
- parse
- config
- public
---
## Parse-async-logger-build-config-text
Parse JSON text into `AsyncLoggerBuildConfig`. This API validates both the synchronous logger portion and the async queue/runtime portion before any async logger is built.
### Interface
```moonbit
pub fn parse_async_logger_build_config_text(input : String) -> AsyncLoggerBuildConfig raise {}
```
#### input
- `input : String` - JSON text containing `logger` and `async_config` sections.
#### output
- `AsyncLoggerBuildConfig` - Typed build config ready for `build_async_logger(...)` or `build_async_text_logger(...)`.
### Explanation
Detailed rules explaining key parameters and behaviors
- The JSON root is split into `logger` and `async_config`.
- `logger` reuses the same synchronous config schema parsed by `parse_logger_config_text(...)`.
- `async_config` is parsed through `parse_async_logger_config_text(...)`.
- This API separates validation from actual async runtime construction.
### How to Use
Here are some specific examples provided.
#### When Need Config-driven Async Bootstrapping
When both sink config and async runtime config come from JSON:
```moonbit
let config = parse_async_logger_build_config_text(raw) catch {
err => return
}
let logger = build_async_logger(config)
```
In this example, parsing and runtime construction remain separate and testable.
#### When Need To Inspect Async Build Config Before Use
When config should be validated or reviewed before build:
```moonbit
let config = parse_async_logger_build_config_text(raw) catch {
err => return
}
println(config.logger.target)
```
In this example, parsed sync and async sections can be inspected independently.
### Error Case
e.g.:
- If the root is not an object, parsing fails.
- If either `logger` or `async_config` contains invalid schema values, parsing fails through the underlying config parsers.
### Notes
Notes are here.
1. Use this API when async build config is stored as JSON.
2. Use `AsyncLoggerBuildConfig::new(...)` when assembling config directly in code.
3. Pair this API with `build_async_logger(...)` after validation.
4. The split `logger` plus `async_config` shape keeps sync and async concerns explicit.
+86
View File
@@ -0,0 +1,86 @@
---
name: parse-logger-config-text
group: api
category: config
update-time: 20260512
description: Parse raw JSON text into a typed LoggerConfig without building the runtime logger yet.
key-word:
- parse
- config
- json
- public
---
## Parse-logger-config-text
Parse JSON text into a typed `LoggerConfig`. This API is useful when you want validation and inspection of config data before turning it into a runtime logger.
### Interface
```moonbit
pub fn parse_logger_config_text(input : String) -> LoggerConfig raise ConfigError {}
```
#### input
- `input : String` - Raw JSON text matching the supported logger config schema.
#### output
- `LoggerConfig` - Parsed typed configuration value.
### Explanation
Detailed rules explaining key parameters and behaviors
- Parsing is separated from runtime construction.
- This API is ideal for validating, editing, or inspecting config values before calling `build_logger(...)`.
- Supported keys are intentionally constrained to stable built-in sink shapes and formatter options.
- The error surface is `ConfigError` rather than silent fallback behavior.
### How to Use
Here are some specific examples provided.
#### When Need Validation Before Runtime Build
When config should be reviewed before creating the logger:
```moonbit
let config = parse_logger_config_text(raw) catch {
err => return
}
let logger = build_logger(config)
```
In this example, parsing and building remain separate phases.
#### When Need To Inspect Parsed Values
When config should be normalized into typed values first:
```moonbit
let config = parse_logger_config_text(raw) catch {
err => return
}
println(config.target)
```
In this example, the parsed object can be inspected or rewritten before runtime use.
### Error Case
e.g.:
- If `input` is invalid JSON, parsing raises `ConfigError`.
- If supported fields have wrong types or unsupported enum text, parsing raises `ConfigError`.
### Notes
Notes are here.
1. Prefer this API when you need typed config inspection before building.
2. Prefer `parse_and_build_logger(...)` when one-step bootstrapping is enough.
3. Keep external config files aligned with the supported stable schema.
4. Parsed config remains reusable across multiple runtime builders if needed.
-17
View File
@@ -29,23 +29,6 @@ pub fn queue_config_to_json(queue : QueueConfig) -> @json_parser.JsonValue {}
- `JsonValue` - Structured JSON representation of the queue config.
---
e.g.:
```moonbit
pub fn queue_config_to_json(queue : QueueConfig) -> @json_parser.JsonValue {}
```
#### input
- `queue : QueueConfig` - Queue settings to export.
#### output
- `JsonValue` - JSON-exportable queue object.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+85
View File
@@ -0,0 +1,85 @@
---
name: queue-config
group: api
category: config
update-time: 20260512
description: Build a serializable queue wrapper config for configured synchronous loggers.
key-word:
- queue
- config
- json
- public
---
## Queue-config
Create a `QueueConfig` value for config-driven synchronous queue wrapping. This API is used inside `LoggerConfig` when the final runtime sink should be wrapped by a bounded synchronous queue.
### Interface
```moonbit
pub fn QueueConfig::new(
max_pending : Int,
overflow~ : QueueOverflowPolicy = QueueOverflowPolicy::DropNewest,
) -> QueueConfig {}
```
#### input
- `max_pending : Int` - Queue capacity used by the configured queue wrapper.
- `overflow : QueueOverflowPolicy` - Overflow strategy for full queues.
#### output
- `QueueConfig` - Queue configuration value suitable for `LoggerConfig` or JSON serialization helpers.
### Explanation
Detailed rules explaining key parameters and behaviors
- This config is used by `build_logger(...)` and `parse_and_build_logger(...)` when `queue` is present in `LoggerConfig`.
- It configures the synchronous `QueuedSink`, not the async adapter package.
- The queue remains explicit and drain-based.
- Overflow behavior is limited to the supported queue policies.
### How to Use
Here are some specific examples provided.
#### When Need Config-driven Bounded Queueing
When runtime queue wrapping should be described as config:
```moonbit
let queue = QueueConfig::new(32, overflow=QueueOverflowPolicy::DropOldest)
let config = LoggerConfig::new(queue=Some(queue))
```
In this example, the queue policy is expressed as data and later consumed by the runtime builder.
#### When Need JSON Export For Tooling
When queue policy should be exported or persisted:
```moonbit
println(stringify_queue_config(QueueConfig::new(8)))
```
In this example, the queue config is converted into a stable JSON representation.
### Error Case
e.g.:
- If `max_pending` is too small, configured runtime drops may happen frequently under bursty load.
- If queue config is omitted from `LoggerConfig`, no synchronous queue wrapper is added.
### Notes
Notes are here.
1. This API is for config-driven queue wrapping, not `bitlogger_async`.
2. Use `Logger::with_queue(...)` when you want code-side queue composition instead of config.
3. Pair with `stringify_queue_config(...)` when inspecting generated config output.
4. Queue capacity policy should be chosen based on expected burst size and acceptable loss behavior.
-17
View File
@@ -29,23 +29,6 @@ pub fn sink_config_to_json(config : SinkConfig) -> @json_parser.JsonValue {}
- `JsonValue` - JSON representation of the sink configuration.
---
e.g.:
```moonbit
pub fn sink_config_to_json(config : SinkConfig) -> @json_parser.JsonValue {}
```
#### input
- `config : SinkConfig` - Sink definition.
#### output
- `JsonValue` - Structured JSON sink value.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+99
View File
@@ -0,0 +1,99 @@
---
name: sink-config
group: api
category: config
update-time: 20260512
description: Build a typed sink configuration for config-driven logger assembly.
key-word:
- sink
- config
- file
- public
---
## Sink-config
Create a `SinkConfig` value describing the concrete sink shape used by config-driven logger builders. This API selects between console, JSON console, text console, and file-based sink assembly while also carrying sink-specific settings.
### Interface
```moonbit
pub fn SinkConfig::new(
kind~ : SinkKind = SinkKind::Console,
path~ : String = "",
append~ : Bool = true,
auto_flush~ : Bool = true,
rotation~ : FileRotation? = None,
text_formatter~ : TextFormatterConfig = default_text_formatter_config(),
) -> SinkConfig {}
```
#### input
- `kind : SinkKind` - Sink variant such as `Console`, `JsonConsole`, `TextConsole`, or `File`.
- `path : String` - File path used when `kind=File`.
- `append : Bool` - File append policy.
- `auto_flush : Bool` - File auto-flush policy.
- `rotation : FileRotation?` - Optional file rotation policy.
- `text_formatter : TextFormatterConfig` - Formatter config used by text console or file text rendering.
#### output
- `SinkConfig` - Typed sink configuration used by `LoggerConfig`.
### Explanation
Detailed rules explaining key parameters and behaviors
- One config type is used for all supported built-in sink shapes.
- File-only options are stored even though only `kind=File` actually consumes them.
- Text formatter config is always present, making text-driven sink configuration simpler and stable.
- This type is consumed by `build_logger(...)` and `parse_and_build_logger(...)`.
### How to Use
Here are some specific examples provided.
#### When Build A Text Console Config
When runtime output should be text-formatted through config:
```moonbit
let sink = SinkConfig::new(
kind=SinkKind::TextConsole,
text_formatter=TextFormatterConfig::new(show_timestamp=false),
)
```
In this example, the formatter choice is embedded directly into sink config.
#### When Build A File Sink Config
When file behavior should be data-driven:
```moonbit
let sink = SinkConfig::new(
kind=SinkKind::File,
path="app.log",
rotation=Some(file_rotation(1024, max_backups=2)),
)
```
In this example, file location and retention policy are part of the same sink definition.
### Error Case
e.g.:
- If `kind=File` but `path` is empty, the config object is still constructible, but runtime usage should be evaluated carefully.
- If `kind` is non-file, file-specific options may simply be unused by the runtime builder.
### Notes
Notes are here.
1. This type is sink-shape configuration, not the runtime sink itself.
2. Use `sink_config_to_json(...)` and `stringify_sink_config(...)` for export.
3. Prefer `SinkConfig::new(...)` over raw JSON when config is assembled programmatically.
4. `LoggerConfig` embeds exactly one `SinkConfig` plus an optional outer queue config.
@@ -33,24 +33,6 @@ pub fn stringify_async_logger_build_config(
- `String` - Serialized JSON text for the full build config.
---
e.g.:
```moonbit
pub fn stringify_async_logger_build_config(config : AsyncLoggerBuildConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `config : AsyncLoggerBuildConfig` - Build config to stringify.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn stringify_async_logger_config(config : AsyncLoggerConfig, pretty~ : Bool
- `String` - Serialized JSON text for the async config.
---
e.g.:
```moonbit
pub fn stringify_async_logger_config(config : AsyncLoggerConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `config : AsyncLoggerConfig` - Config to stringify.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -33,24 +33,6 @@ pub fn stringify_async_logger_state(
- `String` - JSON text for the async logger snapshot.
---
e.g.:
```moonbit
pub fn stringify_async_logger_state(state : AsyncLoggerState, pretty~ : Bool = false) -> String {}
```
#### input
- `state : AsyncLoggerState` - Snapshot to serialize.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - Serialized JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -33,24 +33,6 @@ pub fn stringify_async_runtime_state(
- `String` - Serialized JSON text for the runtime state.
---
e.g.:
```moonbit
pub fn stringify_async_runtime_state(state : AsyncRuntimeState, pretty~ : Bool = false) -> String {}
```
#### input
- `state : AsyncRuntimeState` - State to stringify.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn stringify_logger_config(config : LoggerConfig, pretty~ : Bool = false) ->
- `String` - Serialized logger config JSON.
---
e.g.:
```moonbit
pub fn stringify_logger_config(config : LoggerConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `config : LoggerConfig` - Logger config value.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON string.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn stringify_queue_config(queue : QueueConfig, pretty~ : Bool = false) -> St
- `String` - Serialized JSON text for the queue config.
---
e.g.:
```moonbit
pub fn stringify_queue_config(queue : QueueConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `queue : QueueConfig` - Config to stringify.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
-18
View File
@@ -30,24 +30,6 @@ pub fn stringify_sink_config(config : SinkConfig, pretty~ : Bool = false) -> Str
- `String` - Serialized sink config JSON.
---
e.g.:
```moonbit
pub fn stringify_sink_config(config : SinkConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `config : SinkConfig` - Sink config value.
- `pretty : Bool` - Pretty-print option.
#### output
- `String` - JSON string.
---
### Explanation
Detailed rules explaining key parameters and behaviors
@@ -33,24 +33,6 @@ pub fn stringify_text_formatter_config(
- `String` - Serialized JSON text for the formatter config.
---
e.g.:
```moonbit
pub fn stringify_text_formatter_config(config : TextFormatterConfig, pretty~ : Bool = false) -> String {}
```
#### input
- `config : TextFormatterConfig` - Config to stringify.
- `pretty : Bool` - Pretty-print flag.
#### output
- `String` - JSON text.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+86
View File
@@ -0,0 +1,86 @@
---
name: target-has-prefix
group: api
category: filtering
update-time: 20260512
description: Create a reusable record predicate that matches records by target prefix.
key-word:
- target
- filter
- predicate
- public
---
## Target-has-prefix
Create a `RecordPredicate` that returns `true` when a record target starts with a given prefix. This helper is commonly used with `with_filter(...)`, `filter_sink(...)`, `all_of(...)`, and routing logic.
### Interface
```moonbit
pub fn target_has_prefix(prefix : String) -> RecordPredicate {}
```
#### input
- `prefix : String` - Prefix expected at the start of `rec.target`.
#### output
- `RecordPredicate` - Predicate that matches records whose target starts with the given prefix.
### Explanation
Detailed rules explaining key parameters and behaviors
- Matching is based on `String::has_prefix(...)` over the full target string.
- This helper does not modify records; it only returns a reusable predicate.
- Prefix-based matching is especially useful when using hierarchical targets such as `app.worker.job`.
- It composes cleanly with `all_of(...)`, `any_of(...)`, and `not_(...)`.
### How to Use
Here are some specific examples provided.
#### When Filter A Target Namespace
When a logger should keep one target subtree:
```moonbit
let logger = Logger::new(console_sink(), target="app")
.with_filter(target_has_prefix("app.worker"))
```
In this example, only records under `app.worker...` remain visible.
And child targets continue to compose naturally.
#### When Combine With Level Rules
When both namespace and severity matter:
```moonbit
let predicate = all_of([
target_has_prefix("service.api"),
level_at_least(Level::Warn),
])
```
In this example, the predicate stays reusable across multiple loggers or sinks.
### Error Case
e.g.:
- If `prefix` is empty, the predicate effectively matches every target because every string starts with an empty prefix.
- If no target matches the prefix, the predicate simply returns `false` for those records.
### Notes
Notes are here.
1. This helper is most useful when targets are structured hierarchically.
2. Prefer this helper over ad hoc inline prefix logic for readability.
3. Use `target_is(...)` instead when exact equality is required.
4. Combine with `message_contains(...)` or field predicates for narrower routing rules.
-17
View File
@@ -29,23 +29,6 @@ pub fn text_formatter_config_to_json(config : TextFormatterConfig) -> @json_pars
- `JsonValue` - Structured JSON representation of the formatter config.
---
e.g.:
```moonbit
pub fn text_formatter_config_to_json(config : TextFormatterConfig) -> @json_parser.JsonValue {}
```
#### input
- `config : TextFormatterConfig` - Typed formatter config.
#### output
- `JsonValue` - JSON-exportable formatter object.
---
### Explanation
Detailed rules explaining key parameters and behaviors
+101
View File
@@ -0,0 +1,101 @@
---
name: text-formatter-config
group: api
category: config
update-time: 20260512
description: Build a serializable formatter config object that bridges JSON config and runtime text formatting.
key-word:
- formatter
- config
- json
- public
---
## Text-formatter-config
Create a `TextFormatterConfig` object for config-driven text rendering. This is the serializable counterpart to `text_formatter(...)` and is the main bridge between JSON config parsing and runtime formatter construction.
### Interface
```moonbit
pub fn TextFormatterConfig::new(
show_timestamp~ : Bool = true,
show_level~ : Bool = true,
show_target~ : Bool = true,
show_fields~ : Bool = true,
separator~ : String = " ",
field_separator~ : String = " ",
template~ : String = "",
color_mode~ : ColorMode = ColorMode::Never,
color_support~ : ColorSupport = ColorSupport::TrueColor,
style_markup~ : StyleMarkupMode = StyleMarkupMode::Full,
target_style_markup~ : StyleMarkupMode = StyleMarkupMode::Disabled,
fields_style_markup~ : StyleMarkupMode = StyleMarkupMode::Disabled,
style_tags~ : Map[String, TextStyle] = {},
) -> TextFormatterConfig {}
```
#### input
- Parameters mirror `text_formatter(...)` but are stored in a serializable config object.
- `style_tags : Map[String, TextStyle]` - Local tag definitions stored as plain config data.
#### output
- `TextFormatterConfig` - Config object that can later be serialized or converted to a runtime formatter.
### Explanation
Detailed rules explaining key parameters and behaviors
- This type is data-oriented and suitable for JSON parse/stringify workflows.
- `to_formatter()` converts config into a runtime `TextFormatter`.
- `style_tags` are stored as concrete style objects instead of alias-style runtime behavior.
- This config type is used by `SinkConfig`, `LoggerConfig`, and config-driven sink assembly.
### How to Use
Here are some specific examples provided.
#### When Need Config-built Text Output
When text formatting should be configured rather than hard-coded:
```moonbit
let formatter = TextFormatterConfig::new(
show_timestamp=false,
template="[{level}] {message}",
color_mode=ColorMode::Always,
)
```
In this example, the formatter settings are stored as config rather than a runtime-only formatter.
And the same value can be serialized or embedded in larger logger config objects.
#### When Need Runtime Bridge After Parsing
When config has already been parsed from JSON:
```moonbit
let runtime_formatter = config.sink.text_formatter.to_formatter()
```
In this example, JSON-driven settings become a real runtime formatter only when needed.
### Error Case
e.g.:
- If `template` is empty, runtime formatting falls back to the normal part-assembly path.
- If `style_tags` is empty, no local formatter tag registry is created.
### Notes
Notes are here.
1. Prefer this API when formatter behavior must be stored, parsed, or serialized.
2. Prefer `text_formatter(...)` when writing direct runtime code without config.
3. `to_formatter()` is the key bridge from config to runtime behavior.
4. This type is central to config-driven text sink assembly.
+113
View File
@@ -0,0 +1,113 @@
---
name: text-formatter
group: api
category: formatter
update-time: 20260512
description: Create a configurable text formatter for console, callback, and file-oriented text logging output.
key-word:
- formatter
- text
- color
- public
---
## Text-formatter
Create a `TextFormatter` that controls timestamp, level, target, field rendering, template substitution, color behavior, and style markup behavior. This is the main API for readable text output in `BitLogger`.
### Interface
```moonbit
pub fn text_formatter(
show_timestamp~ : Bool = true,
show_level~ : Bool = true,
show_target~ : Bool = true,
show_fields~ : Bool = true,
separator~ : String = " ",
field_separator~ : String = " ",
template~ : String = "",
color_mode~ : ColorMode = ColorMode::Never,
color_support~ : ColorSupport = ColorSupport::TrueColor,
style_markup~ : StyleMarkupMode = StyleMarkupMode::Full,
target_style_markup~ : StyleMarkupMode = StyleMarkupMode::Disabled,
fields_style_markup~ : StyleMarkupMode = StyleMarkupMode::Disabled,
style_tags~ : StyleTagRegistry? = None,
) -> TextFormatter {}
```
#### input
- `show_timestamp : Bool` - Whether timestamp text is rendered when the record carries a timestamp.
- `show_level : Bool` - Whether the level label is rendered.
- `show_target : Bool` - Whether the target is rendered.
- `show_fields : Bool` - Whether structured fields are rendered.
- `separator : String` - Separator between major rendered parts.
- `field_separator : String` - Separator used between field values in text output.
- `template : String` - Optional template using tokens such as `{level}`, `{target}`, `{message}`, `{timestamp}`, `{timestamp_ms}`, and `{fields}`.
- `color_mode : ColorMode` - `Never`, `Auto`, or `Always`.
- `color_support : ColorSupport` - `Basic` or `TrueColor`.
- `style_markup : StyleMarkupMode` - Controls whether message style tags are parsed.
- `target_style_markup : StyleMarkupMode` - Controls whether target style tags are parsed.
- `fields_style_markup : StyleMarkupMode` - Controls whether field-value style tags are parsed.
- `style_tags : StyleTagRegistry?` - Optional local tag registry.
#### output
- `TextFormatter` - A reusable text formatter instance for text sinks or direct formatting.
### Explanation
Detailed rules explaining key parameters and behaviors
- If `template` is empty, the formatter uses built-in part assembly.
- `color_mode=Auto` currently follows a conservative rule based on `NO_COLOR`.
- `style_markup`, `target_style_markup`, and `fields_style_markup` are independent scopes.
- Local `style_tags` override global tag registry lookup, which overrides builtin tags.
### How to Use
Here are some specific examples provided.
#### When Need Human-readable Console Output
When logs should stay readable in terminals:
```moonbit
let formatter = text_formatter(
show_timestamp=false,
template="[{level}] {target} {message} :: {fields}",
)
let logger = Logger::new(text_console_sink(formatter), target="demo")
```
In this example, the formatter produces predictable text output without timestamps.
And the same formatter can be reused by multiple sinks.
#### When Need Styled ANSI Output
When you want visible severity or semantic tags in terminal output:
```moonbit
let formatter = text_formatter(color_mode=ColorMode::Always)
.with_style_tags(default_style_tag_registry().set_tag("accent", fg=Some("#4cc9f0"), bold=true))
```
In this example, message text can use inline tags such as `<accent>...</>`.
### Error Case
e.g.:
- If `template` contains unknown text, the formatter keeps it as plain text.
- If a style tag is unknown or invalid, current behavior falls back to plain text rather than raising an error.
### Notes
Notes are here.
1. Prefer `text_formatter(...)` when you want explicit control over readable text output.
2. `TextFormatter` is reusable and should usually be constructed once, then shared.
3. `fields_style_markup` currently affects field values only, not field keys.
4. Use `TextFormatterConfig` when the formatter must be driven by JSON config rather than code.