# logging — Configurable logging with compile-time level elision The logging system provides `debug`, `info`, `warn`, and `error` macros that wrap the built-in `log/*` functions. The level check happens at compile time — when `DEFT_LOG_LEVEL` filters out a level, the filtered call sites produce zero runtime code (not even a branch). ## Quick Start
require "deft/stdext/logging"
[info "app started"]
[debug [str "loading " $path " in " $duration "ms"]]
[warn "disk usage at " $pct "%"]
[error "failed to open " $path]
Use `require` (not `import`) so the macros — and the level check — are available at compile time. Control verbosity via the `DEFT_LOG_LEVEL` environment variable: ```sh DEFT_LOG_LEVEL=error deft # only errors DEFT_LOG_LEVEL=warn deft # warnings + errors DEFT_LOG_LEVEL=info deft # info + warnings + errors (default if unset) DEFT_LOG_LEVEL=debug deft # everything DEFT_LOG_LEVEL=none deft # all logging suppressed ```` The level is read once at compile time (when the module is `require`d), so changing `DEFT_LOG_LEVEL` requires a recompile for the filtering to shift. Each macro wraps its call in `[macro/compile-when ...]` — filtered-out call sites compile to a single `push_null`; the `if` branch and `log/*` call never enter the bytecode. ## Macros | Macro | Forwards to | Surfaces in error console | Included levels | |-------|-------------|---------------------------|-----------------| | `[debug ...]` | `[log/debug ...]` | No | debug only | | `[info ...]` | `[log/info ...]` | Yes | debug, info | | `[warn ...]` | `[log/warn ...]` | Yes | debug, info, warn | | `[error ...]` | `[log/error ...]` | Yes | debug, info, warn, error | All macros accept multiple arguments (variadic via `@args`), matching the built-in `[log/* ...]` functions:
[info "user " $name " logged in from " $ip]
Each macro automatically appends source location — file, line, and column of the call site — to every log message:
[info "server started"]
# /tmp/deft.log:  [1778100000000] INFO server started  (myapp.dft:15:1)
## Level hierarchy ``` debug (most verbose) ↓ info ↓ warn ↓ error (least verbose) ↓ off / none (all suppressed) ```` Setting `DEFT_LOG_LEVEL` to a level includes that level and everything above it in the hierarchy. For example, `DEFT_LOG_LEVEL=warn` passes warn and error but suppresses info and debug. ## Built-in fallback The underlying `[log/debug ...]`, `[log/info ...]`, `[log/warn ...]`, and `[log/error ...]` functions remain available and always write to `/tmp/deft.log`. They are not affected by `DEFT_LOG_LEVEL` — only the macros check the level. Use the built-ins when you need guaranteed logging that bypasses the filter. ## Implementation The macros are defined in `stdext/logging.dft`. `require` runs the module at compile time, which sets `log-level` from the environment and registers the macros. Each macro wraps its `log/*` call in `[macro/compile-when ...]` — the condition (`[in? @{...} $log-level]`) is evaluated during compilation of each call site, so filtered levels produce no runtime code.
def log-level ([os/env "DEFT_LOG_LEVEL"] or "debug")

defmacro info {|@args|
    [macro/compile-when [in? @{"debug" "info"} $log-level]
        [log/info [macro/splice $args] [str " (" [__FILE__] ":" [__LINE__] ":" [__COL__] ")"]]]
}
See macro/compile-when for the full conditional-elision mechanism. ## See Also `log/debug`, `log/info`, `log/warn`, `log/error`, `env`, `in?`