# 日志 日志记录有两个层次。裸 `log` 动词是常开的磁盘日志器:它将格式化后的值追加到 `<tmp-dir>/deft.log`,并绕过所有宿主级重定向(TUI 错误控制台、echo 捕获)。在其之上,分级的 `log/debug`、`log/info`、`log/warn` 和 `log/error` 函数为每条记录打标签并送入工作区错误控制台,而 `deft/stdext/logging` 中的 `[debug ...]` / `[info ...]` / `[warn ...]` / `[error ...]` 宏在编译期增加级别过滤。除宏之外的所有内容都无需导入即可使用。 ## 函数 | 函数 | 用途 | |---|---| | `log v ...` | 将值追加到 `<tmp-dir>/deft.log`,绕过捕获和 TUI 重定向 | | `log/debug v ...` | `DEBUG` 记录——仅日志文件,不进入错误控制台 | | `log/info v ...` | `INFO` 记录——日志文件和错误控制台 | | `log/warn v ...` | `WARN` 记录——日志文件和错误控制台 | | `log/error v ...` | `ERROR` 记录——日志文件和错误控制台 | 说明: - `<tmp-dir>` 是每进程临时目录(`[fs/tmp-dir]`,例如 `/tmp/deft-12345`)。裸 `log` 以空格分隔写入值并加换行,没有级别或时间戳;`log/*` 函数会加上前缀 `[<epoch-ms>] LEVEL `,且无论宿主如何,每次调用写一行。 - 在 TUI 宿主中,`log/info`、`log/warn` 和 `log/error` 也会出现在工作区错误控制台;`log/debug` 只留在文件中。在脚本二进制中,控制台报告器是空操作,因此所有级别只写入磁盘。 - `log/*` 函数不做级别过滤:它们总是写入。过滤位于 `deft/stdext/logging` 的宏中,通过 `require` 加载——必须是 `require`,而不是 `import`,这样宏在编译期可用。每个宏将调用位置以 `(file:line:col)` 追加,并将其 `log/*` 调用包裹在 `[macro/compile-when ...]` 中。 - `DEFT_LOG_LEVEL` 在日志模块加载时读取。被过滤的调用位置完全不产生运行时代码。可接受的值有 `debug`(默认)、`info`、`warn`、`error` 以及 `off` / `none`;更改变量需要重新编译,过滤才会改变。 ## 示例
require "deft/stdext/logging"

[debug "loading" "/etc/app.conf"]        # file only
[info "server started on port" 8080]     # file + error console
[warn "disk usage at" 91 "%"]
[error "failed to open" "/etc/missing"]

# Built-ins ignore DEFT_LOG_LEVEL and always write, with their own tag:
[log/info "this still lands in deft.log"]
[log "and so does this"]                 # bare log: no level, no console
### 检查日志文件
set state %{ :user "alice" :tries 2 }
[log "state snapshot" $state]
[log %{ :event :sync :ok true }]

set path [fs/join [fs/tmp-dir] "deft.log"]
echo $path
echo [unwrap [fs/read $path]]
当 `DEFT_LOG_LEVEL=warn` 时,上面的 `[info ...]` 和 `[debug ...]` 调用位置编译为空,而 `[warn ...]` 和 `[error ...]` 保留;直接的 `log/*` 调用不受影响。 ## 另见 - IO — 通道、`echo` 和裸 `log` 动词 - 文件系统 — 回读日志文件 - 调试服务器 — 运行时错误报告