From 661c17e093551bffacab8406cf0379f565ad5b0c Mon Sep 17 00:00:00 2001 From: Nanaloveyuki Date: Tue, 12 May 2026 16:06:00 +0800 Subject: [PATCH] :memo: Add logger write API docs --- docs/api/index.md | 11 +++++ docs/api/logger-bind.md | 79 ++++++++++++++++++++++++++++++ docs/api/logger-debug.md | 77 +++++++++++++++++++++++++++++ docs/api/logger-error.md | 77 +++++++++++++++++++++++++++++ docs/api/logger-info.md | 77 +++++++++++++++++++++++++++++ docs/api/logger-is-enabled.md | 80 ++++++++++++++++++++++++++++++ docs/api/logger-log.md | 92 +++++++++++++++++++++++++++++++++++ docs/api/logger-trace.md | 77 +++++++++++++++++++++++++++++ docs/api/logger-warn.md | 77 +++++++++++++++++++++++++++++ 9 files changed, 647 insertions(+) create mode 100644 docs/api/logger-bind.md create mode 100644 docs/api/logger-debug.md create mode 100644 docs/api/logger-error.md create mode 100644 docs/api/logger-info.md create mode 100644 docs/api/logger-is-enabled.md create mode 100644 docs/api/logger-log.md create mode 100644 docs/api/logger-trace.md create mode 100644 docs/api/logger-warn.md diff --git a/docs/api/index.md b/docs/api/index.md index f67f5db..457b1fe 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -23,10 +23,21 @@ BitLogger API navigation. - [logger-with-min-level.md](./logger-with-min-level.md) - [logger-with-timestamp.md](./logger-with-timestamp.md) - [logger-with-context-fields.md](./logger-with-context-fields.md) +- [logger-bind.md](./logger-bind.md) - [logger-with-filter.md](./logger-with-filter.md) - [logger-with-patch.md](./logger-with-patch.md) - [logger-with-queue.md](./logger-with-queue.md) +## Logger write APIs + +- [logger-is-enabled.md](./logger-is-enabled.md) +- [logger-log.md](./logger-log.md) +- [logger-trace.md](./logger-trace.md) +- [logger-debug.md](./logger-debug.md) +- [logger-info.md](./logger-info.md) +- [logger-warn.md](./logger-warn.md) +- [logger-error.md](./logger-error.md) + ## Formatter and fields - [text-formatter.md](./text-formatter.md) diff --git a/docs/api/logger-bind.md b/docs/api/logger-bind.md new file mode 100644 index 0000000..cb04652 --- /dev/null +++ b/docs/api/logger-bind.md @@ -0,0 +1,79 @@ +--- +name: logger-bind +group: api +category: logging +update-time: 20260512 +description: Attach reusable structured fields to a logger through the bind alias. +key-word: + - logger + - bind + - fields + - public +--- + +## Logger-bind + +Attach shared structured fields to a logger through the `bind(...)` alias. This API is behaviorally identical to `with_context_fields(...)` and exists as a shorter name for common structured context binding. + +### Interface + +```moonbit +pub fn[S] Logger::bind(self : Logger[S], fields : Array[Field]) -> Logger[ContextSink[S]] {} +``` + +#### input + +- `self : Logger[S]` - Base logger that should gain shared fields. +- `fields : Array[Field]` - Structured fields attached to every emitted record. + +#### output + +- `Logger[ContextSink[S]]` - New logger wrapper that prepends shared fields at write time. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- `bind(...)` delegates directly to `with_context_fields(...)`. +- The original logger value is not mutated; a wrapped logger is returned. +- Shared fields are applied to every later log call emitted through the returned logger. +- This alias is useful when you prefer shorter chaining syntax in application code. + +### How to Use + +Here are some specific examples provided. + +#### When Bind Shared Request Context + +When a logger should carry stable fields through a flow: +```moonbit +let request_logger = Logger::new(console_sink(), target="api") + .bind([field("request_id", "req-42")]) +``` + +In this example, subsequent writes automatically include `request_id`. + +#### When Prefer Shorter Chaining Syntax + +When a context-bound child logger should stay readable: +```moonbit +let worker = Logger::new(console_sink(), target="app") + .child("worker") + .bind([field("component", "worker")]) +``` + +In this example, `bind(...)` communicates intent without changing underlying behavior. + +### Error Case + +e.g.: +- If `fields` is empty, the returned logger remains valid and simply adds no extra metadata. + +- If duplicate field keys are bound, all copies are preserved for downstream formatting or inspection. + +### Notes + +1. Use `bind(...)` and `with_context_fields(...)` interchangeably; choose the one that reads better in context. + +2. This alias exists for ergonomics, not for different semantics. + diff --git a/docs/api/logger-debug.md b/docs/api/logger-debug.md new file mode 100644 index 0000000..465aa37 --- /dev/null +++ b/docs/api/logger-debug.md @@ -0,0 +1,77 @@ +--- +name: logger-debug +group: api +category: logging +update-time: 20260512 +description: Emit a debug-level record through the logger using the debug severity shortcut. +key-word: + - logger + - debug + - sync + - public +--- + +## Logger-debug + +Emit a debug-level record through the synchronous logger. This is the convenience wrapper for `log(Level::Debug, ...)`. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::debug(self : Logger[S], message : String, fields~ : Array[Field] = []) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the debug record. +- `message : String` - Debug message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. + +#### output + +- `Unit` - No return value. The record is handled according to the logger threshold and sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This helper delegates to `log(Level::Debug, ...)`. +- Debug logging is useful for development diagnostics that are usually too verbose for normal production visibility. +- Per-call target override is not exposed here; use `log(...)` for that level of control. +- All logger wrappers remain active exactly as they would for the base `log(...)` path. + +### How to Use + +Here are some specific examples provided. + +#### When Need Internal State Diagnostics + +When implementation details should be observable during debugging: +```moonbit +logger.debug("cache refreshed") +``` + +In this example, the call site signals a development-focused diagnostic event. + +#### When Attach Structured Debug Fields + +When a debug event should carry explicit state: +```moonbit +logger.debug("session loaded", fields=[field("user_id", "42")]) +``` + +In this example, the logger emits structured state without using the fully explicit `log(...)` form. + +### Error Case + +e.g.: +- If the logger minimum level is above `Debug`, the call returns without writing a record. + +- If the event needs a custom target override, use `log(...)` instead of this shortcut. + +### Notes + +1. Prefer this helper when debug intent is more readable than a raw `log(Level::Debug, ...)` call. + +2. Use `is_enabled(Level::Debug)` when building the debug payload is expensive. + diff --git a/docs/api/logger-error.md b/docs/api/logger-error.md new file mode 100644 index 0000000..bad64fb --- /dev/null +++ b/docs/api/logger-error.md @@ -0,0 +1,77 @@ +--- +name: logger-error +group: api +category: logging +update-time: 20260512 +description: Emit an error-level record through the logger using the highest built-in severity shortcut. +key-word: + - logger + - error + - sync + - public +--- + +## Logger-error + +Emit an error-level record through the synchronous logger. This is the convenience wrapper for `log(Level::Error, ...)`. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::error(self : Logger[S], message : String, fields~ : Array[Field] = []) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the error record. +- `message : String` - Error message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. + +#### output + +- `Unit` - No return value. The record is handled according to the logger threshold and sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This helper delegates to `log(Level::Error, ...)`. +- `Error` is the highest built-in severity in this sync logger API. +- Per-call target override is not exposed here; use `log(...)` when explicit target control is required. +- Sink composition, filtering, patching, and queue wrappers still apply normally. + +### How to Use + +Here are some specific examples provided. + +#### When Report A Failing Operation + +When an operation should emit a high-severity failure event: +```moonbit +logger.error("worker execution failed") +``` + +In this example, the call site clearly communicates failure severity. + +#### When Attach Structured Error Context + +When an error event should include diagnostic fields: +```moonbit +logger.error("dispatch failed", fields=[field("job_id", "42")]) +``` + +In this example, the record carries machine-readable context without dropping to the generic `log(...)` form. + +### Error Case + +e.g.: +- If the logger minimum level is above `Error`, the call still returns without writing, though this configuration is unusual. + +- If a target override is required, use `log(...)` instead of this severity shortcut. + +### Notes + +1. Use this helper for high-severity application failures. + +2. Emitting an error record is separate from throwing or handling program exceptions. + diff --git a/docs/api/logger-info.md b/docs/api/logger-info.md new file mode 100644 index 0000000..b6c5de1 --- /dev/null +++ b/docs/api/logger-info.md @@ -0,0 +1,77 @@ +--- +name: logger-info +group: api +category: logging +update-time: 20260512 +description: Emit an info-level record through the logger using the standard informational severity shortcut. +key-word: + - logger + - info + - sync + - public +--- + +## Logger-info + +Emit an info-level record through the synchronous logger. This is the convenience wrapper for `log(Level::Info, ...)`. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::info(self : Logger[S], message : String, fields~ : Array[Field] = []) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the info record. +- `message : String` - Informational message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. + +#### output + +- `Unit` - No return value. The record is handled according to the logger threshold and sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This helper delegates to `log(Level::Info, ...)`. +- `Info` is the default minimum logger threshold unless changed explicitly. +- Per-call target override is not exposed here; use `log(...)` if needed. +- Context fields, filters, patches, and queue wrappers behave exactly as they do for other write methods. + +### How to Use + +Here are some specific examples provided. + +#### When Emit Normal Application Events + +When a service should report standard lifecycle milestones: +```moonbit +logger.info("service started") +``` + +In this example, the log event uses the normal informational severity. + +#### When Attach Structured Informational Context + +When an info event should include machine-readable metadata: +```moonbit +logger.info("request completed", fields=[field("status", "200")]) +``` + +In this example, the event remains concise while still carrying useful fields. + +### Error Case + +e.g.: +- If the logger minimum level is above `Info`, the call returns without writing a record. + +- If the event needs an explicit alternate target, use `log(...)` instead of this shortcut. + +### Notes + +1. This is the most common convenience method for normal application events. + +2. Because `Info` is often the default threshold, this helper is a common baseline for examples and docs. + diff --git a/docs/api/logger-is-enabled.md b/docs/api/logger-is-enabled.md new file mode 100644 index 0000000..60aa816 --- /dev/null +++ b/docs/api/logger-is-enabled.md @@ -0,0 +1,80 @@ +--- +name: logger-is-enabled +group: api +category: logging +update-time: 20260512 +description: Check whether a logger would accept a record at a given level. +key-word: + - logger + - level + - enabled + - public +--- + +## Logger-is-enabled + +Check whether a logger would accept a record at the given level based on its current `min_level`. This API is useful for gating expensive work before building message text or fields. + +### Interface + +```moonbit +pub fn[S] Logger::is_enabled(self : Logger[S], level : Level) -> Bool {} +``` + +#### input + +- `self : Logger[S]` - Logger whose current minimum level should be checked. +- `level : Level` - Candidate severity to test. + +#### output + +- `Bool` - `true` when the level is enabled by the logger's current threshold. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This method delegates to `level.enabled(self.min_level)`. +- It only checks logger-level severity gating; it does not evaluate sink filters or patch logic. +- The result reflects the current logger value, so derived loggers with different `min_level` settings can return different answers. +- Use it when message construction or field gathering is expensive enough to justify a pre-check. + +### How to Use + +Here are some specific examples provided. + +#### When Avoid Expensive Debug Preparation + +When debug data should only be built if needed: +```moonbit +if logger.is_enabled(Level::Debug) { + logger.debug(build_debug_snapshot()) +} +``` + +In this example, expensive string construction is skipped unless debug logging is enabled. + +#### When Inspect Effective Logger Threshold + +When code should branch based on current logger behavior: +```moonbit +if logger.is_enabled(Level::Trace) { + logger.trace("trace path active") +} +``` + +In this example, the check mirrors the same severity gate used by `log(...)`. + +### Error Case + +e.g.: +- If `level` is below the current minimum threshold, the method returns `false`. + +- A `true` result does not guarantee final sink output if later filter logic rejects the record. + +### Notes + +1. This is a cheap severity check, not a full end-to-end delivery guarantee. + +2. Prefer using it only when precomputing the log payload is meaningfully expensive. + diff --git a/docs/api/logger-log.md b/docs/api/logger-log.md new file mode 100644 index 0000000..41958ca --- /dev/null +++ b/docs/api/logger-log.md @@ -0,0 +1,92 @@ +--- +name: logger-log +group: api +category: logging +update-time: 20260512 +description: Emit a record through the logger with an explicit level, message, optional fields, and optional target override. +key-word: + - logger + - log + - sync + - public +--- + +## Logger-log + +Emit a record through the synchronous logger with an explicit level and message. This is the core write API behind all level-specific convenience methods. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::log( + self : Logger[S], + level : Level, + message : String, + fields~ : Array[Field] = [], + target? : String = "", +) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the record. +- `level : Level` - Severity level for the record. +- `message : String` - Log message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. +- `target : String` - Optional per-call target override. + +#### output + +- `Unit` - No return value. The record is either skipped by level gating or written to the sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- The logger checks `is_enabled(level)` before building and writing the record. +- If `target` is empty, the logger's stored default target is used. +- If timestamping is enabled, `@env.now()` is captured and stored in the emitted record. +- Context, filter, patch, and queue wrappers act through the sink pipeline after the record is constructed. + +### How to Use + +Here are some specific examples provided. + +#### When Need Full Per-call Control + +When code should choose level, fields, and target explicitly: +```moonbit +logger.log( + Level::Info, + "worker started", + fields=[field("job", "sync")], + target="service.worker", +) +``` + +In this example, the call site controls every major record property. + +#### When Build Higher-level Wrappers + +When application code defines its own logging helpers: +```moonbit +fn log_retry(logger : Logger[ConsoleSink], attempt : Int) -> Unit { + logger.log(Level::Warn, "retry scheduled", fields=[field("attempt", attempt.to_string())]) +} +``` + +In this example, `log(...)` acts as the shared primitive under custom wrappers. + +### Error Case + +e.g.: +- If `level` is below the current minimum threshold, the method returns without writing a record. + +- If `target` is empty and the logger default target is also empty, the emitted record simply has no target label. + +### Notes + +1. Use this API when the call site needs full control instead of a fixed severity helper. + +2. This method is synchronous; any buffering behavior only comes from the wrapped sink type. + diff --git a/docs/api/logger-trace.md b/docs/api/logger-trace.md new file mode 100644 index 0000000..7ed611c --- /dev/null +++ b/docs/api/logger-trace.md @@ -0,0 +1,77 @@ +--- +name: logger-trace +group: api +category: logging +update-time: 20260512 +description: Emit a trace-level record through the logger using the lowest built-in severity shortcut. +key-word: + - logger + - trace + - sync + - public +--- + +## Logger-trace + +Emit a trace-level record through the synchronous logger. This is the convenience wrapper for `log(Level::Trace, ...)`. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::trace(self : Logger[S], message : String, fields~ : Array[Field] = []) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the trace record. +- `message : String` - Trace message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. + +#### output + +- `Unit` - No return value. The record is handled according to the logger threshold and sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This helper delegates to `log(Level::Trace, ...)`. +- Trace is the lowest built-in severity and is often disabled in production. +- Per-call target override is not exposed here; use `log(...)` if that is needed. +- Context, filtering, patching, and queue wrappers still apply through the logger sink chain. + +### How to Use + +Here are some specific examples provided. + +#### When Need Low-level Execution Tracing + +When fine-grained flow diagnostics are useful: +```moonbit +logger.trace("entered reconciliation step") +``` + +In this example, trace intent is explicit and concise. + +#### When Attach Structured Trace Context + +When a trace event should include fields: +```moonbit +logger.trace("cache probe", fields=[field("key", "user:42")]) +``` + +In this example, trace output stays lightweight while still carrying structured detail. + +### Error Case + +e.g.: +- If the logger minimum level is above `Trace`, the call returns without writing a record. + +- If a per-call target override is required, this helper is too narrow and `log(...)` should be used instead. + +### Notes + +1. Prefer this helper when trace intent is clearer than a raw `log(Level::Trace, ...)` call. + +2. Very verbose trace logging can become expensive even in a synchronous pipeline. + diff --git a/docs/api/logger-warn.md b/docs/api/logger-warn.md new file mode 100644 index 0000000..771cd3e --- /dev/null +++ b/docs/api/logger-warn.md @@ -0,0 +1,77 @@ +--- +name: logger-warn +group: api +category: logging +update-time: 20260512 +description: Emit a warn-level record through the logger using the warning severity shortcut. +key-word: + - logger + - warn + - sync + - public +--- + +## Logger-warn + +Emit a warn-level record through the synchronous logger. This is the convenience wrapper for `log(Level::Warn, ...)`. + +### Interface + +```moonbit +pub fn[S : Sink] Logger::warn(self : Logger[S], message : String, fields~ : Array[Field] = []) -> Unit {} +``` + +#### input + +- `self : Logger[S]` - Logger that should emit the warning record. +- `message : String` - Warning message text. +- `fields : Array[Field]` - Optional structured fields attached to the record. + +#### output + +- `Unit` - No return value. The record is handled according to the logger threshold and sink pipeline. + +### Explanation + +Detailed rules explaining key parameters and behaviors + +- This helper delegates to `log(Level::Warn, ...)`. +- Warning records are useful for abnormal but non-fatal conditions. +- Per-call target override is not exposed here; use `log(...)` when that is required. +- All logger wrappers still participate normally in the write path. + +### How to Use + +Here are some specific examples provided. + +#### When Signal A Recoverable Problem + +When an operation degraded but still continued: +```moonbit +logger.warn("cache miss ratio increased") +``` + +In this example, the event is elevated above normal information without being treated as a hard failure. + +#### When Attach Structured Warning Context + +When a warning should include machine-readable detail: +```moonbit +logger.warn("retry scheduled", fields=[field("attempt", "3")]) +``` + +In this example, the warning remains easy to filter and inspect later. + +### Error Case + +e.g.: +- If the logger minimum level is above `Warn`, the call returns without writing a record. + +- If a target override is needed at this call site, use `log(...)` instead of this shortcut. + +### Notes + +1. Use this helper for degraded or suspicious states that do not stop execution. + +2. Warning logs are often a practical signal threshold for alerting or separate routing. +