Skip to contents

Wrap a script or pipeline's top-level call in with_logging() so an uncaught error leaves a clean, correctly-colored tree instead of dimmed "interrupted" steps. On error, every currently open step is marked failed, the error is logged as a leaf line, then rethrown – with_logging() never silently swallows errors. It also prints a "Run complete" / "Run failed" summary line with elapsed time.

Usage

with_logging(expr, summary = TRUE, global = FALSE, warnings = FALSE)

Arguments

expr

Code to run. Omitted when global = TRUE.

summary

Print an end-of-run summary line? Default TRUE. In global mode only the "Run failed" line is printed (on an uncaught error); there is no frame exit to hang a "Run complete" line on.

global

If TRUE, do not wrap an expression; instead install a session-persistent global error handler for use at the top level of a script. On an error that reaches top level unhandled while logtree steps are open, it marks those steps failed and logs the error message as a leaf – the same result as the block form, but without wrapping the body. It fires only for genuinely uncaught top-level errors (an inner tryCatch() that catches first pre-empts it) and only when steps are open. The handler persists until logtree_reset(). Must be called from a clean top level – the first line of a script: calling it where condition handlers are active (inside tryCatch(), or a function running under one) errors, by design. Requires R (>= 4.0).

warnings

Route R's own conditions into the tree as leaf lines? FALSE (the default) leaves warning() and message() exactly as they are. TRUE routes both; a subset such as "warning" or "message" routes only those.

Two consequences to weigh before switching it on:

  • Routed conditions are muffled. A routed warning() becomes a leaf and stops there: it no longer reaches warnings(), the caller's own handlers, or stderr. That is the point – one record of the run rather than two halves – but it means the tree is now the only place that warning appears.

  • A routed warning elevates its step, exactly as log_warn() does. So wrapping third-party code that warns freely will turn the enclosing steps yellow, which may be more honesty than you wanted.

In global mode the routing applies only while logtree steps are open, so a session-persistent handler cannot swallow warnings from unrelated code.

Value

In block mode, the value of expr, invisibly. In global mode, NULL, invisibly.

Details

Note: expr is lazily evaluated, so log_step() calls written inside the { ... } block close when the function lexically enclosing that block returns – not necessarily when with_logging() itself returns. Use with_logging({ ... }) as a function's entire body to keep these in sync; if other code runs after the call in the same function, steps opened inside the block stay open until that function returns.

The global = TRUE form is meant for the top level of a script, where there is no frame to wrap. It is not shown in the examples below because it installs a session-persistent handler and is only meaningful for an error that reaches top level:

with_logging(global = TRUE)
log_open("Load data")
stop("EOF")   # marks the open step failed + logs "EOF" before R exits

warnings = TRUE additionally routes R's own conditions into the tree: a warning() raised by wrapped code becomes a log_warn() leaf and a message() becomes a log_info() leaf, in place rather than on stderr, so the tree is a complete record of the run rather than half of one. It is opt-in because routing means muffling – see the argument's own documentation below for what that costs.

Examples

logtree_reset()
with_logging({
  log_step("Step one")
  log_success("done")
})
#>  Step one
#> ├─  done
#>  Run complete in 0.00s
#> └─  Done  0.00s

# R's own conditions routed into the tree instead of onto stderr.
logtree_reset()
with_logging({
  log_step("Load data")
  warning("3 rows coerced to NA")
  message("using cached manifest")
}, warnings = TRUE)
#>  Load data
#> ├─  3 rows coerced to NA
#> ├─  using cached manifest
#>  Run complete in 0.01s
#> └─  Done  0.01s