//! The per-process logger: std.log wired to the tagged kernel log ring.
//!
//! A program just calls `std.log.info("mounted {s}", .{path})` (or a scoped
//! logger); this backend formats the line into a fixed buffer and emits ONE
//! `debug_write` record carrying the level. The kernel stamps the record with
//! the sender's pid and task name (its binary path) — the process does NOT put
//! its own name in the payload; attribution is the kernel's, structural and
//! unforgeable. Serial shows the kernel-rendered `<path>: message` line, and
//! the logger service demultiplexes the ring into one file per process.
//!
//! Installed for every user binary by the root shim (library/runtime/root.zig)
//! via `std_options`; a program can override by declaring its own
//! `pub const std_options`.

const std = @import("std");
const system = @import("system.zig");

fn levelOf(comptime level: std.log.Level) system.KlogLevel {
    return switch (level) {
        .err => .err,
        .warn => .warn,
        .info => .info,
        .debug => .debug,
    };
}

pub fn logFn(
    comptime level: std.log.Level,
    comptime scope: @EnumLiteral(),
    comptime format: []const u8,
    args: anytype,
) void {
    // One record = one line = at most klog_maximum_message bytes of payload.
    // On overflow keep what fits and end with "~" so the record is still a
    // whole line (the kernel would split an embedded rest anyway).
    var buffer: [256]u8 = undefined;
    const prefix = if (scope == .default) "" else "(" ++ @tagName(scope) ++ ") ";
    const line = std.fmt.bufPrint(&buffer, prefix ++ format, args) catch truncated: {
        buffer[buffer.len - 1] = '~';
        break :truncated buffer[0..];
    };
    _ = system.writeRecord(levelOf(level), line);
}

/// The std.Options the root shim installs unless the program overrides it.
/// Debug level: filtering is the log *reader's* job here — the ring is cheap,
/// serial is a dev convenience, and the logger service keeps everything.
pub const default_options: std.Options = .{
    .log_level = .debug,
    .logFn = logFn,
};
